找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4327|回复: 1
收起左侧

用DS1302及DS18B20+MAX6951设计的多功能电子日历牌

[复制链接]
ID:152503 发表于 2016-12-6 10:26 | 显示全部楼层 |阅读模式
上周做的,这个是用protues软件的仿真的主程序如下
//-------------------------- main.c ------------------------
//  名称: 用DS1302及DS18B20+MAX6951设计的多功能电子日历牌
//----------------------------------------------------------
//  说明: 本例所有分立式数码管全部用MAX6951驱动,电路中使用了
//        时钟芯片DS1302与温度传感器DS18B20,实现了含温度显示
//        的多功能电子日历牌设计,其中的调节功能由读者自行完成.

  1. #include <xc.h>
  2. #include <stdio.h>
  3. #include "DS1302.h"
  4. #include "DS18B20.h"
  5. #define INT8    signed char
  6. #define INT8U   unsigned char
  7. #define INT16U  unsigned int
  8. //MAX695X引脚定义
  9. #define DIN  PORTCbits.RC0  //数据线
  10. #define CLK  PORTCbits.RC1  //时钟线
  11. #define CS0  2    //YYYY-MM-DD驱动器片选线
  12. #define CS1  3    //HH-MM-SS W驱动器片选线
  13. #define CS2  4    //温度数码管驱动器片选线
  14. //秒闪烁LED控制
  15. #define LED_BLINK   PORTCbits.RC7
  16. //MAX6951片选控制端口
  17. #define CS_PORT PORTC
  18. //日期显示缓冲,格式:YYYY-MM-DD(全解码,直接发送)
  19. INT8U Date_Buff[] = {2,0,0,0,0,0,0,0};
  20. //时间及星期显示缓冲,格式:HH-MM-SS W(全解码,直接发送)
  21. INT8U Time_w_Buff[] = {0,0,0,0,0,0,0};
  22. //温度显示缓冲:XXX.X℃ ~ -XX.X℃,(范围:125℃~-55℃)
  23. //(全部不解码,发送段码)
  24. //缓冲最后两位固定为"℃"中的度及C的段码
  25. INT8U Temp_Buff[] = {0x00,0x00,0x00,0x00,0x63,0x4E};
  26. //在非解码模式下MAX6950/1对应的段码表
  27. //此表不同于直接驱动时所使用的段码表
  28. //原来的各段顺序是:     DP,G,F,E,D,C,B,A
  29. //MAX6950/1的驱动顺序是:DP,A,B,C,D,E,F,G
  30. //除小数点位未改变外,其他位是逆向排列的.
  31. const INT8U SEGCODE_695X[] =
  32. { 0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70, //0~7
  33.   0x7F,0x7B,0x77,0x1F,0x4E,0x3D,0x4F,0x47, //8~F
  34. };
  35. #define NEG_SEGCODE 0x01    //负数符号段码"-"
  36. #define BLK_SEGCODE 0x00    //黑屏段码
  37. extern volatile INT8U DateTime[];
  38. //----------------------------------------------------------
  39. // 向MAX695X写数据
  40. //----------------------------------------------------------
  41. void Write(INT8U Addr,INT8U Dat,INT8U CS_NO)
  42. {
  43.     INT8U i;
  44.     CS_PORT &= ~(1<<CS_NO);
  45.     for(i = 0; i < 8; i++)    //串行写入8位地址Addr
  46.     {  CLK = 0;
  47.        if (Addr & 0x80) DIN = 1; else DIN = 0;
  48.        CLK = 1; __delay_us(20);//时钟上升沿移入数据
  49.        Addr <<= 1;
  50.     }
  51.     for(i = 0; i < 8; i++)    //串行写入8位数据Dat
  52.     {  CLK = 0;
  53.        if (Dat & 0x80)  DIN = 1; else DIN = 0;
  54.        CLK = 1; __delay_us(20);//时钟上升沿移入数据
  55.        Dat <<= 1;
  56.     }
  57.     CS_PORT |= (1<<CS_NO);
  58. }
  59. //----------------------------------------------------------
  60. // MAX695X初始化
  61. //----------------------------------------------------------
  62. void Init_MAX695X()
  63. {
  64.     //设置亮度:中等亮度/扫描所有的0~7只数码管/非关断0x01;关断:0x00
  65.     Write(0x02,0x07,CS0);Write(0x03,0x07,CS0); Write(0x04,0x01,CS0);
  66.     Write(0x02,0x07,CS1);Write(0x03,0x07,CS1); Write(0x04,0x01,CS1);
  67.     Write(0x02,0x07,CS2);Write(0x03,0x07,CS2); Write(0x04,0x01,CS2);
  68. }
  69. //----------------------------------------------------------
  70. // 将两位整数分解为两个数位
  71. //----------------------------------------------------------
  72. void DEC_TO_2DIGIT(INT8U d, INT8U *a1, INT8U *b1)
  73. {
  74.    *a1 = 0; *b1 = 0;
  75.    while (d >= 10) { d -= 10; ++*a1; }
  76.    *b1 = d;
  77. }   
  78. //----------------------------------------------------------
  79. // 读取并显示温度
  80. //----------------------------------------------------------
  81. void Read_and_Show_Temperature()
  82. {
  83.    INT8U i;  char t[4];
  84.    INT8  _temp_sign;               //温度符号
  85.    INT8U _temp_int, _temp_df;      //温度整数部分与小数部分
  86.    if (Read_Temperature() != 1) return;   //读取温度
  87.    //将两字节温度数据转换为符号,整数及小数部分
  88.    Temperature_Convert(&_temp_sign,&_temp_int,&_temp_df);
  89.    //将整数部分转换为字符串
  90.    sprintf(t,"%3d",(int)_temp_int);
  91.    //由字符串得到三个整数位的段码(空格转换为黑屏)
  92.    if (t[0] == ' ') Temp_Buff[0] = BLK_SEGCODE;
  93.    else             Temp_Buff[0] = SEGCODE_695X[t[0] - '0'];
  94.    if (t[1] == ' ') Temp_Buff[1] = BLK_SEGCODE;
  95.    else             Temp_Buff[1] = SEGCODE_695X[t[1] - '0'];
  96.    Temp_Buff[2] = SEGCODE_695X[t[2] - '0'] | 0x80; //个位数加小数点
  97.    Temp_Buff[3] = SEGCODE_695X[_temp_df];   //小数位的段码
  98.    if (_temp_sign == -1)    //处理符号位
  99.    {  if (Temp_Buff[1] == BLK_SEGCODE) Temp_Buff[1] = NEG_SEGCODE;
  100.       else //此处的else不可省略
  101.       if (Temp_Buff[0] == BLK_SEGCODE) Temp_Buff[0] = NEG_SEGCODE;
  102.    }
  103.    //显示温度:XXX.X℃~-XX.X℃(全部不解码)------------------------------
  104.    Write(0x01,0B00000000,CS2);
  105.    for(i = 0; i < 6; i++) Write(0x60 | i, Temp_Buff,CS2);
  106.    __delay_ms(20);
  107. }
  108. //----------------------------------------------------------
  109. // 读取并显示当前日期时间
  110. //----------------------------------------------------------
  111. void Read_and_Show_DateTime()
  112. {   
  113.     INT8U i,a,b;   
  114.     getDateTime();//读取DS1302实时时钟
  115.     //分解年月日
  116.     DEC_TO_2DIGIT(DateTime[6],&a,&b);
  117.     Date_Buff[2] = a; Date_Buff[3] = b;
  118.     DEC_TO_2DIGIT(DateTime[4],&a,&b);
  119.     Date_Buff[4] = a; Date_Buff[5] = b;
  120.     DEC_TO_2DIGIT(DateTime[3],&a,&b);
  121.     Date_Buff[6] = a; Date_Buff[7] = b;
  122.     //分解时分秒,星期
  123.     DEC_TO_2DIGIT(DateTime[2],&a,&b);
  124.     Time_w_Buff[0] = a; Time_w_Buff[1] = b;
  125.     DEC_TO_2DIGIT(DateTime[1],&a,&b);
  126.     Time_w_Buff[2] = a; Time_w_Buff[3] = b;
  127.     DEC_TO_2DIGIT(DateTime[0],&a,&b);
  128.     Time_w_Buff[4] = a; Time_w_Buff[5] = b;
  129.     Time_w_Buff[6] = DateTime[5] - 1;
  130.     //遇到星期0时,用星期8表示,数码管上的8显示为“日”
  131.     if (Time_w_Buff[6] == 0) Time_w_Buff[6] = 8;
  132.     //显示年月日:YYYY-MM-DD(全解码,直接发送)------------------------
  133.     Write(0x01,0B11111111,CS0);
  134.     for(i = 0; i < 8; i++) Write(0x60 | i, Date_Buff, CS0);
  135.     //显示时间及星期:HH-MM-SS W(全解码,直接发送)--------------------
  136.     Write(0x01,0B11111111,CS1);
  137.     for(i = 0; i < 7; i++) Write(0x60 | i, Time_w_Buff,CS1);
  138. }
  139. //----------------------------------------------------------
  140. // 主程序
  141. //----------------------------------------------------------
  142. void main()
  143. {
  144.     T0CS = 0;                               //TMR0时钟选择:内部时钟
  145.     PSA = 0;                                //前分频器分配给TMR0
  146.     PS2 = 1; PS1 = 0; PS0 = 0;              //32分频(OPTION低3位为100)
  147.     TMR0 = (INT8U)(256 - _XTAL_FREQ/4/32*0.005);  //5ms定时初值
  148.     T0IF = 0;                               //清TMR0中断标志
  149.     GIE = 1;                                //开全局中断
  150.     T0IE = 1;                               //使能TMR0溢出中断
  151.     TRISC = 0x00; PORTC = 0xFF;             //MAX6951控制端口
  152.     TRISD2 = TRISD3 = 0;                    //DS1302 SCLK,RST输出
  153.     Init_MAX695X();                         //初始化三片695X
  154.     Read_Temperature();                     //预读温度
  155.     //初始化DS1302,并配置使能DS1302的点滴式充电器
  156.     init_DS1302(); __delay_ms(1000);        //等待1秒
  157.     while (1)
  158.     {
  159.        Read_and_Show_DateTime();            //读取并显示日期时间
  160.        Read_and_Show_Temperature();         //读取并显示温度
  161.     }
  162. }
  163. //----------------------------------------------------------
  164. // TMR0溢出中断控制秒闪烁功能
  165. //----------------------------------------------------------
  166. void interrupt TMR0_OVR_Interrupt()
  167. {
  168.    static INT8U pre_second = 0;
  169.    static INT8U T_Count = 0;               //用于延时累加的变量
  170.    if (T0IF)
  171.    {   T0IF = 0;                            //软件清零
  172.        TMR0 = (INT8U)(256 - _XTAL_FREQ/4/32*0.005); //5ms定时初值
  173.        if (pre_second != Time_w_Buff[5])    //读到新的秒数
  174.        {   pre_second = Time_w_Buff[5];     //保存当前秒
  175.            LED_BLINK = 0;                   //点亮LED
  176.            T_Count = 0;
  177.        }
  178.        else
  179.        {   if ( ++T_Count != 100 ) return; //不到0.005*100=0.5s时返回
  180.            T_Count = 0;
  181.            LED_BLINK = 1;                   //0.5s后关LED
  182.        }
  183.    }
  184. }
复制代码


回复

使用道具 举报

ID:1 发表于 2016-12-7 04:45 | 显示全部楼层
很好,谢谢分享,楼主能上传一下仿真和程序的压缩包供大家学习吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表