《单片机C语言模块化编程之数码管显示电子万年历篇.doc》由会员分享,可在线阅读,更多相关《单片机C语言模块化编程之数码管显示电子万年历篇.doc(60页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-date单片机C语言模块化编程之数码管显示电子万年历篇单片机C语言模块化编程之数码管显示电子万年历篇数码管显示模块化显示电子万年历数码管 共阳极7407驱动 共阴极max7221/7419驱动Ds1302 实时时间显示Ds18b20 温度显示芯片/*delay.h*/#ifndef _DELAY_H#define _DELAY_H_#define uint unsigned
2、int #define uchar unsigned char void delay(uint xms); /秒级延时void delayms(uint xms); /毫秒级延时,不可以更改,若更改,DS18B20将显示异常#endif/*delay.c*/#include delay.hvoid delay(uint xms)uint i;uchar j;for(i=xms;i0;i-)for(j=110;j0;j-);void delayms(uint xms) /毫秒级别延时while(xms-);/*ds1302.h*/#ifndef _DS1302_H_#define _DS1302
3、_H_#include #define uint unsigned int #define uchar unsigned charsbit IO=P10; /ds1302跟单片机接口sbit SCLK=P11;sbit RST=P12;extern unsigned char datetime7; /存储获得的时间值extern void gettime();/读取时间值函数#endif/*ds1302.c*/#include #include ds1302.h uchar datetime7=0,0,0,0,0,0,0; /用来接收获得的时间值 void write_a_byte_to_ds
4、1302(uchar X) uchar i; for(i=0;i=1; uchar get_a_byte_from_ds1302() uchar i,b=0x00; for(i=0;i4)*10+(b&0x0f); /注意运算的优先级 uchar read_data(uchar add) uchar dat; RST=0; SCLK=0; RST=1; write_a_byte_to_ds1302(add); dat=get_a_byte_from_ds1302(); SCLK=1; RST=0; return dat; void gettime() /ds1302读取当前时间存储在datet
5、ime中 uchar i,add=0x81; for(i=0;i7;i+) datetimei=read_data(add); add+=2; /*max7221.h*/#ifndef _MAX7221_H_ /注:Max7221只能用来驱动共阴数码管,对共阳的没效#define _MAX7221_H_#include #define uint unsigned int #define uchar unsigned charsbit DIN=P20;/max7221与单片机接口 DIN.CSB.CLK.sbit CSB=P21;sbit CLK=P22;sbit DIN1=P23;sbit C
6、SB1=P24;sbit CLK1=P25;extern void write(unsigned char addr , unsigned char dat);/max7221写数据,转换数据函数 ,num的值为1,或者2,当num为1时,片选的是第一块Max7221,同理亦然。extern void write1(uchar addr,uchar dat);extern void init(); /max7221初始化extern void init1();#endif/*max7221.c*/#include max7221.h#include void write(uchar addr,
7、uchar dat) /写数据,写地址函数uchar i;CSB=0;for(i=0;i8;i+)CLK=0;addr=1;DIN=CY;CLK=1;_nop_();_nop_();CLK=0;for(i=0;i8;i+)CLK=0;dat=1;DIN=CY;CLK=1;_nop_();_nop_();CLK=0;CSB=1;void write1(uchar addr,uchar dat)uchar i;CSB1=0;for(i=0;i8;i+)CLK1=0;addr=1;DIN1=CY;CLK1=1;_nop_();_nop_();CLK1=0;for(i=0;i8;i+)CLK1=0;d
8、at=1;DIN1=CY;CLK1=1;_nop_();_nop_();CLK1=0;CSB1=1;void init() write(0x09,0xff); /编码模式地址0x09 , 0x00-0xff,为1的则位选通write(0x0a,0x07); /亮度地址0x0a ,0x00-0x0f,0x0f时最亮write(0x0b,0x07); /扫描数码管个数地址0x0c,最多扫描8只数码管write(0x0c,0x01); /工作模式地址0x0c 0x00:关闭;0x01:正常void init1()write1(0x09,0xff);write1(0x0a,0x07);write1(0
9、x0b,0x07);write1(0x0c,0x01);/*ds18b20.h*/#ifndef _DS18B20_H#define _DS18B20_H#include #include delay.h#include #define NOP() _nop_(),_nop_(),_nop_(),_nop_()sbit DQ=P13; /DS18B20控制线,单线模式。extern bit ng; /正负数标志位,ng=0,为正数,反之为负数,正数负数的处理方法不同,extern bit DS18B20_IS_OK;/为1时表示当前读取温度正常,否则读取失败。extern uchar Disp
10、lay_Digit4; /读取的温度值转换后存在这个数组中extern void Read_Temperature(); /读取当前温度值extern void Process_Temperature(); /处理当前获得的温度值,正数,负数等。#endif/*ds18b20.c*/#include ds18b20.h/温度字符uchar code Temperature_Char8 = 0x0c,0x12,0x12,0x0c,0x00,0x00, 0x00,0x00;/温度小数对照表uchar code df_Table = 0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9 ;
11、uchar CurrentT = 0 ; /当前读取的温度整数部分uchar Temp_Value = 0x00,0x00; /从DS18B20读取的温度值bit ng=0; /正负数标志位,ng=0,为正数,反之为负数,正数负数的处理方法不同,bit DS18B20_IS_OK=1; /为1时表示当前读取温度正常,否则读取失败。uchar Display_Digit4=0,0,0,0; /读取的温度值转换后存在这个数组中/-/ 初始化DS18B20/-uchar Init_DS18B20() uchar status; DQ = 1; delayms(8); DQ = 0 ; delayms
12、(90); DQ = 1; delayms(8); status = DQ; delayms(100); DQ = 1; return status;/-/读一字节/-uchar ReadOneByte() uchar i, dat = 0; DQ = 1; _nop_(); for (i = 0; i = 1; DQ = 1; _nop_();_nop_(); if(DQ) dat |= 0x80; delayms(30); DQ = 1; return dat;/-/ 写一字节/-void WriteOneByte(uchar dat) uchar i ; for (i = 0; i =1
13、; /-/ 读取温度值/- void Read_Temperature() if( Init_DS18B20() = 1) /DS18B20故障 DS18B20_IS_OK = 0; else WriteOneByte(0xCC); /跳过序列号 WriteOneByte(0x44); /启动温度转换 Init_DS18B20(); WriteOneByte(0xCC); /跳过序列号 WriteOneByte(0xBE); /读取温度寄存器 Temp_Value0 = ReadOneByte(); /温度低8位 Temp_Value1 = ReadOneByte(); /温度高8位 DS18
14、B20_IS_OK = 1; /-/对读取的温度值进行判断,处理,负数的情况,整数情况/-void Process_Temperature() / uchar i; /延时值与负数标识/ uchar ng = 0; /高5位全为1(0)则为负数,为负数时取反加1,并设置负数标识 if ( (Temp_Value1 & 0xF8) = 0xF8) Temp_Value1 = Temp_Value1; Temp_Value0 = Temp_Value0 + 1; if (Temp_Value0 = 0x00) Temp_Value1+; /负数标识置1 ng = 1; else ng=0; /查表
15、得到温度小数部分 Display_Digit0 = df_Table Temp_Value0 & 0x0F ; /获取温度整数部分(高字节中的第三位与低字节中的高四位,无符号) CurrentT = (Temp_Value0 & 0xF0)4)|(Temp_Value1 & 0x07)4); /将整数部分分解为3位待显示数字 Display_Digit3 = CurrentT / 100; Display_Digit2 = CurrentT % 100 / 10; Display_Digit1 = CurrentT % 10; /*main.c*/#include max7221.h#incl
16、ude ds1302.h#include ds18b20.huchar code table=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; /数码管段码共阳极uchar disbuff=0,0,10,0,0,10,0,0; /第一个max7221显示缓存uchar disbuff1=0,0,10,0,0,10,0,0; /第二个max7221显示缓存void init_T() /定时器初始化TMOD=0X01;TH0=-5000/256;TL0=-5000%256;TR0=1;ET0=1;EA=1;void main() /主函数ucha
17、r i;init();init1(); /第一个max7221初始化init_T(); /第二个max7221初始化Read_Temperature(); /先读一遍当前温度delayms(50000); /读取温度有一段时间,先让他等待一段时间否则下一刻显示的将会是错误的温度delayms(50000);delayms(50000);while(1)gettime(); /读取当前时间值disbuff0=datetime2/10; /将获得的时间值分解出来disbuff1=datetime2%10;disbuff3=datetime1/10;disbuff4=datetime1%10;dis
18、buff6=datetime0/10;disbuff7=datetime0%10;disbuff10=datetime6/10;disbuff11=datetime6%10;disbuff13=datetime4/10;disbuff14=datetime4%10;disbuff16=datetime3/10;disbuff17=datetime3%10; for(i=0;i8;i+)/第一个max7221显示write(i+1,disbuff1i);for(i=0;i0;break;case 1: P0=tableDisplay_Digit1&0x7f;/有小数点的位要&0x7fP3=0x2
19、01; /小数位,个为break;case 2: /十位if(Display_Digit2=0)if(Display_Digit3=0)/若十位为零且百位也为零,则都显示十位为空P0=0xff;P0=0xff;elseP0=tableDisplay_Digit2; /否则,正常显示当前十位的值P3=0x202;break;case 3: if(Display_Digit3=0)/若百位为零,则不显示,P0=0xff;else/否则正常显示P0=tableDisplay_Digit3;P3=0x203;break;case 4: /显示口P0=0x63;P3=0x80;break;case 5: /固定显示CP0=0x39;P3=0x40;break;case 6: / 对负数的处理if(ng=1) /若ng=1,表示当前表示当前获得的温度值为负数,if(Display_Digit3=0) /因为考虑到温度为负数的时候最小值为-55.0所以,只可能在十位,和百位这两个位置可能出现负号if(Display_Digit2=0)/百位和十位都为零,则,在十位的位置添加一个负号,P0=0xbf,P0=0xbf;P3=0x08;else/否则直接在百位的位置添加一个负号、P0=0xbf;P3=0x04; break;num=(num+1)%7; /num值不断在0-6直接循环-