很适初学者做的例程,两组数码管没有用74H595而是用N个IO直接控制,感觉这是我数码管时代最后一个作品,51单片机,一般工业用的也只是简单的控制,关键一点就是他是我们通向科技顶峰的天梯,一路走来感悟很多………致我们走过的青春。推荐个文本编辑器920,用手机上51黑更方便,只要有人贴个源代码,复制就OK,发贴也快(题外话)
制作出来的实物图如下:
单片机源程序如下:
- #include<reg51.h>
- #include <intrins.h>
- #define uchar unsigned char//只有256
- #define uint unsigned int//有16位但占内存。
- uchar count;//中断计数
- uint sec;//秒显示
- uint su;//秒显示
- sbit wei0=P1^2;//位
- sbit wei1=P1^1;//位
- sbit wei2=P1^0;//位
- sbit wei00=P2^4;//位
- sbit wei01=P2^3;//位
- sbit wei02=P2^2;//位
- sbit k2=P1^4;//按键
- sbit k1=P1^5;//按键
- sbit k3=P1^6;//按键
- sbit k4=P1^7;//按键
- sbit led=P2^7;//按键
- bit write_secbf=0;//定时溢出标志位,用来写24C02
- sbit scl_24=P2^1;//24c02时钟线
- sbit sda_24=P2^0;//24c02数据线
- bit k;//位变量取值只有0、1、黙认为0*/
- void delay (int a)//毫秒级延时
- {
- int x,y;
- for(x=a;x>0;x--)
- for(y=110;y>0;y--);
- }
- void usdelay()
- {
- _nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();
- }
- uchar code table[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共阴表(wei=0;开反之关)加显示位(P0=table[shi]+0x80;(+或|))显小数点
- /*uchar code table1[16] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
- 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//共阳表(wei=1;开反之关)加显示位(P0=table[shi]&0x7f;)显小数点*/
- uint qian,bai,shi,ge;
- void display(int dat)//4位显示子函数
- {
- qian=dat/1000;
- bai=dat%1000/100;
- shi=dat%100/10;
- ge=dat%10;
- //wei3=0;
- //P0=table[qian];
- //delay(2);
- //wei3=1;
- wei2=1;
- P0=table[bai];
- delay(3);
- wei2=0;
- wei1=1;
- P0=table[shi];//|0x80;
- delay(3);
- wei1=0;
- wei0=1;
- P0=table[ge];
- delay(3);
- wei0=0;
- }
- uint qian1,bai1,shi1,ge1;
- void display1(int dat)//4位显示子函数
- {
- qian1=dat/1000;
- bai1=dat%1000/100;
- shi1=dat%100/10;
- ge1=dat%10;
- //wei3=0;
- //P0=table[qian1];
- //delay(2);
- //wei3=1;
- wei02=1;
- P3=table[bai1];
- delay(3);
- wei02=0;
- wei01=1;
- P3=table[shi1];//|0x80;
- delay(3);
- wei01=0;
- wei00=1;
- P3=table[ge1];
- delay(3);
- wei00=0;
- }
- /***************以下开始为24CXX用子程序**********************/
- void star24() //开始信号
- {//时钟线在高电平时,数据线由高变低即为开始信号 由高变低即为开始信号
- sda_24=1;
- usdelay();
- scl_24=1;
- usdelay();
- sda_24=0;//数据线由高变低即为开始信号
- usdelay();
- scl_24=0;
- }
- void stop24() //结束信号
- {//时钟线在高电平时,数据线由低变高即为结束信号
- sda_24=0;
- usdelay();
- scl_24=1;
- usdelay();
- sda_24=1;
- usdelay();
- sda_24=0; //这句可有可无
- scl_24=0; //这句可有可无
- }
- void Ack24()//应答
- { uchar i;
- scl_24=1;
- usdelay();
- while((sda_24==1)&&(i<200))i++;
- scl_24=0;
- usdelay();
- }
- /*
- void NoAck24() //不应答
- {
- sda_24=1; //时钟线高电平时,数据线高,即为不应答
- usdelay();
- scl_24=1;
- usdelay();
- scl_24=0;
- usdelay();
- } */
- /**********24c0初始化***************************/
- void init_24()
- {
- sda_24=1;
- usdelay();
- scl_24=1;
- usdelay();
- }
- /**********读数据24c02***************************/
- void write_byte(uchar dat)
- {
- uchar i,temp;
- temp=dat;
- //scl_24=0;//低电平可以变数据,为高时是读,且不能变
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- scl_24=0;
- usdelay();
- sda_24=CY;//CY是PSW寄存器中的CY位,再把CY赋给SDA,再由SCL控制发出去
- //sda_24=(bit)(temp&0x80);//用这句也可以换掉上一句(bit)是强制转换命令,把数据转成非0即1
- usdelay();
- scl_24=1;
- usdelay();
- }
- scl_24=0;
- usdelay();
- sda_24=1;//释放总线
- usdelay();
- }
- /**********读数据24c02***************************/
- uchar read_byte()
- {
- uchar i,k;
- scl_24=0; //这句可有可无
- usdelay(); //这句可有可无
- sda_24=1; //释放总线
- usdelay();
- for(i=0;i<8;i++)
- {
- scl_24=1;
- usdelay();
- k=(k<<1)|sda_24;//判断8次,移位7次
- scl_24=0;
- usdelay();
- }
- return k;
- }
- /**********写24c02指定地址的数据***************************/
- void write_add(uchar add,uchar dat)
- {
- star24();
- write_byte(0xa0);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个0是写标志
- Ack24();//写了后要马上应答
- write_byte(add);//写要往哪个地址写数据00-1023
- Ack24();//每写一次要给一个应答位
- write_byte(dat);//把数据写入
- Ack24();
- stop24();//给一个停止位,结束写数据
- }
- /**********读数据24c02指定地址的数据***************************/
- uchar read_add(uchar add)
- {
- uchar dat;
- star24();
- write_byte(0xa0);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个0是写标志
- Ack24();//写了后要马上应答
- write_byte(add);//写入要往哪个地址读数据00-1023
- Ack24();//每写一次要给一个应答位
- star24();
- write_byte(0xa1);//呼叫器件,高四位为定了的1010,即A,低四位三个接了地,所以为000,最后一个1是读标志
- Ack24();//写了后要马上应答
- dat=read_byte();
- stop24();//给一个停止位,结束读数据
- return dat;//返回一个DAT(数据)
- }
- void keyscan()
- { if(k3==0&&su>0)//按K1时停TR0=0;
- {
- delay(3);
- if(k3==0&&su>0) //与上sec>0条件
- while(!k3);
- //TR1=1;
- TR1=~TR1;//取反定时器TR0,按一次开0,再按关1;
- }
-
- if(k2==0)
- {
- delay(3);
- if(k2==0)
- while(!k2);
- TR1=0;
- su++;
- if(su>255) su=0;
- sec=su;
- write_add(0,sec);//在地址2 写入min
- delay(1);
- }
- if(k1==0)
- {
- delay(3);
- if(k1==0)
- while(!k1);
- TR1=0;
- su--;
- if(su==0) su=255;
- sec=su;
- write_add(0,sec);//在地址2 写入min
- delay(1);
- }
- }
- void main()
- { init_24();//24c02初始化
- TMOD=0X11;//定时器1 TMOD=0X11;方式1.
- TH1=(65536-50000)/256;//装初值
- TL1=(65536-50000)%256;//装初值
- EA=1;
- ET1=1;
- TR1=0;//定时器先关。等开关键启动
- led=0;//反相器0为关。
- sec=read_add(0);//从地址( )中读出以前保存的数据
- delay(2);
- su=sec;
- while(1)
- {
- keyscan();
- if(count==2*1)//50000个20=1秒。
- {
- count=0;
- sec--;
- if(sec==0)//如果秒>100秒清0并执行后面、
- {
- TR1=1;//定时器先关。等开关键启动
- sec=su;
- led=~led;
- //delay(10);
- //led=0;
- }
- }
- display(sec); //实时数据
- display1(su);//设置数据
- }
- }
- void timer0() interrupt 3 //定时器0的中断子函数(外部0为0、定时0为1、外部1为2、定时1为3、串口4、)
- {
- TH1=(65536-50000)/256;//装初值
- TL1=(65536-50000)%256;//装初值
- count++;//中断发生后中断计数加1
- }
-
复制代码
所有资料51hei提供下载:
IIC定时双数码管OK.zip
(37.59 KB, 下载次数: 32)
|