资讯详情

时钟及温度用74hc164+74ls145数码管显示单片机程序

下面是实物图: 电路图很简单我就不画了 用74hc164串行转并行芯片+74ls145这2个芯片驱动一个负责段选一个负责位选,具体看程序顶部的引脚定义.完整的keil工程文件下载地址: http://www.51hei.com/f/164smg.rar 下面是程序源码.

#include<reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit iicclk=P1^0;////总线存储时钟引脚定义 sbit iicdat=P1^1;////总线存储数据引脚定义 sbit hc164dat=P1^2;//段显串行数据引脚定义 sbit hc164clk=P1^3;//段显串行时钟引脚定义 /*sbit hc164clr=P1^4;*///段显芯片清零引脚,低电平时,全部输出引脚清零,即低电平 sbit ls145p0=P1^5;///位选译码芯片P0 sbit ls145p1=P1^6;///位选译码芯片P1 sbit ls145p2=P1^7;///位选译码芯片P2 sbit ls145p3=P3^7;///位选译码芯片P2,用于在74HC164移入数据时P0~P3全置高,关闭所有数码管 sbit DS1820DQ=P0^0; sbit ADD=P0^4;///////加一 sbit MINUS=P0^5;/////减一 sbit ER=P0^6;/////确定 sbit SET=P0^7;///////设定键 uchar code tabledu[]={0xed,0x21,0x8f,0xab,0x63,0xea,0xee,0xa1,0xef,0xeb,0x0};//垃圾显示板0~~9段显数据 uchar code tablewe[]={0x0,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0,0x10};//位选编码,P2口高八位产生编码值,0x10为关闭所有位选 char dateshu[8]; uchar tim,sec,ming,mins,hourg,hours,min,hour,setflag,seta,dqflag,temperl,temperh,dat; void delay1ms(uint x)//0.5毫秒延时函数 { uint y,z; for(y=x;y>0;y--) for(z=60;z>0;z--); } void delayns() { _nop_(); _nop_(); } void delay10us(uchar z)//z为3是定时10微秒 { while(z) z--; } void DelayX0us(uchar n) { while (n--) { _nop_(); _nop_(); } } void dqrsr()//1820初始化函数 { dqflag=0; DS1820DQ=1; delayns(); DS1820DQ=0; DelayX0us(48);//时序延时500US DS1820DQ=1; delay10us(6);//时序延时20us if(DS1820DQ==0)dqflag=1; DelayX0us(42); } void dqwrite(uchar a) { uchar i; dqflag=0; DS1820DQ=1; //to释放总线 delayns();//时序延时 for(i=8;i>0;i--)//写一个字节的数据 { DS1820DQ=0;//总线置低 _nop_(); _nop_(); a=a>>1;//右移时,逸出位保存到CY中 DS1820DQ=CY;//发送送据 DelayX0us(6);//延时70us DS1820DQ=1; //to释放总线 } } uchar dqread(void)//1820读函数 { uchar i; DS1820DQ=1; //to释放总线 delayns();//时序延时 for(i=0;i<8;i++) { dat>>=1; DS1820DQ=0; _nop_(); _nop_(); DS1820DQ=1; delayns(); if(DS1820DQ)dat|=0x80; //如果读回的数据为1则作与处理移入DAT变量 DelayX0us(6);//延时70us } return dat; } void write164(uchar x) { uchar y; hc164clk=0;//时钟置低 _nop_(); _nop_(); for(y=0;y<8;y++) { hc164dat=(x&0x80); delayns(); hc164clk=1; delayns(); hc164clk=0; delayns(); x<<=1; } } void init() { P0=0xff;//输入P0全置一,让按键读回输入信息 P2=tablewe[8];//关闭所有数码管的位选 hc164clk=0;//时钟置低,以产生上升沿移入数据 IE=0X82; //EA=1开总中断ET0=1定时器零中断允许 TC=0X10;//TR0=1定时零中断启动 TMOD=0X01;//M1M0=01 T0 工作方式1,16位定时器 TH0=(65636-50000)/256; TL0=(65636-50000)%256;//50ms定时初值 DS1820DQ=1; } void iicstart()//暂未使用 { } void iicstop()//暂未使用 { } void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f,uchar g,uchar h)//显示函数 { P2=tablewe[8]; write164(tabledu[a]); P2=tablewe[0]; delay1ms(2); P2=tablewe[8]; write164(tabledu[b]); P2=tablewe[1]; delay1ms(2); P2=tablewe[8]; write164(tabledu[c]); P2=tablewe[2]; delay1ms(2); P2=tablewe[8]; write164(tabledu[d]); P2=tablewe[3]; delay1ms(2); P2=tablewe[8]; write164(tabledu[e]); P2=tablewe[4]; delay1ms(2); P2=tablewe[8]; write164(tabledu[f]); P2=tablewe[5]; delay1ms(2); P2=tablewe[8]; write164(tabledu[g]); P2=tablewe[6]; delay1ms(2); P2=tablewe[8]; write164(tabledu[h]); P2=tablewe[7]; delay1ms(2); } void timer()//24小时时间计算函数 { if(sec>59) { sec=0; min++; if(min>59) { min=0; hour++; if(hour>23) { hour=0; } } } dateshu[0]=sec%10; dateshu[1]=sec/10; dateshu[2]=min%10; dateshu[3]=min/10; dateshu[4]=hour%10; dateshu[5]=hour/10; } void key()//设定程序入口 { if(SET==0) { setflag=1; } } void keyshu()//设定键函数 { bit b,d,e; b=MINUS;d=ADD;//变量B,D,E分别读回P0。4~P0。6的状态。分别为加一,减一,确认键 e=EER; if(b==0)//减一按键按下 { dateshu[seta]--; if(dateshu[seta]<0)dateshu[seta]=9;//减到零时自动循环回九 b=MINUS;//再读回键值,做松手查检测 while(b==0){b=MINUS;display(dateshu[0],dateshu[1],10,seta+1,dateshu[2],dateshu[3],dateshu[4],dateshu[5]);}//松手检测 } else if(d==0)//加一按键按下 { dateshu[seta]++; if(dateshu[seta]>9)dateshu[seta]=0;//加到九时自动循环回零 d=ADD;//做松手检测 while(d==0){d=ADD;display(dateshu[0],dateshu[1],10,seta+1,dateshu[2],dateshu[3],dateshu[4],dateshu[5]);}//松手检测 } else if(e==0)//确认键按下 { seta++; e=ENR; while(e==0){e=ENTER;display(dateshu[0],dateshu[1],10,seta+1,dateshu[2],dateshu[3],dateshu[4],dateshu[5]);} if(seta>5)//如果六位数值已设定完毕,测退出设定状态 { seta=0;sec=0;setflag=0; sec=dateshu[1]*10+dateshu[0];//分别将设定好的值,赋给时秒变量,设定生效 min=dateshu[3]*10+dateshu[2];//分别将设定好的值,赋给分变量,设定生效 hour=dateshu[5]*10+dateshu[4];//分别将设定好的值,赋给时变量,设定生效 } } } void main()

{ init();//各外围元件及初始化 delay10us(150);//进入大循环时的延时 while(1) { key();//检测功能键有无按下 if(setflag==0)//如果设定功能未进入,则显示 { timer();//时间运算函数 display(dateshu[0],dateshu[1],10,10,dateshu[2],dateshu[3],dateshu[4],dateshu[5]);//显示实时时钟 } else//如果进入了功能设定函数 { keyshu();//读取键值 display(dateshu[0],dateshu[1],10,seta+1,dateshu[2],dateshu[3],dateshu[4],dateshu[5]);//显示实时设定 } if((dateshu[0]==3)&&(dateshu[1]%2==0))//每隔十秒温度读取显示一次 {uchar i;//显示延时用 dqrsr();//初始化 if(dqflag==1)//检测存在脉冲 { dqwrite(0xcc);//跳过ROM操作 dqwrite(0x44);//开始温度转换 while(!DS1820DQ);//延时等待温度转换完毕 dqrsr();//初始化 if(dqflag==1) { uchar temper;//温度变量 dqwrite(0xcc);//跳过ROM操作 dqwrite(0xbe);//读取数据指令 temperl=dqread();//读取低字节温度值 temperh=dqread();//读取高字节温度值 temperl=temperl>>4;//移去低四位的温度值 temperh=temperh<<4;//移去读回的符号号 temper=temperl+temperh;//将处理后的高字节温度和低字节温度值相加 for(i=250;i>0;i--)display(temper%10,temper/10,temper/100,10,10,10,10,10);//延时显示实时温度

} } } } } void time0(void) interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256;//定时器零重赋初值 tim++; if(tim==20) { tim=0;//tim==20时,为50MS*20=1S sec++; } }

-电子元器件采购网(www.ruidan.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。 自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台