|
DIY高精度時(shí)鐘、溫度顯示器Ds3231+12864+ds18b20+89c51 硬件: 程序: - #include<reg52.h>
- #include<intrins.h>
- #include<stdlib.h>
-
- #define uchar unsigned char
- #define uint unsigned int
- /*端口定義*/
- sbit LCD_RS=P2^6;
- sbit LCD_RW=P2^5;
- sbit LCD_EN=P2^4;
- sbit LCD_PSB=P2^3;
- sbit DQ=P3^7; //18b20
- sbit SDA=P1^4; //ds32321 //模擬I2C數(shù)據(jù)傳送位SDA
- sbit SCL=P1^3; //模擬I2C時(shí)鐘控制位SCL
- //***按鍵功能****//
- ////***K1停止時(shí)間顯示****//
- ////***K2選擇修改位置****//
- ////***K3進(jìn)行加1的修改****//
- ////***K4將修改寫(xiě)入ds3231,同時(shí)啟動(dòng)時(shí)間顯示****//
- sbit K1=P3^2;
- sbit K2=P3^3;
- sbit K3=P3^4;
- sbit K4=P3^5;
- //定義變量
- uchar numbr[10]="0123456789"; //字模
-
-
- uchar dis4[]=" "; // 第四行顯示 自己添加
- uchar t[]=" . ℃" ; //18b20
- uint sdata,xiaoshu1,xiaoshu2; //整數(shù)、小數(shù)1位、小數(shù)2位
- bit fg=1; //溫度正負(fù)標(biāo)志
- uchar tempL=0,tempH=0; // 變量
- uchar year,month,date,hour,min,sec; // ds3231
- uchar a[]="2011年22月33日";
- uchar b[]="11時(shí)22分33秒";
- ///函數(shù)
- //******************延時(shí)子程序 *******************************
-
- //這個(gè)延時(shí)程序的具體延時(shí)時(shí)間是time=i*8+10,適用于小于2ms的延時(shí)
-
- //************************************************************
- void delay(unsigned char i)
- {
- for(i;i>0;i--);
- }
- //***********************************************************
- // 延時(shí)子程序
- //************************************************************
- void delay1ms(uchar j)
- {
- while(j!=0)
- {uchar i;
- for(i=124;i>0;i--); //延時(shí)124*8+10=1002us
- j--;
- }
- }
- /**************************12864部分*************************************/
- /**************************12864部分*************************************/
- /*寫(xiě)指令數(shù)據(jù)到LCD
- RS=L——表示DB0-DB7為顯示指令數(shù)據(jù)
- RW=L——表示DB0-DB7數(shù)據(jù)被write(當(dāng)E=“H-L”,指令數(shù)據(jù)被寫(xiě)到IR或DR)
- E=高脈沖
- 此時(shí)DB0-DB7=指令碼 */
- void write_cmd(uchar cmd)
- {
- LCD_RS=0;
- LCD_RW=0;
- LCD_EN=0;
- P0=cmd;
- delay1ms(5);
- LCD_EN=1;
- delay1ms(5);
- LCD_EN=0;
- }
- /*設(shè)定顯示位置*/
- void lcd_pos(uchar X, uchar Y)
- {
- uchar pos;
-
- if(X == 0)
- {
- X = 0x80;
- }
- else if(X == 1)
- {
- X = 0x90;
- }
- else if(X == 2)
- {
- X = 0x88;
- }
- else if(X == 3)
- {
- X = 0x98;
- }
- pos = X + Y;
- write_cmd(pos); //顯示地址
- }
-
- /*寫(xiě)顯示數(shù)據(jù)到LCD*/
- /*
- RS=H ——表示DB0-DB7為顯示數(shù)據(jù)
- RW=L ——RW=L,E='H-L',DB0-DB7數(shù)據(jù)被寫(xiě)到IR或DR
- E=高脈沖
- DB0-DB7=顯示數(shù)據(jù) */
- void write_dat(uchar dat)
- {
- LCD_RS=1;
- LCD_RW=0;
- LCD_EN=0;
- P0=dat;
- delay1ms(5);
- LCD_EN=1;
- delay1ms(5);
- LCD_EN=0;
- }
- /*LCD初始化*/
- void lcd_init()
- { uint i;
-
- LCD_PSB=1; //并口方式
- write_cmd(0x30); //基本操作指令
- delay1ms(5);
- write_cmd(0x0c); //打開(kāi)顯示,光標(biāo)關(guān)閉
- delay1ms(5);
- write_cmd(0x01); //清除LCD顯示類(lèi)容
- delay1ms(5);
-
-
- lcd_pos(3,0);
- i=0;
- while(dis4[i]!='\0')
- {
- delay1ms(1);
- write_dat(dis4[i]);
- delay1ms(1);
- i++;
- }
-
- }
- /**********************************18b20************************************************/
- /**********************************18b20************************************************/
-
-
- void Init_DS18B20(void) //初始化
- {
- uchar x=0;
- DQ=1; //DQ先置高
- delay(8); //稍延時(shí)
- DQ=0; //發(fā)送復(fù)位脈沖
- delay(80); //延時(shí)(>480us)
- DQ=1; //拉高數(shù)據(jù)線
- delay(5); //等待(15~60us)
- x=DQ; //用X的值來(lái)判斷初始化有沒(méi)有成功,18B20存在的話X=0,否則X=1
- delay(20);
- }
-
- //**********讀一個(gè)字節(jié)************//
-
- ReadOneChar(void) //主機(jī)數(shù)據(jù)線先從高拉至低電平1us以上,再使數(shù)據(jù)線升為高電平,從而產(chǎn)生讀信號(hào)
- {
- unsigned char i=0; //每個(gè)讀周期最短的持續(xù)時(shí)間為60us,各個(gè)讀周期之間必須有1us以上的高電平恢復(fù)期
- unsigned char dat=0;
- for (i=8;i>0;i--) //一個(gè)字節(jié)有8位
- {
- DQ=1;
- delay(1);
- DQ=0;
- dat>>=1;
- DQ=1;
- if(DQ)
- dat|=0x80;
- delay(4);
- }
- return(dat);
- }
- //*********************** **寫(xiě)一個(gè)字節(jié)**************************//
-
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0; //數(shù)據(jù)線從高電平拉至低電平,產(chǎn)生寫(xiě)起始信號(hào)。15us之內(nèi)將所需寫(xiě)的位送到數(shù)據(jù)線上,
- for(i=8;i>0;i--) //在15~60us之間對(duì)數(shù)據(jù)線進(jìn)行采樣,如果是高電平就寫(xiě)1,低寫(xiě)0發(fā)生。
- {
- DQ=0; //在開(kāi)始另一個(gè)寫(xiě)周期前必須有1us以上的高電平恢復(fù)期。
- DQ=dat&0x01;
- delay(5);
- DQ=1;
- dat>>=1;
- }
- delay(4);
- }
-
- void ReadTemperature(void) //讀溫度值(低位放tempL;高位放tempH;)//
- {
- Init_DS18B20(); //初始化
- WriteOneChar(0xcc); //跳過(guò)讀序列號(hào)的操作
- WriteOneChar(0x44); //啟動(dòng)溫度轉(zhuǎn)換
- delay(125); //轉(zhuǎn)換需要一點(diǎn)時(shí)間,延時(shí)
- Init_DS18B20(); //初始化
- WriteOneChar(0xcc); //跳過(guò)讀序列號(hào)的操作
- WriteOneChar(0xbe); //讀溫度寄存器(頭兩個(gè)值分別為溫度的低位和高位)
- tempL=ReadOneChar(); //讀出溫度的低位LSB
- tempH=ReadOneChar(); //讀出溫度的高位MSB
-
- if(tempH>0x7f) //最高位為1時(shí)溫度是負(fù)
- {
- tempL=~tempL; //補(bǔ)碼轉(zhuǎn)換,取反加一
- tempH=~tempH+1;
- fg=0; //讀取溫度為負(fù)時(shí)fg=0
- }
- sdata = tempL/16+tempH*16; //整數(shù)部分
- xiaoshu1 = (tempL&0x0f)*10/16; //小數(shù)第一位
- xiaoshu2 = (tempL&0x0f)*100/16%10;//小數(shù)第二位
- t[0]=numbr[sdata/10];
- t[1]=numbr[sdata%10];
- t[3]=numbr[xiaoshu1];
- t[4]=numbr[xiaoshu2];
-
- }
- /*****************************************ds3231********************************************/
-
- #define ADDRTW 0xD0 //器件寫(xiě)地址
- #define ADDRTD 0xD1 //器件讀地址
- #define DS3231_SEC 0x00 //秒
- #define DS3231_MIN 0x01 //分
- #define DS3231_HOUR 0x02 //時(shí)
- #define DS3231_DAY 0x03 //星期
- #define DS3231_DATE 0x04 //日
- #define DS3231_MONTH 0x05 //月
- #define DS3231_YEAR 0x06 //年
- //鬧鈴1
- #define DS3231_Al1SEC 0x07 //秒
- #define DS3231_AL1MIN 0x08 //分
- #define DS3231_AL1HOUR 0x09 //時(shí)
- #define DS3231_AL1DAY 0x0A //星期/日
- //鬧鈴2
- #define DS3231_AL2MIN 0x0b //分
- #define DS3231_AL2HOUR 0x0c //時(shí)
- #define DS3231_AL2DAY 0x0d //星期/日
- #define DS3231_CONTROL 0x0e //控制寄存器
- #define DS3231_STATUS 0x0f //狀態(tài)寄存器
- bit ack;
-
-
- uchar BCD2HEX(uchar val) //BCD轉(zhuǎn)換為Byte
- { uchar i;
- i= val&0x0f;
- val >>= 4;
- val &= 0x0f;
- val *= 10;
- i += val;
-
- return i;
- }
-
-
- uchar HEX2BCD(uchar val)//B碼轉(zhuǎn)換為BCD碼
- {
- uchar i,j,k;
-
- i=val/10;
- j=val%10;
- k=j+(i<<4);
- return k;
- }
-
- void Start()
- {
- SDA=1; //發(fā)送起始條件的數(shù)據(jù)信號(hào)
- delay(1);
- SCL=1;
- delay(5); //起始條件建立時(shí)間大于4.7us,延時(shí)
- SDA=0; //發(fā)送起始信號(hào)
- delay(5); // 起始條件鎖定時(shí)間大于4μs
- SCL=0; //鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
- delay(2);
- }
- void Stop()
- {
- SDA=0; //發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)
- delay(1); //發(fā)送結(jié)束條件的時(shí)鐘信號(hào)
- SCL=1; //結(jié)束條件建立時(shí)間大于4us
- delay(5);
-
- SDA=1; //發(fā)送I2C總線結(jié)束信號(hào)
- delay(4);
- }
- /********************************************************/
- /*******************************************************************
- 字節(jié)數(shù)據(jù)發(fā)送函數(shù)
- 函數(shù)原型: void SendByte(uchar Dat);
- 功能: 將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對(duì)
- 此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)
- ack=1 發(fā)送數(shù)據(jù)正常,
- ack=0 被控器無(wú)應(yīng)答或損壞。
- ********************************************************************/
- void SendByte(uchar Dat)
- {
- uchar BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數(shù)據(jù)長(zhǎng)度為8位
- {
- if((Dat<<BitCnt)&0x80)
- SDA=1; //判斷發(fā)送位
- else
- SDA=0;
- delay(1);
- SCL=1; //置時(shí)鐘線為高,通知被控器開(kāi)始接收數(shù)據(jù)位
- delay(5); //保證時(shí)鐘高電平周期大于4μs
- SCL=0;
- }
-
- delay(2);
- SDA=1; //8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位
- delay(2);
- SCL=1;
- delay(3);
- if(SDA==1)
- ack=0;
- else
- ack=1; //判斷是否接收到應(yīng)答信號(hào)
- SCL=0;
- delay(2);
- }
-
- uchar RcvByte() // 功能: 用來(lái)接收從器件傳來(lái)的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號(hào)),發(fā)完后請(qǐng)用應(yīng)答函數(shù)應(yīng)答從機(jī)。
- {
- uchar retc;
- uchar BitCnt;
-
- retc=0;
- SDA=1; //置數(shù)據(jù)線為輸入方式
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- delay(1);
- SCL=0; //置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位
-
- delay(5); //時(shí)鐘低電平周期大于4.7μs
-
- SCL=1; //置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效
- delay(3);
- retc=retc<<1;
- if(SDA==1)
- retc=retc+1; //讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中
- delay(2);
- }
- SCL=0;
- delay(2);
- return(retc);
- }
-
- void I2CACK(bit a) // 功能: 主控器進(jìn)行應(yīng)答信號(hào)(可以是應(yīng)答或非應(yīng)答信號(hào),由位參數(shù)a決定)
- {
-
- if(a==0)
- SDA=0; //在此發(fā)出應(yīng)答或非應(yīng)答信號(hào)
- else
- SDA=1;
- delay(3);
- SCL=1;
-
- delay(5); //時(shí)鐘低電平周期大于4μs
-
- SCL=0; //清時(shí)鐘線,鉗住I2C總線以便繼續(xù)接收
- delay(2);
- }
-
-
-
- uchar I2CRead() /************從DS3231當(dāng)前地址讀一個(gè)字節(jié)************/
- {
- uchar read_data;
- Start();
- SendByte(ADDRTD);
- if(ack==0)
- {
- return(0);
- }
- read_data = RcvByte();
- I2CACK(1);
- Stop();
- return read_data;
- }
-
-
- uchar I2CReadAdd(uchar addr) /************從DS3231指定地址讀一個(gè)字節(jié)************/
- {
- Start();
- SendByte(ADDRTW);
- if(ack==0)
- {
- return(0);
- }
- SendByte(addr);
- if(ack==0)
- {
- return(0);
- }
- return(I2CRead());
- }
- void Readtime() /*********************讀取時(shí)間**********************/
- {
- uchar temp;
- temp=I2CReadAdd(DS3231_SEC);//秒
- sec=BCD2HEX(temp);
-
- temp=I2CReadAdd(DS3231_MIN);//分
- min=BCD2HEX(temp);
-
- temp=I2CReadAdd(DS3231_HOUR); //時(shí)
- hour=BCD2HEX(temp);
-
- temp=I2CReadAdd(DS3231_DATE); //日
- date=BCD2HEX(temp);
-
- temp=I2CReadAdd(DS3231_MONTH); //月
- month=BCD2HEX(temp);
-
- temp=I2CReadAdd(DS3231_YEAR); //年
- year=BCD2HEX(temp);
- }
-
- void InitDS3231() //ds3231初始化
- {SCL=1;
- delay(5);
- SDA=1;
- delay(5);
-
- }
- void TimeDisplay(uchar Dhour,uchar Dmin,uchar Dsec) //時(shí)分秒數(shù)組賦值
- { b[0]=numbr[Dhour / 10]; // 時(shí)十位
- b[1]=numbr[Dhour % 10]; // 時(shí)個(gè)位
- b[4]=numbr[Dmin / 10]; // 分十位
- b[5]=numbr[Dmin % 10]; // 分個(gè)位
- b[8]=numbr[Dsec / 10]; // 秒十位
- b[9]=numbr[Dsec % 10]; // 秒個(gè)位
- }
- void DateDisplay(uchar Dyear,uchar Dmonth,uchar Dday) //年月天數(shù)組賦值
- { a[2]=numbr[Dyear / 10]; // 年十位
- a[3]=numbr[Dyear % 10]; // 年個(gè)位
- a[6]=numbr[Dmonth / 10]; // 月十位
- a[7]=numbr[Dmonth % 10]; // 月個(gè)位
- a[10]=numbr[Dday / 10]; // 天十位
- a[11]=numbr[Dday % 10]; // 天個(gè)位
- }
-
- void Start_I2C()
- {
- SDA=1; //發(fā)送起始條件的數(shù)據(jù)信號(hào)
- delay(1);
- SCL=1;
- delay(5); //起始條件建立時(shí)間大于4.7us,延時(shí)
-
- SDA=0; //發(fā)送起始信號(hào)
- delay(5); // 起始條件鎖定時(shí)間大于4μs
-
- SCL=0; //鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
- delay(2);
- }
-
- void Stop_I2C()
- {
- SDA=0; //發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)
- delay(1); //發(fā)送結(jié)束條件的時(shí)鐘信號(hào)
- SCL=1; //結(jié)束條件建立時(shí)間大于4us
- delay(5);
-
- SDA=1; //發(fā)送I2C總線結(jié)束信號(hào)
- delay(4);
- }
-
- uchar write_byte(uchar addr, uchar write_data)
- {
- Start_I2C();
- SendByte(ADDRTW); //////*******************************************************************///////////
- if (ack == 0)
- return 0;
-
- SendByte(addr);
- if (ack == 0)
- return 0;
-
- SendByte(write_data);
- if (ack == 0)
- return 0;
-
- Stop_I2C();
- delay1ms(10);
- return 1;
- }
-
- void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec)
- { uchar temp=0;
-
- temp=HEX2BCD(yea);
- write_byte(DS3231_YEAR,temp); //修改年
-
- temp=HEX2BCD(mon);
- write_byte(DS3231_MONTH,temp); //修改月
-
- temp=HEX2BCD(da); /////////////////////
- write_byte(DS3231_DATE,temp); //修改日
-
- temp=HEX2BCD(hou);
- write_byte(DS3231_HOUR,temp); //修改時(shí)
-
- temp=HEX2BCD(min);
- write_byte(DS3231_MIN,temp); //修改分
-
- temp=HEX2BCD(sec);
- write_byte(DS3231_SEC,temp); //修改秒
- }
-
-
-
-
-
- void xianshi(void)
- {
-
- { uint i;
-
-
- TimeDisplay(hour,min,sec);
- lcd_pos(1,1); //時(shí)間
- i=0;
- while(b[i]!='\0')
- {
- delay1ms(1);
- write_dat(b[i]);
- delay1ms(1);
- i++;
- }
-
- DateDisplay(year,month,date); //顯示日期
- delay1ms(1);
- lcd_pos(0,0);
- i=0;
- while(a[i]!='\0')
- {
- delay1ms(1);
- write_dat(a[i]);
- delay1ms(1);
- i++;
- }
- ReadTemperature(); //顯示溫度
- delay1ms(1);
- lcd_pos(2,1);
- delay1ms(1);
- i=0;
- while(t[i]!='\0')
- {
- delay1ms(1);
- write_dat(t[i]);
- delay1ms(2);
- i++;
- }
- }
- }
-
- void shuaxin(void)
- { uint i;
- TimeDisplay(hour,min,sec);
- lcd_pos(1,1); //時(shí)間
- i=0;
- while(b[i]!='\0')
- {
- delay1ms(1);
- write_dat(b[i]);
- delay1ms(1);
- i++;
- }
-
- DateDisplay(year,month,date); //顯示日期
- delay1ms(1);
- lcd_pos(0,0);
- i=0;
- while(a[i]!='\0')
- {
- delay1ms(1);
- write_dat(a[i]);
- delay1ms(1);
- i++;
- }
- }
-
-
-
- void sotp(void)
- {
- uint i;
-
- while(1)
- {
- duan1: if(K1==0)
- {
- delay1ms(100);
- if(K1==0)
- {
- Readtime();
- shuaxin();
- i=0;
- goto duan2;
-
- }
- }
- else
- {goto duan5;}
-
- duan2: if(K2==0)
- {
- delay1ms(100);
- if(K2==0)
- {
- i++;
- if(i>6){i=0;}
- shuaxin();
- }
- }
- switch(i)
- {
- case 0: if(K3==0){delay1ms(100);if(K3==0){year=year+1;} if(year>=100){year=0;} shuaxin();} break;
- case 1: if(K3==0){delay1ms(100);if(K3==0){month=month+1;} if(month>=13){month=0;} shuaxin();} break;
- case 2: if(K3==0){delay1ms(100);if(K3==0){date=date+1;} if(date>=32){date=0;} shuaxin();} break;
- case 3: if(K3==0){delay1ms(100);if(K3==0){hour=hour+1;} if(hour>=25){hour=0;} shuaxin();} break;
- case 4: if(K3==0){delay1ms(100);if(K3==0){min=min+1;} if(min>=61){min=0;} shuaxin();} break;
- case 5: if(K3==0){delay1ms(100);if(K3==0){sec=sec+1;} if(sec>=61){sec=0;} shuaxin();} break;
- }
-
-
- duan4: if(K4==0)
- {
- delay1ms(100);
- if(K4==0)
- {
- ModifyTime(year,month,date,hour,min,sec);
- goto duan5; ///////////////////*******************//////////
- }
- }
-
- else
- {goto duan2;}
-
-
-
-
-
-
-
- duan5: Readtime();
- xianshi();
- }
-
- }
-
-
-
-
- main() /*主程序*/
- {
-
-
- lcd_init();
- delay1ms(5);
- InitDS3231();
- delay1ms(5);
- delay1ms(5);
- sotp();
- }
復(fù)制代碼
以上的Word格式文檔51黑下載地址:
ds3231,51例程.7z
(2.83 MB, 下載次數(shù): 94)
2019-8-2 17:15 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|