数码管模块化显示电子万年历.docx
《数码管模块化显示电子万年历.docx》由会员分享,可在线阅读,更多相关《数码管模块化显示电子万年历.docx(15页珍藏版)》请在冰豆网上搜索。
数码管模块化显示电子万年历
数码管显示模块化显示电子万年历
数码管共阳极7407驱动共阴极max7221/7419驱动
Ds1302实时时间显示
Ds18b20温度显示芯片
/*delay.h*/#ifndef_DELAY_H#define_DELAY_H_
#defineuintunsignedint
#defineucharunsignedchar
/*delay.c*/
#include"delay.h"voiddelay(uintxms)
uinti;
ucharj;
for(i=xms;i>0;i--)for(j=110;j>0;j--);
voiddelayms(uintxms)//毫秒级别延时
while(xms--);
/*ds1302.h*/#ifndef_DS1302_H_
#define_DS1302_H_
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitIO=P1A0;〃ds1302跟单片机接口
sbitSCLK二PHI;
sbitRST=P1A2;
externunsignedchardatetime[7];//存储获得的时间值
externvoidgettime();//读取时间值函数
#endif
/*ds1302.c*/
#include
#include"ds1302.h"
uchardatetime[7]={0,0,0,0,0,0,0};//用来接收获得的时间值
voidwrite_a_byte_to_ds1302(ucharX)
uchari;
for(i=0;i<8;i++)
IO=X&0X01;
SCLK=1;
SCLK=0;
X>>=1;
ucharget_a_byte_from_ds1302()
uchari,b=0x00;
for(i=0;i<8;i++)
b|=_crol_((uchar)IO,i);
SCLK=1;
SCLK=0;
//returnb/16*10+b%16;II返回的BCD码转换为十进制
return(b>>4)*10+(b&0x0f);//注意运算的优先级
ucharread_data(ucharadd)
uchardat;
RST=0;
SCLK=0;
RST=1;
write_a_byte_to_ds1302(add);
dat=get_a_byte_from_ds1302();
SCLK=1;
RST=0;
returndat;
voidgettime()//ds1302读取当前时间存储在datetime中
uchari,add=0x81;
for(i=0;i<7;i++)
datetime[i]=read_data(add);
add+=2;
/*max7221.h*/
#ifndef_MAX7221_H_//注:
Max7221只能用来驱动共阴数码管,对共阳
的没效
#define_MAX7221_H_
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitDIN=P2A0;//max7221与单片机接口DIN..CSB..CLK..
sbitCSB=P2A1;
sbitCLK=P2A2;
sbitDIN1=P2A3;
sbitCSB1=P2A4;
sbitCLK1=P2A5;
externvoidwrite(unsignedcharaddr,unsignedchardat);
//max7221写数据,转换数据函数,num的值为1,或者2,当num为1时,片选的是第一块Max7221,同理亦然。
externvoidwrite1(ucharaddr,uchardat);
externvoidinit();//max7221初始化
externvoidinit1();
#endif
/*max7221.c*/#include"max7221.h"
#include
voidwrite(ucharaddr,uchardat)//写数据,写地址函数uchari;
CSB=0;
for(i=0;i<8;i++)
CLK=0;
addr<<=1;
DIN=CY;
CLK=1;
_nop_();
_nop_();
CLK=0;
for(i=0;i<8;i++)
CLK=0;
dat<<=1;
DIN=CY;
CLK=1;
_nop_();
_nop_();
CLK=0;
CSB=1;
voidwrite1(ucharaddr,uchardat)uchari;
CSB1=0;
for(i=0;i<8;i++)
CLK1=0;
addr<<=1;
DIN1=CY;
CLK1=1;
_nop_();
_nop_();
CLK1=0;
for(i=0;i<8;i++)
CLK1=0;
dat<<=1;
DIN1=CY;
CLK1=1;
_nop_();
_nop_();
CLK1=0;
CSB1=1;
voidinit()
write(0x09,0xff);//
编码模式地址0x09,0x00-0xff,为1的则位
选通
write(0x0a,0x07);//
亮度地址0x0a,0x00-0x0f,0x0f时最亮
write(0x0b,0x07);//
扫描数码管个数地址0x0c,最多扫描8只数码
管
write(0x0c,0x01);//
工作模式地址OxOc0x00:
关闭;0x01:
正常
voidinit1()
write1(0x09,0xff);
write1(0x0a,0x07);
write1(0x0b,0x07);
write1(0x0c,0x01);
/*ds18b20.h*/
#ifndef_DS18B20_H
#define_DS18B20_H
#include
#include"delay.h"
#include
#defineNOP(){_nop_(),_nop_(),_nop_(),_nop_()}
sbitDQ=P1A3;//DS18B20
控制线,单线模式。
externbitng;//正负数标志位,ng=0,为正数,反之为负数,正
数负数的处理方法不同,
externbitDS18B20_IS_OK;
//为1时表示当前读取温度正常,否则第7页
读取失败。
#endif
/*ds18b20.c*/#include"ds18b20.h"
//温度字符
ucharcodeTemperature_Char[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};
//温度小数对照表
ucharcodedf_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
ucharCurrentT=0;//当前读取的温度整数部分
ucharTemp_Value[]={0x00,0x00};//从DS18B20读取的温度值
bitng=0;//正负数标志位,ng=0,为正数,反之为负数,正
数负数的处理方法不同,
bitDS18B20_IS_OK=1;//为1时表示当前读取温度正常,否则读取失
败。
ucharDisplay_Digit[4]={0,0,0,0};//读取的温度值转换后存在这个数组中
//初始化DS18B20
ucharInit_DS18B20()
ucharstatus;
DQ=1;delayms(8);DQ=0;delayms(90);DQ=1;delayms(8);
status=DQ;delayms(100);
DQ=1;
returnstatus;
//读一字节
ucharReadOneByte()
uchari,dat=0;
DQ=1;_nop_();
for(i=0;i<8;i++)
DQ=0;dat>>=1;DQ=1;_nop_();_nop_();
if(DQ)dat|=0x80;
delayms(30);
DQ=1;
returndat;
//写一字节
voidWriteOneByte(uchardat)
uchari;
for(i=0;i<8;i++)
DQ=0;DQ=dat&0x01;delayms(5);DQ=1;dat>>=1;
//读取温度值
voidRead_Temperature()
if(Init_DS18B20()==1
DS18B20_IS_OK=0;else
)//DS18B20故障
WriteOneByte(0xCC);//
WriteOneByte(0x44);//
Init_DS18B20();
WriteOneByte(0xCC);//
WriteOneByte(0xBE);//
跳过序列号
启动温度转换
跳过序列号读取温度寄存器
Temp_Value[0]=ReadOneByte();//
温度低8位
Temp_Value[1]=ReadOneByte();//
温度高8位
DS18B20_IS_OK=1;
//对读取的温度值进行判断,处理,负数的情况,整数情况
voidProcess_Temperature()
//uchari;
//延时值与负数标识
//ucharng=0;
//高5位全为1(0)则为负数,为负数时取反加1,并设置负数标识
if((Temp_Value[1]&0xF8)==0xF8)
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00)Temp_Value[1]++;
//负数标识置1ng=1;
else
ng=0;
//查表得到温度小数部分
Display_Digit[0]=df_Table[Temp_Value[0]&0x0F];
//获取温度整数部分(高字节中的第三位与低字节中的高四位,无符号)
CurrentT=((Temp_Value[0]&0xF0)>>4)|((Temp_Value[1]0x07)<<4);
//将整数部分分解为3位待显示数字
Display_Digit[3]=CurrentT/100;
Display_Digit[2]=CurrentT%100/10;
Display_Digit[1]=CurrentT%10;
/*main.c*/
#include"max7221.h"
#include"ds1302.h"
#include"ds18b20.h"
code
uchartable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管段码共阳极
uchardisbuff[]={0,0,10,0,0,10,0,0};//
第一个max7221显示缓存
uchardisbuff1[]={0,0,10,0,0,10,0,0};//第二个max7221显示缓存
voidinit_T()//定时器初始化
TMOD=0X01;
TH0=-5000/256;
TL0=-5000%256;
TR0=1;
ET0=1;
EA=1;
voidmain()//主函数
uchari;
init();
init1();//第一个max7221初始化
init_T();//第二个max7221初始化
Read_Temperature();//先读一遍当前温度
delayms(50000);//读取温度有一段时间,先让他等待一段时
间否则下一刻显示的将会是错误的温度
delayms(50000);
delayms(50000);
while
(1)
gettime();//读取当前时间值
disbuff[1]=datetime[2]%10;
disbuff[3]=datetime[1]/10;
disbuff[4]=datetime[1]%10;
disbuff[6]=datetime[0]/10;
disbuff[7]=datetime[0]%10;
disbuff1[0]=datetime[6]/10;
disbuff1[1]=datetime[6]%10;
disbuff1[3]=datetime[4]/10;
disbuff1[4]=datetime[4]%10;
disbuff1[6]=datetime[3]/10;
disbuff1[7]=datetime[3]%10;
for(i=0;i<8;i++)//第一个max7221显示
write(i+1,disbuff1[i]);
for(i=0;i<8;i++)//第二个max7221显示
write1(i+1,disbuff[i]);
Read_Temperature();//再次读取当前温度
if(DS18B20_IS_OK)//如果读取成功
Process_Temperature();//对温度进行处理,特别要考虑的
是负数的情况
delayms(50000);//延时等温度显示稳定了再
次读取,这个值要取适当,否则数码管显示会出现闪烁情况
delayms(50000);
delayms(50000);
voidTimer0_1()interrupt1//为了避免温度显示在数码管上出
现闪屏的情况,这里使用定时器来显示当前温度。
TH0=-3000/256;
//这个数值要足够的小,这样扫描次数才会更多,
staticnum=0;
显示才会更稳定
TL0=-3000%256;
P3=0x00;//每次进来时候要让位码清空,也叫做消影
switch(num)//通过一个Switch语句来实现对数码管的扫
case0:
//在数码管上显示当前温度
值
P0=table[Display_Digit[0]];
P3=0x20>>0;
break;
case1:
P0=table[Display_Digit[1]]&0x7f;
要&0x7f
//小数后面的一位
//有小数点的位
P3=0x20>>1;
break;
case2:
//小数位,个为
//十位
if(Display_Digit[2]==0)
if(Display_Digit[3]==0)
//若十位为零
且百位也为零,则都显示十位为空P0=0xff;
P0=0xff;
else
P0=table[Display_Digit[2]];
显示当前十位的值
P3=0x20>>2;
break;
case3:
if(Display_Digit[3]==0)
零,则不显示,
P0=0xff;
else
P0=table[Display_Digit[3]];
P3=0x20>>3;
break;
case4:
//显示口
P0=~0x63;
P3=0x80;
break;
case5:
//固定显示C
//否则,正常
//若百位为
//否则正常显示
P0=~0x39;
P3=0x40;
break;
case6:
//对负数的处理
if(ng==1)//若ng=1,表示当前表示当前获得的温度值为负数,
if(Display_Digit[3]==0)//因为考虑到温度为负数的时候最小值为-55.0所以,只可能在十位,和百位这两个位置可能出现负号
if(Display_Digit[2]==0)//百位和十位都为零,则,在十位的位置添加一个负号,P0=0xbf,
P0=0xbf;
P3=0x08;
else//否则直接在百位的位置添加一个负号、
P0=0xbf;
P3=0x04;
break;
num=(num+1)%7;//num值不断在0-6直接循环希望以上资料对你有所帮助,附励志名言3条:
1、生命对某些人来说是美丽的,这些人的一生都为某个目标而奋斗。
2、推销产品要针对顾客的心,不要针对顾客的头。
3、不同的信念,决定不同的命运。
第17页