求高手改時鐘顯示閃爍程序 和DS3231低溫度程序 程序是在論壇里下載的 還想在修改哈 望高手幫幫忙
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
F4)1PLOAPT)DBM(0YA`TL8Y.png (205.82 KB, 下載次數: 52)
下載附件
2020-5-11 10:17 上傳
%7ZE08@NKIUK]YGKFP_D7.png (128.3 KB, 下載次數: 66)
下載附件
2020-5-11 10:17 上傳
VHIS[RJNZ@D%T6DLPV)VC}N.png (221.56 KB, 下載次數: 48)
下載附件
2020-5-11 10:17 上傳
單片機源程序如下:
- #include <reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit SDA=P2^7; //數據傳送位SDA
- sbit SCL=P2^6; //時鐘控制位SCL
- sbit INT=P3^3; //中斷位
- sbit RESET=P3^2; //復位
- sbit smg4=P1^1; //位碼1聲明 分個位
- sbit smg3=P1^3; //位碼2聲明 分十位
- sbit smg2=P1^5; //位碼3聲明 時個位
- sbit smg1=P1^7; //位碼4聲明 時十位
- sbit k1=P1^4; //按鍵k1的聲明
- sbit k2=P1^6; //按鍵k2的聲明
- sbit k3=P3^7; //按鍵k3的聲明
- sbit bell=P3^5; //蜂鳴器聲明
- sbit gm=P2^1; //測光聲明,黑暗時等于1
- bit gm_en=0; //光敏使能信號;
- bit ack; //應答標志位
- char code dis_code[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E};//數碼管沒有按a-h的順序連接,自定義的顯示字庫,0-9,A-F
- //0X28,0XEE,0X32,0XA2,0XE4,0XA1,0X21,0XEA,0X20,0XA0,0X60,0X25,0X37,0X26,0X31,0X71
- uchar bell_en=0,x=1;//鬧鐘使能信號,任意鍵關閉鈴聲標志位
- uchar tabtime[]={0x00,0x00,0x07,0x02,0x23,0x10,0x18}; //首次上電時默認的時間2018年 星期二 10月23日 07:00:00
- uchar year,month,day,week,hour,minute,second,temperature; //從1302讀出的實時時間數據
- uchar gm_time=60,temp_en=0,n=0,a=0,b=0; //gm_time光敏控制亮度值,n是按鍵標志位,a產生一個1秒的計時,b控制字符閃爍,temp_en溫度顯示標志
- uint t=0; //用來產生30秒的計時
- uint TtempH,TtempL; //定義溫度高位,低位
- char shi,fen,miao,b_shi=7,b_fen=0; //必須使用符號型:數據暫存單元shi/fen/miao,鬧鈴時間b_shi,b_fen,
- void baojing(); //報警函數
- void delay_50us(uint t); //延時50*T微妙函數的聲明
- void Start_I2C(); //I2C總線產生起始信號函數
- void Stop_I2C(); //I2C總線產生停止信號函數
- void Ack_I2C(bit a); //接收應答信號函數;
- void SendByte(uchar c); //向I2C總線寫入一個字節的數據函數
- uchar RcvByte(); //字節數據接收函數
- uchar write_byte(uchar addr, uchar write_data);//將一個字節寫入DS3231指定地址
- uchar read_byte(uchar addr); //從DS3231指定地址讀一個字節
- void Set_Time(); //設置時間
- void get_time(void); //讀取時間
- void get_Temperature(); //讀取溫度
- void show_Temperature(); //顯示溫度
- void init(); //初始化函數
- void timer0(); //定時器0中斷服務程序
- void display(uchar s,f); //顯示子程序
- void key(); //按鍵控制函數
- void baojing()//報警函數
- {
- uint j=10,i=10;
- bell=0;
- while(i--)display(shi,fen);
- bell=1;
- while(j--)display(shi,fen);
- }
- //函數名稱:void delay_50US(unsigned int t)
- //功能: 延時50*t(us)
- void delay_50us(uint t)
- {
- unsigned char j;
- for(;t>0;t--)
- {
- for(j=19;j>0;j--);
- }
- }
- void Start_I2C() //I2C總線產生起始信號函數
- {
- SDA=1; //拉高數據線,發送起始條件的數據信號
- SCL=1; //拉高時鐘線
- SDA=0; //在時鐘線為高電平時,拉低數據線,產生起始信號
- SCL=0; //鉗住I2C總線,準備發送或接收數據
- }
- void Stop_I2C() //I2C總線產生停止信號函數
- {
- SDA=0; //拉低數據線,發送結束條件的數據信號
- SCL=1; //拉高時鐘線,發送結束條件的時鐘信號
- SDA=1; //時鐘時線為高電平時,拉高數據線,發送I2C總線結束信號
- }
- /********************************************************************
- 應答子函數
- 函數原型: void I2CACK(bit a);
- 功能: 主控器進行應答信號(可以是應答或非應答信號,由位參數a決定)
- ********************************************************************/
- void Ack_I2C(bit a) //接收應答信號函數;a是定義的一個位變量,來暫存應答狀態。
- {
-
- if(a==0)
- SDA=0; //在此發出應答或非應答信號
- else
- SDA=1;
- SCL=1;
- SCL=0; //清時鐘線,鉗住I2C總線以便繼續接收
- }
- /*******************************************************************
- 字節數據發送函數
- 函數原型: void SendByte(uchar c);
- 功能: 將數據c發送出去,可以是地址,也可以是數據,發完后等待應答,并對
- 此狀態位進行操作.(不應答或非應答都使ack=0)
- ack=1 發送數據正常,
- ack=0 被控器無應答或損壞。
- ********************************************************************/
- void SendByte(uchar c) //向I2C總線寫入一個字節的數據函數
- {
- uchar BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數據長度為8位
- {
- if((c<<BitCnt)&0x80)
- SDA=1; //判斷發送位
- else
- SDA=0;
- SCL=1; //置時鐘線為高,通知被控器開始接收數據位
- SCL=0;
- }
-
- SDA=1; //8位發送完后釋放數據線,準備接收應答位
- SCL=1;
- if(SDA==1)
- ack=0;
- else
- ack=1; //判斷是否接收到應答信號
- SCL=0;
- }
- /*******************************************************************
- 字節數據接收函數
- 函數原型: uchar RcvByte();
- 功能: 用來接收從器件傳來的數據,并判斷總線錯誤(不發應答信號),
- 發完后請用應答函數應答從機。
- ********************************************************************/
- uchar RcvByte() //字節數據接收函數
- {
- uchar retc;
- uchar BitCnt;
-
- retc=0;
- SDA=1; //置數據線為輸入方式
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- SCL=0; //置時鐘線為低,準備接收數據位
- SCL=1; //置時鐘線為高使數據線上數據有效
- retc=retc<<1;
- if(SDA==1)
- retc=retc+1; //讀數據位,接收的數據位放入retc中
- }
- SCL=0;
- return(retc);
- }
-
-
- /***********將一個字節寫入DS3231指定地址***********/
- uchar write_byte(uchar addr, uchar write_data)
- {
- Start_I2C();
- SendByte(0xD0);
- if (ack == 0)
- return 0;
-
- SendByte(addr);
- if (ack == 0)
- return 0;
-
- SendByte(write_data);
- if (ack == 0)
- return 0;
-
- Stop_I2C();
- return 1;
- }
- /************從DS3231指定地址讀一個字節************/
- uchar read_byte(uchar addr)
- {
- uchar read_data;
- Start_I2C();
- SendByte(0xD0);
- if(ack==0)
- return(0);
-
- SendByte(addr);
- if(ack==0)
- return(0);
-
- Start_I2C();
- SendByte(0xD1);
- if(ack==0)
- return(0);
- read_data = RcvByte();
- Ack_I2C(1);
- Stop_I2C();
- return read_data;
- }
-
- /**************************設置時間******************************************/
- void Set_Time()
- {
- uchar i;
- uchar ucAddr=0x00; //秒的地址
- for(i=0;i<7;i++)
- {
- write_byte(ucAddr,tabtime[i]);//從秒開始連續寫入秒分時星期日月年
- ucAddr+=1;
- }
- }
-
-
- /*********************讀取時間**********************/
- void get_time(void)
- {
- hour=read_byte(0x02)/16*10+read_byte(0x02)%16;
- minute=read_byte(0x01)/16*10+read_byte(0x01)%16; //因只顯示時、分,故可只讀取時、分
- year=read_byte(0x06)/16*10+read_byte(0x06)%16;
-
- /*
- uchar i;
- uchar ucCurtime[7];
- uchar ucAddr = 0x00; //秒地址
- for(i=0;i<7;i++)
- {ucCurtime[i]=0;}
-
- for(i=0; i<7; i++)
- {
- ucCurtime[i] = read_byte(ucAddr); //格式為: 從秒地址開始連續讀取,秒分時星期日月年。
- ucAddr += 1;
- }
- year=ucCurtime[6]/16*10+ucCurtime[6]%16;
- month=ucCurtime[5]/16*10+ucCurtime[5]%16;
- day=ucCurtime[4]/16*10+ucCurtime[4]%16;
- week=ucCurtime[3]/16*10+ucCurtime[3]%16;
- hour=ucCurtime[2]/16*10+ucCurtime[2]%16;
- minute=ucCurtime[1]/16*10+ucCurtime[1]%16;
- second=ucCurtime[0]/16*10+ucCurtime[0]%16;
- */
- }
-
- /*********************讀取溫度**********************/
- void get_Temperature()
- {
- TtempH=read_byte(0X11); //讀溫度高字節
- //因數碼管位數只有四位,故溫度的小數部分不顯示,可以不用讀溫度低字節
- TtempL=read_byte(0x12); //原為注釋不用ox12 //讀溫度低字節
- TtempL=(TtempL>>6)*25; //原為注釋不用 //將BIT7,BIT6的數據移入BIT1,BIT0位;分辨率數值擴大100倍便于整數運算
-
- }
- void show_Temperature() //顯示溫度
- {
- if((TtempH&0X80)==0x80) //判斷首字節為1即為零下溫度
- {
- P0=0xBF; //0xbf第一位數碼管顯示“-”
- smg1=0;
- delay_50us(gm_time);
- smg1=1;
- //////
- P0=dis_code[TtempL/10];//送顯示斷碼 十位
- smg2=0;
- delay_50us(gm_time);
- smg2=1;
- P0=dis_code[TtempL%10];//送顯示斷碼 個位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- P0=0xC6; //送顯示斷碼 ℃
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
-
- }
- else
- smg1=1; //第一位數碼管不顯示
- if((TtempH/10)==0) //原為0 溫度低于10度時,即為個位時,第二位數碼管位不顯示
- smg2=1; //原為=1
- else
- {
- P0=dis_code[TtempH/10];//送顯示斷碼 十位
- smg2=0;
- delay_50us(gm_time);
- smg2=1;
- }
-
- P0=dis_code[TtempH%10];//送顯示斷碼 個位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- P0=0xC6; //送顯示斷碼 ℃
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
-
-
- }
- void init() //初始化函數
- {
- write_byte(0x0e,0x00); //設定DS3231的控制寄存器
- IE=0X82; //設定單片機的中斷允許控制寄存器,(1000 0010)
- TMOD=0X01; //0000 0001選擇定時器0的工作方式1 選擇定時器1的工作方式0
- TH0=(65536-50000)/256;//初值15536定時50mS
- TL0=(65536-50000)%256;
- TR0=1; //設定TCON的TR0位,開啟定時器0
- }
- void timer0() interrupt 1 //定時器0中斷服務程序,用來設置冒號閃爍頻率
- {
- TH0=(65536-50000)/256;//進入中斷重新賦初值15536
- TL0=(65536-50000)%256;//計數5萬次(50毫秒)
- a++; //標志位b,用來確定光標閃爍頻率
- t++;
- if(t==600)t=0; //50ms*600次=30秒,用于溫度顯示,30秒一次
- if(t>520)temp_en=1; //溫度顯示持續3秒
- else temp_en=0;
- if(a==20)a=0;//a=20 時被清零 產生一個1秒的計時。
- }
- //四位數碼管顯示程序
- void display(uchar s,f)
- {
- if((s/10)<1) //小于10,第一位不顯示
- smg1=1;
- else
- {
- P0=dis_code[s/10];//送顯示斷碼 時的十位
- if((n==1||n==3)&&a<5)
- smg1=1; //鎖存數據
- else
- smg1=0;
- delay_50us(gm_time);
- smg1=1;
- }
- P0=dis_code[s%10]; //送顯示斷碼 時的個位
- if((n==1||n==3)&&a<5)
- smg2=1;
- else
- smg2=0; //鎖存數據
- delay_50us(gm_time);
- smg2=1;
-
-
-
- if((n==2||n==4)&&a<5)
- P0=0x7F; //字符閃爍,小點不閃
- else if(a>=10)
- P0=dis_code[f/10]-0x80; //小點閃爍,字符不閃
- else
- P0=dis_code[f/10]; //送顯示斷碼 分的十位
- smg3=0;
- delay_50us(gm_time);
- smg3=1;
- if((n==2||n==4)&&a<5)
- P0=0x7F; //字符閃爍,小點不閃
- else if(a>=10)
- P0=dis_code[f%10]-0x80; //小點閃爍,字符不閃
- else
- P0=dis_code[f%10]; //送顯示斷碼 分的個位
- smg4=0;
- delay_50us(gm_time);
- smg4=1;
- }
- void key() //按鍵控制函數
- {
-
- if(k1==0&&k2==0) //k1k2同時按下,切換鬧鈴開關 并且在按下之后查看鬧鐘時間松手后恢復時間顯示
- {
- delay_50us(40);
- if(k1==0&&k2==0)
- {
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果處于響零狀態,就任意鍵關閉響鈴
- shi=b_shi;
- fen=b_fen;
- bell_en=!bell_en;
- if(bell_en==1) //使能的話報警兩聲
- {
-
- baojing();
- baojing();
- }
- else
- {
-
- baojing(); //無效的話報警一聲
- }
- while(k1==0&&k2==0)
- display(shi,fen);//等待松手
- shi=hour;
- fen=minute;
- }
- }
- if(k1==0&&k3==0) //k1k3同時按下,切換光控功能
- {
- delay_50us(40);
- if(k1==0&&k3==0)
- {
- gm_en=!gm_en;
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果處于響零狀態,就任意鍵關閉響鈴
- if(gm_en==1) //使能的話報警兩聲
- {
- baojing();
- baojing();
- }
- else baojing(); //無效的話報警一聲
- while(k1==0&&k3==0)
- display(88,88);//等待松手
- }
- }
-
-
- if(k2==0&&k3==0) //K2,K3同時按下,進入 調時間 和 鬧鈴狀態
- { //功能鍵k1被按下
- delay_50us(40); //消抖延時
- if(k2==0&&k3==0)
- {
- if(bell_en==1&&b_shi==hour&&b_fen==minute&&x==1)
- x=0; //如果處于響零狀態,就任意鍵關閉響鈴
- while(k2==0&&k3==0)
- n=1;
-
- }
- //要加入數字閃爍代碼
- }
-
-
-
-
- if(n==0)//狀態0,正常顯示時間
- {
- b=a; //b是控制小數點閃爍的
- shi=hour;
- fen=minute;
- }
-
- if(n==1) //狀態1:調節時間的"時"
- {
- b=10;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延時
- if(k1==0)
- {
- while(k1==0)
- n=2;
- }
- }
-
- if(k2==0)
- {
- delay_50us(40); //消抖延時
- if(k2==0)//k2被按下
- shi=shi+1; //小時加一
- if(shi>=24)
- shi=0; //達到24清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)
- {
- delay_50us(40); //消抖延時
- if(k3==0) //k3被按下
- shi--; //小時減一
- if(shi<0)
- shi=23;//小于0,重新賦值
- while(k3==0)
- display(shi,fen);
- }
- }
-
- if(n==2)//狀態2:調節時間的"分"
- {
- b=10;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延時
- if(k1==0)
- {
- while(k1==0)
- n=3;
- }
- tabtime[2]=shi/10*16+shi%10;
- tabtime[1]=fen/10*16+fen%10;
-
- hour=shi;
- minute=fen;
- Set_Time();//設置DS1302的初始時間
-
- }
-
-
- if(k2==0)//k2被按下
- {
- delay_50us(40); //消抖延時
- if(k2==0)
- fen++;//分加一
- if(fen>=60)
- fen=0;//分到達60 分清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)//k3被按下
- {
- delay_50us(40); //消抖延時
- if(k3==0)
- fen--;//分減一
- if(fen<0)
- fen=59;//分小于0,分重新賦值59
- while(k3==0)
- display(shi,fen);
- }
-
- }
-
-
- if(n==3)//狀態三:調節鬧鈴"時"
- {
- b=10;
- shi=b_shi;
- fen=b_fen;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延時
- if(k1==0)
- {
- while(k1==0)
- n=4;
- }
- }
-
- if(k2==0)//k2被按下
- {
- delay_50us(40); //消抖延時
- if(k2==0)
- b_shi++;//鬧鈴時間加一
- if(b_shi>=24)
- b_shi=0;//鬧鈴時間清零
- while(k2==0)
- display(shi,fen);
- }
-
- if(k3==0)//k3被按下
- {
- delay_50us(40); //消抖延時
- if(k3==0)
- b_shi--;//鬧鈴時間減一
- if(b_shi<0)
- b_shi=23;//鬧鈴時間
- while(k3==0)
- display(shi,fen);
- }
- }
-
-
- if(n==4)//狀態四 :調節鬧鈴的"分"
- {
- b=10;
- shi=b_shi;
- fen=b_fen;
-
- if(k1==0)
- {
- delay_50us(40); //消抖延時
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
51hei.png (8.18 KB, 下載次數: 42)
下載附件
2020-5-11 14:40 上傳
所有資料51hei提供下載:
0.8寸數碼管 PCB 電路圖 程序.rar
(3.56 MB, 下載次數: 82)
2020-5-11 10:18 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|