|
74HC595驅動8位數碼管顯示異常問題:
1. 用定時器0計時模擬時鐘顯示正常;
2. 讀取DS3231時鐘芯片的數據就顯示異常,前面7位亮度低,第8位亮度高,數字變化看不清楚,具體見異常顯示圖片。
壓縮包里面有所有的工程資料
請論壇大師看看怎么解決這個問題,謝謝。
原理圖.png (387.57 KB, 下載次數: 51)
下載附件
2024-4-19 09:47 上傳
異常顯示.jpg (60.54 KB, 下載次數: 46)
下載附件
2024-4-19 09:48 上傳
正常顯示.jpg (53.05 KB, 下載次數: 46)
下載附件
2024-4-19 09:48 上傳
單片機源程序如下:
- //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();
- }
復制代碼
|
|