|
74HC595驱动8位数码管显示异常问题:
1. 用定时器0计时模拟时钟显示正常;
2. 读取DS3231时钟芯片的数据就显示异常,前面7位亮度低,第8位亮度高,数字变化看不清楚,具体见异常显示图片。
压缩包里面有所有的工程资料
请论坛大师看看怎么解决这个问题,谢谢。
单片机源程序如下:
- //74HC595驱动8位数码管
- //#include <reg52.h>
- #include <STC8G.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- uchar code Table[] =
- { // 0 1 2 3 4 5 6 7 8 9 A b C d E 不显 -
- 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0xFF,0xbf
- }; //共阳段码表
- //-----------------------------------------------------------------------------
- sbit SER = P3^7; //串行数据输入端
- sbit STCP = P3^6; //时钟脉冲信号——上升沿有效 存储寄存器时钟输入端,并行输出
- sbit SHCP = P3^5; //输入信号————上升沿有效 移位寄存器时钟输入端
- sbit key1 = P3^0; //选择键
- sbit key2 = P3^1; //加键
- sbit key3 = P3^2; //减键
- char shi=12,fen=59,miao=30;
- //char shi,fen,miao;
- uchar shan,shan1,A,K,C,D,E,F;
- uchar knum; //选择键计数变量
- uint keycont1,keycont2,keycont3;//消抖计时变量
- bit lock1,lock2,lock3;//按键自锁标志
- bit key3_shotr_flag;
- bit ack; //应答标志位
- uchar key3_cnt;//按键3按下次数记录
- uint key3_sj_time;//按键3双击时间变量
- uchar key_num;//按键触发编号变量
- uchar hour,minute,second,year,month,day,date,week;
- #define const_key_time 20 //按键去抖动延时的时间
- //#define const_key_time2 20 //按键去抖动延时的时间
- //#define const_key_time3 20 //按键去抖动延时的时间
- #define const_key_long_time 500 //按键去抖动延时的时间
- #define const_key_lj_time 400 //按键去抖动延时的时间
- #define key3_sj_cnt 250 //按键去抖动延时的时间
- void TimerInit();
- void KeyScan(); //按键扫描
- void key_service();//按键服务程序
- void Display (uchar shi10,uchar shi,uchar fen10,uchar fen,uchar miao10,uchar miao); // 数码管显示
- void SMG_Int(uchar Dat); // 数码管单字节串行移位函数
- ///////////////////////////////////
- // ------------------------------------------------------------
- // IO口模拟I2C通信
- // ------------------------------------------------------------
- sbit SCL=P3^4; //串行时钟
- sbit SDA=P3^3; //串行数据
- /********************************************************************************************************
- ** DS3231常数定义
- ********************************************************************************************************/
- #define DS3231_WriteAddress 0xD0 //器件写地址
- #define DS3231_ReadAddress 0xD1 //器件读地址
- #define DS3231_SECOND 0x00 //秒
- #define DS3231_MINUTE 0x01 //分
- #define DS3231_HOUR 0x02 //时
- #define DS3231_WEEK 0x03 //星期
- #define DS3231_DAY 0x04 //日
- #define DS3231_MONTH 0x05 //月
- #define DS3231_YEAR 0x06 //年
- #define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位) 整数部分
- #define DS3231_TEMPERATUREL 0x12 //温度寄存器低字节(低2位) 小数部分
- #define NACK 1
- #define ACK 0
- //////////////////
- void Delay5US() //@11.0592MHz STC Y6指令
- {
- unsigned char i;
- _nop_();
- i = 16;
- while (--i);
- }
- void delay(uint x)
- {
- uint y,z;
- for(y=0; y<x; y--)
- for(z=0; z<930; z--);
- }
- /**********************************************
- //IIC Start
- **********************************************/
- void IIC_Start()
- {
- SCL = 1;
- SDA = 1;
- SDA = 0;
- SCL = 0;
- }
- /**********************************************
- //IIC Stop
- **********************************************/
- void IIC_Stop()
- {
- SCL = 0;
- SDA = 0;
- SCL = 1;
- SDA = 1;
- }
- /********************************************************************************************************
- ** 3231
- ********************************************************************************************************/
- uchar BCD2HEX(uchar val)//转10进制
- {
- return ((val>>4)*10)+(val&0x0f);
- }
- uchar HEX2BCD(uchar val) //转16进制
- {
- return (((val%100)/10)<<4)|(val%10);
- }
- void SendByte(uchar c)
- {
- uchar BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
- {
- if((c<<BitCnt)&0x80)
- SDA=1; //判断发送位
- else
- SDA=0;
- SCL=1; //置时钟线为高,通知被控器开始接收数据位
- Delay5US(); //保证时钟高电平周期大于4μs
- SCL=0;
- }
- SDA=1; //8位发送完后释放数据线,准备接收应答位
- SCL=1;
- Delay5US();
- if(SDA==1)
- ack=0;
- else
- ack=1; //判断是否接收到应答信号
- SCL=0;
- Delay5US();
- }
- uchar RcvByte()
- {
- uchar retc;
- uchar BitCnt;
-
- retc=0;
- SDA=1; //置数据线为输入方式
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- SCL=0; //置时钟线为低,准备接收数据位
- Delay5US(); //时钟低电平周期大于4.7μs
- SCL=1; //置时钟线为高使数据线上数据有效
- Delay5US();
- retc=retc<<1;
- if(SDA==1)
- retc=retc+1; //读数据位,接收的数据位放入retc中
- Delay5US();
- }
- SCL=0;
- return(retc);
- }
-
- void Ack_I2C(bit a)
- {
- SDA = a;
- SCL=1;
- Delay5US(); //时钟低电平周期大于4us
- SCL=0; //清时钟线,钳住I2C总线以便继续接收
- Delay5US();
- }
- uchar write_byte(uchar addr, uchar write_data)
- {
- IIC_Start();
- SendByte(DS3231_WriteAddress);
- if (ack == 0)
- return 0;
-
- SendByte(addr);
- if (ack == 0)
- return 0;
-
- SendByte(write_data);
- if (ack == 0)
- return 0;
-
- IIC_Stop();
- Delay5US();
- Delay5US();
- return 1;
- }
- uchar read_current()
- {
- uchar read_data;
- IIC_Start();
- SendByte(DS3231_ReadAddress);
- if(ack==0)
- return(0);
- read_data = RcvByte();
- Ack_I2C(1);
- IIC_Stop();
- return read_data;
- }
- uchar read_random(uchar random_addr)
- {
- uchar Tmp;
- IIC_Start();
- SendByte(DS3231_WriteAddress);
- if(ack==0)
- return(0);
- SendByte(random_addr);
- if(ack==0)
- return(0);
- Tmp=read_current();
- if(random_addr==DS3231_HOUR)
- Tmp&=0x3f;
-
- return(BCD2HEX(Tmp));//都转10进制输出
- }
-
- void KeyScan() //按键程序放在2ms定时器中断里面扫描
- {
- if(key1)
- {
- keycont1=0;
- lock1=0;
- }
- else if(lock1==0)//按键按下
- {
- keycont1++;
- if(keycont1>const_key_time)
- {
- keycont1=0;
- lock1=1; //按键锁置1,避免一直触发
- key_num=1; //触发1号键
- }
- }
- /////////////////////////
- if(key2)
- {
- keycont2=0;
- lock2=0;
- }
- else if(lock2==0)
- {
- keycont2++;
- if(keycont2>const_key_time)
- {
- keycont2=0;
- lock2=1;
- key_num=2; //触发2号键
- }
- }
- else if(keycont2<const_key_long_time)//长按 连减
- {
- keycont2++;
- if(keycont2==const_key_long_time)
- {
- keycont2=const_key_lj_time;//连加速度设置
- key_num=2; //触发2号键
- }
- }
- /////////////////////////
- if(key3) //按键没有按下
- {
- keycont3=0;
- lock3=0;
- if(key3_cnt>0) //按键按下次数key3_cnt>0说明按键按下过
- {
- key3_sj_time++;// 计时变量自加
- if(key3_sj_time>key3_sj_cnt)//计时大于500ms 2ms中断
- {
- key3_sj_time=0;//双击计时变量清零
- key3_cnt=0;//按键按下次数清零
- }
- }
-
- if(key3_shotr_flag) //松手后触发3号按键的单击短按
- {
- key_num=3; //触发3号键
- key3_shotr_flag=0;
- }
- }
- else if(lock3==0) //按键按下
- {
- keycont3++;
- if(keycont3>const_key_time)
- {
- keycont3=0;
- key3_cnt++;//k3按键次数
- lock3=1;
- if(key3_cnt==1)//单击
- {
- // key_num=3; //触发3号键
- key3_shotr_flag=1;
- }
- if(key3_cnt==2 && knum==0) //双击
- {
- miao = 30;//把秒写30
- }
- if(key3_cnt==3 && knum==0) //三击
- {
- fen = 30;//把分写30
- }
- }
- }
- else if(keycont3<const_key_long_time)//长按 连减
- {
- keycont3++;
- if(keycont3==const_key_long_time)
- {
- keycont3=const_key_lj_time;//连减速度设置
- key_num=3; //触发3号键
- }
- }
- }
- void key_service() // 按键服务的应用程序
- {
- switch(key_num)
- {
- case 1: knum++;
- if(knum==4)
- knum=0;
- key_num=0; //响应按键服务处理程序后,按键编号清零,避免一直触发!!!
- break;
- case 2: if(knum==1){shi++; if(shi>23)shi=0;}
- else if (knum==2){fen++; if(fen>59)fen=0;}
- else if (knum==3){miao++; if(miao>59)miao=0;}
- key_num=0; //响应按键服务处理程序后,按键编号清零,避免一直触发!!!
- break;
-
- case 3: if(knum==1){shi--; if(shi<0)shi=23;}
- else if (knum==2){fen--; if(fen<0)fen=59;}
- else if (knum==3){miao--; if(miao<0)miao=59;}
- key_num=0; //响应按键服务处理程序后,按键编号清零,避免一直触发!!!
- break;
- default: break;
- }
- }
- void out595()
- {
- STCP = 0; //数据并行输出,(借助上升沿)
- _nop_();
- _nop_();
- STCP = 1;
- }
- void Display (uchar shi10,uchar shi,uchar fen10,uchar fen,uchar miao10,uchar miao)
- {
- uchar i;
- //显示第1位 小时10位
- if(knum==1) //
- {
- if(shan>125) // 调时数码管闪烁
- i = Table[15];
- else
- i = Table[shi10];
-
- SMG_Int(i); //段码
- SMG_Int(0x01);//位码
-
- out595();
- //显示第2位 小时个位
- if(shan>125) //
- i = Table[15]; //黑屏
- else
- i = Table[shi];
-
- SMG_Int(i);
- SMG_Int(0x02);
-
- out595();
- }
- else
- {
- i = Table[shi10];
-
- SMG_Int(i);
- SMG_Int(0x01);
-
- out595();
-
- //显示第2位 小时个位
- i = Table[shi];
-
- SMG_Int(i);
- SMG_Int(0x02);
-
- out595();
- }
- //显示第3位 -
- // if(shan<125)
- // i = Table[15];
- // else
- i = Table[16]; //"-" 闪烁
- SMG_Int(i);
- SMG_Int(0x04);
- out595();
- //显示第4位 分钟10位
- if(knum==2)
- {
- if(shan>125) //
- i = Table[15];
- else
- i = Table[fen10];
- SMG_Int(i);
- SMG_Int(0x08);
-
- out595();
-
- //显示第5位 分钟个位
- if(shan>125) //
- i = Table[15];
- else
- i = Table[fen];
-
- SMG_Int(i);
- SMG_Int(0x10);
-
- out595();
- }
- else
- {
- i = Table[fen10];
-
- SMG_Int(i);
- SMG_Int(0x08);
-
- out595();
-
- //显示第5位 分钟个位
- i = Table[fen];
-
- SMG_Int(i);
- SMG_Int(0x10);
-
- out595();
- }
- //显示第6位 -
- // if(shan<125) //"-" 闪烁
- // i = Table[15];
- // else
- i = Table[16]; //"-"
- SMG_Int(i);
- SMG_Int(0x20);
- out595();
- if(knum==3)
- {
- //显示第7位 秒10位
- if(shan>125) //
- i = Table[15];
- else
- i = Table[miao10];
-
- SMG_Int(i);
- SMG_Int(0x40);
-
- out595();
-
- //显示第8位 秒个位
- if(shan>125) //
- i = Table[15];
- else
- i = Table[miao];
-
- SMG_Int(i);
- SMG_Int(0x80);
-
- out595();
- }
- else
- {
- //显示第7位 秒10位
- i = Table[miao10];
-
- SMG_Int(i);
- SMG_Int(0x40);
-
- out595();
-
- //显示第8位 秒个位
- i = Table[miao];
-
- SMG_Int(i);
- SMG_Int(0x80);
-
- out595();
- }
- }
- void SMG_Int(uchar Dat) //通过8次循环将8位数据移入74HC595
- {
- uchar i;
- for(i=8;i>=1;i--)
- {
- if (Dat & 0x80) //如果数据的最高位是1
- {
- SER = 1; //串行数据输入端置1
- }
-
- else
- {
- SER = 0; //否则串行数据输入端清零
- }
- Dat <<= 1; //数据左移1位,分8次把8位数据移入74HC595
- SHCP = 0; //SH引脚的上升沿把数据送入寄存器
- _nop_();
- _nop_();
- SHCP = 1;
- }
- }
- void TimerInit() //定时器0初始化
- {
- TMOD = 0x01;
- TH0 = (65536-2000)/256; //2ms初值
- TL0 = (65536-2000)%256;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void main ()
- {
- TimerInit();
- // PWM_Init();
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x00;//
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- while(1)
- {
- // shi = read_random(DS3231_HOUR);
- // fen = read_random(DS3231_MINUTE) ;
- // miao = read_random(DS3231_SECOND);
- // A=shi/10;
- // K=shi%10;
- // C=fen/10;
- // D=fen%10;
- // E=miao/10;
- // F=miao%10;
-
- Display (A,K,C,D,E,F);
- key_service();// 按键服务的应用程序
- }
- }
- void Timer0() interrupt 1
- {
- static uint cnt;
-
- TH0 = (65536-2000)/256;
- TL0 = (65536-2000)%256;
- // shan1++;
- // if(shan1==250)
- // shan1=0;
-
- shan++;
- if(shan==250)
- shan=0;
- if(knum==0)
- {
- cnt++;
- if(cnt==500)
- {
- cnt = 0;
- miao++;
- if(miao == 60)
- {
- miao = 0;
- fen++;
- if(fen==60)
- {
- fen = 0;
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- }
- A=shi/10;
- K=shi%10;
- C=fen/10;
- D=fen%10;
- E=miao/10;
- F=miao%10;
-
- KeyScan();
- }
复制代码
|
|