在時鐘顯示狀態下沒有什么問題,按k4按鍵會進入溫度顯示狀態,松開則取消。但是顯示溫度時數碼管會一直出現閃爍的殘影,就是正常的溫度夾雜閃爍的殘影,好像在不停掃描一樣,有沒有大佬幫忙看看哪里有問題?時鐘顯示正常,不會有閃爍的殘影。代碼放下面了。
51hei圖片_20220921234236.jpg (413.65 KB, 下載次數: 17)
下載附件
2022-9-21 23:42 上傳
51hei圖片_20220921234229.jpg (467.51 KB, 下載次數: 16)
下載附件
2022-9-21 23:42 上傳
單片機源程序如下:
- #include <REGX52.H>
- unsigned char KeyNum,MODE1=-1,MODE2=-1,TimeSetSelect=-1,TimeSetFlashFlag,alarmSetSelect=-1,alarmSetSelectflash,Clocklock=0,alarmlock=0,Tlock=0;
- char Hour=12,Min=00,Sec=02;
- int T;
- void Nixie(unsigned char Location,Number);
- void TimeShow(void)//時間顯示功能
- {if(Clocklock==1){
- DS1302_ReadTime();//讀取時間
- Nixie(1,DS1302_Time[0]/10);
- Nixie(2,DS1302_Time[0]%10);
- Nixie(4,DS1302_Time[1]/10);
- Nixie(5,DS1302_Time[1]%10);
- Nixie(7,DS1302_Time[2]/10);
- Nixie(8,DS1302_Time[2]%10);
- Nixie(3,17);
- Nixie(6,17);
- }
- }
-
- void TimeSet(void)//時間設置功能
- {if(Clocklock==1){
- if(KeyNum==1)//按鍵2按下
- {
- TimeSetSelect++;//設置選擇位加1
- TimeSetSelect%=3;//越界清零
- }
- if(KeyNum==3)//按鍵3按下
- {
- DS1302_Time[TimeSetSelect]++;//時間設置位數值加1
- if(DS1302_Time[0]>23){DS1302_Time[0]=0;}//時越界判斷
- if(DS1302_Time[1]>59){DS1302_Time[1]=0;}//分越界判斷
- if(DS1302_Time[2]>59){DS1302_Time[2]=0;}//秒越界判斷
- }
- if(KeyNum==4)//按鍵4按下
- {
- DS1302_Time[TimeSetSelect]--;//時間設置位數值減1
- if(DS1302_Time[0]<0){DS1302_Time[0]=23;}//時越界判斷
- if(DS1302_Time[1]<0){DS1302_Time[1]=59;}//分越界判斷
- if(DS1302_Time[2]<0){DS1302_Time[2]=59;}//秒越界判斷
- }
- //更新顯示,根據TimeSetSelect和TimeSetFlashFlag判斷可完成閃爍功能
- if(TimeSetSelect==0 && TimeSetFlashFlag==1){Nixie(1,16);Nixie(2,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(1,DS1302_Time[0]/10);Nixie(2,DS1302_Time[0]%10);Nixie(3,17);Nixie(6,17);}
- if(TimeSetSelect==1 && TimeSetFlashFlag==1){Nixie(4,16);Nixie(5,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(4,DS1302_Time[1]/10);Nixie(5,DS1302_Time[1]%10);Nixie(3,17);Nixie(6,17);}
- if(TimeSetSelect==2 && TimeSetFlashFlag==1){Nixie(7,16);Nixie(8,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(7,DS1302_Time[2]/10);Nixie(8,DS1302_Time[2]%10);Nixie(3,17);Nixie(6,17);}
- }
- }
- void alarmshow(void){//時間顯示功能
- if(alarmlock==1){
- Nixie(1,Hour/10);
- Nixie(2,Hour%10);
- Nixie(4,Min/10);
- Nixie(5,Min%10);
- Nixie(7,Sec/10);
- Nixie(8,Sec%10);
- Nixie(3,17);
- Nixie(6,17);
- }
- }
- void alarmset(){
- if(alarmlock==1){
- if(KeyNum==2)//按鍵2按下
- {
- alarmSetSelect++;//設置選擇位加1
- alarmSetSelect%=3;//越界清零
- }
- if(KeyNum==3)//按鍵3按下
- {
- if(alarmSetSelect==0){
- Hour++;
- if(Hour>23){Hour=0;};
- }else if(alarmSetSelect==1){
- Min++;
- if(Min>23){Min=0;};
- }else{
- Sec++;
- if(Sec>23){Sec=0;};
- }
- }
- if(KeyNum==4)//按鍵4按下
- {
- switch(alarmSetSelect){
- case 0:Hour--;
- if(Hour<0){Hour=23;}
- break;
- case 1:Min--;
- if(Min<0){Min=59;}
- break;
- case 2:Sec--;
- if(Sec<0){Sec=59;}
- break;
- }
- }
- if(alarmSetSelect==0 && alarmSetSelectflash==1){Nixie(1,16);Nixie(2,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(1,Hour/10);Nixie(2,Hour%10);Nixie(3,17);Nixie(6,17);}
- if(alarmSetSelect==1 && alarmSetSelectflash==1){Nixie(4,16);Nixie(5,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(4,Min/10);Nixie(5,Min%10);Nixie(3,17);Nixie(6,17);}
- if(alarmSetSelect==2 && alarmSetSelectflash==1){Nixie(7,16);Nixie(8,16);Nixie(3,17);Nixie(6,17);}
- else {Nixie(7,Sec/10);Nixie(8,Sec%10);Nixie(3,17);Nixie(6,17);}
- }
- }
- void TShow(){
- if(Tlock==1){
- DS18B20_ConvertT(); //轉換溫度
- T=DS18B20_ReadT(); //讀取溫度
- Nixie(6,T/10);
- Nixie(7,T%10);
- Nixie(8,12);
- }
-
- }
- void main()
- {
- DS1302_Init();
- Timer0Init();
- DS1302_SetTime();//設置時間
-
- while(1)
- {
- KeyNum=Key();//讀取鍵碼
- if(KeyNum==1)//按鍵1按下
- {
- MODE1++;
- Clocklock=1;
- alarmlock=0;
- Tlock=0;
- }
- switch(MODE1)//根據不同的功能執行不同的函數
- {
- case 0:TimeShow();
- if(P3_3==0){
- while(P3_3==0){
- Clocklock=0;
- Tlock=1;
- TShow();
- }
- Tlock=0;
- Clocklock=1;
- TimeShow();
- }
- break;
- case 1:TimeSet();DS1302_SetTime();break;
- case 2:TimeSet();DS1302_SetTime();break;
- case 3:TimeSet();DS1302_SetTime();break;
- case 4:MODE1=0;break;
- }
- if(KeyNum==2)//按鍵2按下
- {
- MODE2++;
- Clocklock=0;
- Tlock=0;
- TimeShow();
- alarmlock=1;
- }
- switch(MODE2)//根據不同的功能執行不同的函數
- {
- case 0:alarmshow();break;
- case 1:alarmset();break;
- case 2:alarmset();break;
- case 3:alarmset();break;
- case 4:MODE2=0;break;
- }
- if(DS1302_Time[0]==Hour&&DS1302_Time[1]==Min&&DS1302_Time[2]==Sec){
- int x;
- for(x=0,P2=0x01;x<25;x++){
- P2=!P2; //1111 1110
- Delay(200);
- }
-
- }
- }
- }
- void Timer0_Routine() interrupt 1
- {
- static unsigned int T0Count;
- TL0 = 0x18; //設置定時初值
- TH0 = 0xFC; //設置定時初值
- T0Count++;
- if(T0Count>=500)//每500ms進入一次
- {
- T0Count=0;
- TimeSetFlashFlag=!TimeSetFlashFlag;//閃爍標志位取反
- alarmSetSelectflash=!alarmSetSelectflash;//閃爍標志位取反
- }
- }
- unsigned char Key()
- {
- unsigned char KeyNumber=0;
-
- if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
- if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
- if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
- if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
-
- return KeyNumber;
- }
- void Timer0Init(void)
- {
- TMOD &= 0xF0; //設置定時器模式
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0x18; //設置定時初值
- TH0 = 0xFC; //設置定時初值
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- ET0=1;
- EA=1;
- PT0=0;
- }
- void Delay(unsigned int xms)
- {
- unsigned char i, j;
- while(xms--)
- {
- i = 2;
- j = 199;
- do
- {
- while (--j);
- } while (--i);
- }
- }
- //引腳定義
- sbit DS1302_SCLK=P3^6;
- sbit DS1302_IO=P3^4;
- sbit DS1302_CE=P3^5;
- //寄存器寫入地址/指令定義
- #define DS1302_SECOND 0x80
- #define DS1302_MINUTE 0x82
- #define DS1302_HOUR 0x84
- #define DS1302_WP 0x8E
- //時間數組,索引0~6分別為年、月、日、時、分、秒、星期,設置為有符號的便于<0的判斷
- char DS1302_Time[]={12,59,25};
- /**
- * @brief DS1302初始化
- * @param 無
- * @retval 無
- */
- void DS1302_Init(void)
- {
- DS1302_CE=0;
- DS1302_SCLK=0;
- }
- /**
- * @brief DS1302寫一個字節
- * @param Command 命令字/地址
- * @param Data 要寫入的數據
- * @retval 無
- */
- void DS1302_WriteByte(unsigned char Command,Data)
- {
- unsigned char i;
- DS1302_CE=0;
- DS1302_SCLK=0;
- DS1302_CE=1;
- for(i=0;i<8;i++)
- {
- DS1302_IO=Command&(0x01<<i);
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- }
- for(i=0;i<8;i++)
- {
- DS1302_IO=Data&(0x01<<i);
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- }
- // DS1302_CE=0;
- }
- /**
- * @brief DS1302讀一個字節
- * @param Command 命令字/地址
- * @retval 讀出的數據
- */
- unsigned char DS1302_ReadByte(unsigned char Command)
- {
- unsigned char i,Data=0x00;
- Command|=0x01; //將指令轉換為讀指令
- DS1302_CE=0;
- DS1302_SCLK=0;
- DS1302_CE=1;
- for(i=0;i<8;i++)
- {
- DS1302_IO=Command&(0x01<<i);
- DS1302_SCLK=0;
- DS1302_SCLK=1;
- }
- for(i=0;i<8;i++)
- {
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- if(DS1302_IO){Data|=(0x01<<i);}
- }
- DS1302_CE=0;
- DS1302_SCLK=1;
- DS1302_IO=0; //讀取后將IO設置為0,否則讀出的數據會出錯
- DS1302_IO=1;
- DS1302_CE=1;
- return Data;
- }
- /**
- * @brief DS1302設置時間,調用之后,DS1302_Time數組的數字會被設置到DS1302中
- * @param 無
- * @retval 無
- */
- void DS1302_SetTime(void)
- {
- DS1302_WriteByte(DS1302_WP,0x00);
- DS1302_WriteByte(DS1302_HOUR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
- DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
- DS1302_WriteByte(DS1302_SECOND,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
- DS1302_WriteByte(DS1302_WP,0x80);
- }
- /**
- * @brief DS1302讀取時間,調用之后,DS1302中的數據會被讀取到DS1302_Time數組中
- * @param 無
- * @retval 無
- */
- void DS1302_ReadTime(void)
- {
- unsigned char Temp1;
- Temp1=DS1302_ReadByte(DS1302_HOUR);
- DS1302_Time[0]=Temp1/16*10+Temp1%16;
- Temp1=DS1302_ReadByte(DS1302_MINUTE);
- DS1302_Time[1]=Temp1/16*10+Temp1%16;
- Temp1=DS1302_ReadByte(DS1302_SECOND);
- DS1302_Time[2]=Temp1/16*10+Temp1%16;
- }
- unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,0X40};
- void Nixie(unsigned char Location,Number){
- switch(Location){
- case 1:P2_4=1;P2_3=1;P2_2=1;break;
- case 2:P2_4=1;P2_3=1;P2_2=0;break;
- case 3:P2_4=1;P2_3=0;P2_2=1;break;
- case 4:P2_4=1;P2_3=0;P2_2=0;break;
- case 5:P2_4=0;P2_3=1;P2_2=1;break;
- case 6:P2_4=0;P2_3=1;P2_2=0;break;
- case 7:P2_4=0;P2_3=0;P2_2=1;break;
- case 8:P2_4=0;P2_3=0;P2_2=0;break;
- }
- P0=NixieTable[Number];
- Delay(1);
- P0=0X00;
- }
- //引腳定義
- sbit OneWire_DQ=P3^7;
- /**
- * @brief 單總線初始化
- * @param 無
- * @retval 從機響應位,0為響應,1為未響應
- */
- void Delay5us(){ //Delay 5us
- }
- void Delay500us() //Delay 500us
- {
- unsigned char i;
- _nop_();
- i = 227;
- while (--i);
- }
- void Delay70us() //Delay 70us
- {
- unsigned char i;
- _nop_();
- i = 29;
- while (--i);
- }
- void Delay10us() //Delay 10us
- {
- unsigned char i;
- i = 2;
- while (--i);
- }
- void Delay50us() //@11.0592MHz
- {
- unsigned char i;
- _nop_();
- i = 20;
- while (--i);
- }
-
-
-
-
- unsigned char OneWire_Init(void)
- {
- // unsigned char i;
- unsigned char AckBit;
- OneWire_DQ=1;
- OneWire_DQ=0;
- Delay500us(); //Delay 500us
- OneWire_DQ=1;
- Delay70us() ; //Delay 70us
- AckBit=OneWire_DQ;
- Delay500us() ; //Delay 500us
- return AckBit;
- }
- /**
- * @brief 單總線發送一位
- * @param Bit 要發送的位
- * @retval 無
- */
- void OneWire_SendBit(unsigned char Bit)
- {
- // unsigned char i;
- OneWire_DQ=0;
- Delay10us(); //Delay 10us
- OneWire_DQ=Bit;
- Delay50us(); //Delay 50us
- OneWire_DQ=1;
- }
- /**
- * @brief 單總線接收一位
- * @param 無
- * @retval 讀取的位
- */
- unsigned char OneWire_ReceiveBit(void)
- {
- // unsigned char i;
- unsigned char Bit;
- OneWire_DQ=0;
- Delay5us(); //Delay 5us
- OneWire_DQ=1;
- Delay5us(); //Delay 5us
- Bit=OneWire_DQ;
- Delay50us(); //Delay 50us
- return Bit;
- }
- /**
- * @brief 單總線發送一個字節
- * @param Byte 要發送的字節
- * @retval 無
- */
- void OneWire_SendByte(unsigned char Byte)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- OneWire_SendBit(Byte&(0x01<<i));
- }
- }
- /**
- * @brief 單總線接收一個字節
- * @param 無
- * @retval 接收的一個字節
- */
- unsigned char OneWire_ReceiveByte(void)
- {
- unsigned char i;
- unsigned char Byte=0x00;
- for(i=0;i<8;i++)
- {
- if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
- }
- return Byte;
- }
- //DS18B20指令
- #define DS18B20_SKIP_ROM 0xCC
- #define DS18B20_CONVERT_T 0x44
- #define DS18B20_READ_SCRATCHPAD 0xBE
- /**
- * @brief DS18B20開始溫度變換
- * @param 無
- * @retval 無
- */
- void DS18B20_ConvertT(void)
- {
- OneWire_Init();
- OneWire_SendByte(DS18B20_SKIP_ROM);
- OneWire_SendByte(DS18B20_CONVERT_T);
- }
- /**
- * @brief DS18B20讀取溫度
- * @param 無
- * @retval 溫度數值
- */
- double DS18B20_ReadT(void)
- {
- unsigned char TLSB,TMSB;
- float Temp;
- int T;
- OneWire_Init();
- OneWire_SendByte(DS18B20_SKIP_ROM);
- OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
- TLSB=OneWire_ReceiveByte();
- TMSB=OneWire_ReceiveByte();
- Temp=(TMSB<<8)|TLSB;
- T=Temp/16.0;
- return T;
-
-
-
- }
- #include <REGX52.H>
- //引腳配置:
- sbit LCD_RS=P2^6;
- sbit LCD_RW=P2^5;
- sbit LCD_EN=P2^7;
- #define LCD_DataPort P0
- //函數定義:
- /**
- * @brief LCD1602延時函數,12MHz調用可延時1ms
- * @param 無
- * @retval 無
- */
- void LCD_Delay()
- {
- unsigned char i, j;
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
- /**
- * @brief LCD1602寫命令
- * @param Command 要寫入的命令
- * @retval 無
- */
- void LCD_WriteCommand(unsigned char Command)
- {
- LCD_RS=0;
- LCD_RW=0;
- LCD_DataPort=Command;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
- /**
- * @brief LCD1602寫數據
- * @param Data 要寫入的數據
- * @retval 無
- */
- void LCD_WriteData(unsigned char Data)
- {
- LCD_RS=1;
- LCD_RW=0;
- LCD_DataPort=Data;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
- /**
- * @brief LCD1602設置光標位置
- * @param Line 行位置,范圍:1~2
- * @param Column 列位置,范圍:1~16
- * @retval 無
- */
- void LCD_SetCursor(unsigned char Line,unsigned char Column)
- {
- if(Line==1)
- {
- LCD_WriteCommand(0x80|(Column-1));
- }
- else if(Line==2)
- {
- LCD_WriteCommand(0x80|(Column-1+0x40));
- }
- }
- /**
- * @brief LCD1602初始化函數
- * @param 無
- * @retval 無
- */
- void LCD_Init()
- {
- LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣
- LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關
- LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動
- LCD_WriteCommand(0x01);//光標復位,清屏
- }
- /**
- * @brief 在LCD1602指定位置上顯示一個字符
- * @param Line 行位置,范圍:1~2
- * @param Column 列位置,范圍:1~16
- * @param Char 要顯示的字符
- * @retval 無
- */
- void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
- {
- LCD_SetCursor(Line,Column);
- LCD_WriteData(Char);
- }
- /**
- * @brief 在LCD1602指定位置開始顯示所給字符串
- * @param Line 起始行位置,范圍:1~2
- * @param Column 起始列位置,范圍:1~16
- * @param String 要顯示的字符串
- * @retval 無
- */
- void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=0;String[i]!='\0';i++)
- {
- LCD_WriteData(String[i]);
- }
- }
- /**
- * @brief 返回值=X的Y次方
- */
- int LCD_Pow(int X,int Y)
- {
- unsigned char i;
- int Result=1;
- for(i=0;i<Y;i++)
- {
- Result*=X;
- }
- return Result;
- }
- /**
- * @brief 在LCD1602指定位置開始顯示所給數字
- * @param Line 起始行位置,范圍:1~2
- * @param Column 起始列位置,范圍:1~16
- * @param Number 要顯示的數字,范圍:0~65535
- * @param Length 要顯示數字的長度,范圍:1~5
- * @retval 無
- */
- void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
- }
- }
- /**
- * @brief 在LCD1602指定位置開始以有符號十進制顯示所給數字
- * @param Line 起始行位置,范圍:1~2
- * @param Column 起始列位置,范圍:1~16
- * @param Number 要顯示的數字,范圍:-32768~32767
- * @param Length 要顯示數字的長度,范圍:1~5
- * @retval 無
- */
- void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
- {
- unsigned char i;
- unsigned int Number1;
- LCD_SetCursor(Line,Column);
- if(Number>=0)
- {
- LCD_WriteData('+');
- Number1=Number;
- }
- else
- {
- LCD_WriteData('-');
- Number1=-Number;
- }
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
- }
- }
- /**
- * @brief 在LCD1602指定位置開始以十六進制顯示所給數字
- * @param Line 起始行位置,范圍:1~2
- * @param Column 起始列位置,范圍:1~16
- * @param Number 要顯示的數字,范圍:0~0xFFFF
- * @param Length 要顯示數字的長度,范圍:1~4
- * @retval 無
- */
- void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i,SingleNumber;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- SingleNumber=Number/LCD_Pow(16,i-1)%16;
- if(SingleNumber<10)
- {
- LCD_WriteData(SingleNumber+'0');
- }
- else
- {
- LCD_WriteData(SingleNumber-10+'A');
- }
- }
- }
- /**
- * @brief 在LCD1602指定位置開始以二進制顯示所給數字
- * @param Line 起始行位置,范圍:1~2
- * @param Column 起始列位置,范圍:1~16
- * @param Number 要顯示的數字,范圍:0~1111 1111 1111 1111
- * @param Length 要顯示數字的長度,范圍:1~16
- * @retval 無
- */
- void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
- }
- }
復制代碼
|