|
上周做的,这个是用protues软件的仿真的主程序如下
//-------------------------- main.c ------------------------
// 名称: 用DS1302及DS18B20+MAX6951设计的多功能电子日历牌
//----------------------------------------------------------
// 说明: 本例所有分立式数码管全部用MAX6951驱动,电路中使用了
// 时钟芯片DS1302与温度传感器DS18B20,实现了含温度显示
// 的多功能电子日历牌设计,其中的调节功能由读者自行完成.
- #include <xc.h>
- #include <stdio.h>
- #include "DS1302.h"
- #include "DS18B20.h"
- #define INT8 signed char
- #define INT8U unsigned char
- #define INT16U unsigned int
- //MAX695X引脚定义
- #define DIN PORTCbits.RC0 //数据线
- #define CLK PORTCbits.RC1 //时钟线
- #define CS0 2 //YYYY-MM-DD驱动器片选线
- #define CS1 3 //HH-MM-SS W驱动器片选线
- #define CS2 4 //温度数码管驱动器片选线
- //秒闪烁LED控制
- #define LED_BLINK PORTCbits.RC7
- //MAX6951片选控制端口
- #define CS_PORT PORTC
- //日期显示缓冲,格式:YYYY-MM-DD(全解码,直接发送)
- INT8U Date_Buff[] = {2,0,0,0,0,0,0,0};
- //时间及星期显示缓冲,格式:HH-MM-SS W(全解码,直接发送)
- INT8U Time_w_Buff[] = {0,0,0,0,0,0,0};
- //温度显示缓冲:XXX.X℃ ~ -XX.X℃,(范围:125℃~-55℃)
- //(全部不解码,发送段码)
- //缓冲最后两位固定为"℃"中的度及C的段码
- INT8U Temp_Buff[] = {0x00,0x00,0x00,0x00,0x63,0x4E};
- //在非解码模式下MAX6950/1对应的段码表
- //此表不同于直接驱动时所使用的段码表
- //原来的各段顺序是: DP,G,F,E,D,C,B,A
- //MAX6950/1的驱动顺序是:DP,A,B,C,D,E,F,G
- //除小数点位未改变外,其他位是逆向排列的.
- const INT8U SEGCODE_695X[] =
- { 0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70, //0~7
- 0x7F,0x7B,0x77,0x1F,0x4E,0x3D,0x4F,0x47, //8~F
- };
- #define NEG_SEGCODE 0x01 //负数符号段码"-"
- #define BLK_SEGCODE 0x00 //黑屏段码
- extern volatile INT8U DateTime[];
- //----------------------------------------------------------
- // 向MAX695X写数据
- //----------------------------------------------------------
- void Write(INT8U Addr,INT8U Dat,INT8U CS_NO)
- {
- INT8U i;
- CS_PORT &= ~(1<<CS_NO);
- for(i = 0; i < 8; i++) //串行写入8位地址Addr
- { CLK = 0;
- if (Addr & 0x80) DIN = 1; else DIN = 0;
- CLK = 1; __delay_us(20);//时钟上升沿移入数据
- Addr <<= 1;
- }
- for(i = 0; i < 8; i++) //串行写入8位数据Dat
- { CLK = 0;
- if (Dat & 0x80) DIN = 1; else DIN = 0;
- CLK = 1; __delay_us(20);//时钟上升沿移入数据
- Dat <<= 1;
- }
- CS_PORT |= (1<<CS_NO);
- }
- //----------------------------------------------------------
- // MAX695X初始化
- //----------------------------------------------------------
- void Init_MAX695X()
- {
- //设置亮度:中等亮度/扫描所有的0~7只数码管/非关断0x01;关断:0x00
- Write(0x02,0x07,CS0);Write(0x03,0x07,CS0); Write(0x04,0x01,CS0);
- Write(0x02,0x07,CS1);Write(0x03,0x07,CS1); Write(0x04,0x01,CS1);
- Write(0x02,0x07,CS2);Write(0x03,0x07,CS2); Write(0x04,0x01,CS2);
- }
- //----------------------------------------------------------
- // 将两位整数分解为两个数位
- //----------------------------------------------------------
- void DEC_TO_2DIGIT(INT8U d, INT8U *a1, INT8U *b1)
- {
- *a1 = 0; *b1 = 0;
- while (d >= 10) { d -= 10; ++*a1; }
- *b1 = d;
- }
- //----------------------------------------------------------
- // 读取并显示温度
- //----------------------------------------------------------
- void Read_and_Show_Temperature()
- {
- INT8U i; char t[4];
- INT8 _temp_sign; //温度符号
- INT8U _temp_int, _temp_df; //温度整数部分与小数部分
- if (Read_Temperature() != 1) return; //读取温度
- //将两字节温度数据转换为符号,整数及小数部分
- Temperature_Convert(&_temp_sign,&_temp_int,&_temp_df);
- //将整数部分转换为字符串
- sprintf(t,"%3d",(int)_temp_int);
- //由字符串得到三个整数位的段码(空格转换为黑屏)
- if (t[0] == ' ') Temp_Buff[0] = BLK_SEGCODE;
- else Temp_Buff[0] = SEGCODE_695X[t[0] - '0'];
- if (t[1] == ' ') Temp_Buff[1] = BLK_SEGCODE;
- else Temp_Buff[1] = SEGCODE_695X[t[1] - '0'];
- Temp_Buff[2] = SEGCODE_695X[t[2] - '0'] | 0x80; //个位数加小数点
- Temp_Buff[3] = SEGCODE_695X[_temp_df]; //小数位的段码
- if (_temp_sign == -1) //处理符号位
- { if (Temp_Buff[1] == BLK_SEGCODE) Temp_Buff[1] = NEG_SEGCODE;
- else //此处的else不可省略
- if (Temp_Buff[0] == BLK_SEGCODE) Temp_Buff[0] = NEG_SEGCODE;
- }
- //显示温度:XXX.X℃~-XX.X℃(全部不解码)------------------------------
- Write(0x01,0B00000000,CS2);
- for(i = 0; i < 6; i++) Write(0x60 | i, Temp_Buff,CS2);
- __delay_ms(20);
- }
- //----------------------------------------------------------
- // 读取并显示当前日期时间
- //----------------------------------------------------------
- void Read_and_Show_DateTime()
- {
- INT8U i,a,b;
- getDateTime();//读取DS1302实时时钟
- //分解年月日
- DEC_TO_2DIGIT(DateTime[6],&a,&b);
- Date_Buff[2] = a; Date_Buff[3] = b;
- DEC_TO_2DIGIT(DateTime[4],&a,&b);
- Date_Buff[4] = a; Date_Buff[5] = b;
- DEC_TO_2DIGIT(DateTime[3],&a,&b);
- Date_Buff[6] = a; Date_Buff[7] = b;
- //分解时分秒,星期
- DEC_TO_2DIGIT(DateTime[2],&a,&b);
- Time_w_Buff[0] = a; Time_w_Buff[1] = b;
- DEC_TO_2DIGIT(DateTime[1],&a,&b);
- Time_w_Buff[2] = a; Time_w_Buff[3] = b;
- DEC_TO_2DIGIT(DateTime[0],&a,&b);
- Time_w_Buff[4] = a; Time_w_Buff[5] = b;
- Time_w_Buff[6] = DateTime[5] - 1;
- //遇到星期0时,用星期8表示,数码管上的8显示为“日”
- if (Time_w_Buff[6] == 0) Time_w_Buff[6] = 8;
- //显示年月日:YYYY-MM-DD(全解码,直接发送)------------------------
- Write(0x01,0B11111111,CS0);
- for(i = 0; i < 8; i++) Write(0x60 | i, Date_Buff, CS0);
- //显示时间及星期:HH-MM-SS W(全解码,直接发送)--------------------
- Write(0x01,0B11111111,CS1);
- for(i = 0; i < 7; i++) Write(0x60 | i, Time_w_Buff,CS1);
- }
- //----------------------------------------------------------
- // 主程序
- //----------------------------------------------------------
- void main()
- {
- T0CS = 0; //TMR0时钟选择:内部时钟
- PSA = 0; //前分频器分配给TMR0
- PS2 = 1; PS1 = 0; PS0 = 0; //32分频(OPTION低3位为100)
- TMR0 = (INT8U)(256 - _XTAL_FREQ/4/32*0.005); //5ms定时初值
- T0IF = 0; //清TMR0中断标志
- GIE = 1; //开全局中断
- T0IE = 1; //使能TMR0溢出中断
- TRISC = 0x00; PORTC = 0xFF; //MAX6951控制端口
- TRISD2 = TRISD3 = 0; //DS1302 SCLK,RST输出
- Init_MAX695X(); //初始化三片695X
- Read_Temperature(); //预读温度
- //初始化DS1302,并配置使能DS1302的点滴式充电器
- init_DS1302(); __delay_ms(1000); //等待1秒
- while (1)
- {
- Read_and_Show_DateTime(); //读取并显示日期时间
- Read_and_Show_Temperature(); //读取并显示温度
- }
- }
- //----------------------------------------------------------
- // TMR0溢出中断控制秒闪烁功能
- //----------------------------------------------------------
- void interrupt TMR0_OVR_Interrupt()
- {
- static INT8U pre_second = 0;
- static INT8U T_Count = 0; //用于延时累加的变量
- if (T0IF)
- { T0IF = 0; //软件清零
- TMR0 = (INT8U)(256 - _XTAL_FREQ/4/32*0.005); //5ms定时初值
- if (pre_second != Time_w_Buff[5]) //读到新的秒数
- { pre_second = Time_w_Buff[5]; //保存当前秒
- LED_BLINK = 0; //点亮LED
- T_Count = 0;
- }
- else
- { if ( ++T_Count != 100 ) return; //不到0.005*100=0.5s时返回
- T_Count = 0;
- LED_BLINK = 1; //0.5s后关LED
- }
- }
- }
复制代码
|
|