|
本帖最后由 凌凈清河 于 2019-2-13 19:46 編輯
DS3231作為一個(gè)走時(shí)精準(zhǔn)的RTC芯片,內(nèi)部帶有溫度補(bǔ)償電路,此例將讀取其中11H和12H寄存器,提取測得的溫度值并傳送到串口輸出。
類似程序網(wǎng)上非常之多,不再贅述,在此重新提說幾處需要注意的地方。
1.根據(jù)DS3231的芯片手冊,其溫度傳感器的精度為±3℃,畢竟不是專用的溫度傳感器,在使用中可以作為一個(gè)參考,且僅此而已。
2.根據(jù)DS3231的芯片手冊,其溫度分辨率為±0.25℃,所以其小數(shù)部分讀出的值只能是.00、.25、.50、.75這四種,如果讀出的值不是這四種,則數(shù)據(jù)處理有誤。
3.本實(shí)驗(yàn)使用一個(gè)float型數(shù)據(jù)直接接收了轉(zhuǎn)換的溫度值,沒有對補(bǔ)碼的符號位進(jìn)行判斷等。
注明:本程序沒有使用CONV位進(jìn)行強(qiáng)制轉(zhuǎn)換,但是實(shí)際上溫度值的刷新速度還是很令人滿意(用手按住芯片,溫度值更改速度很快,下面的測試圖片是恒溫下檢測的,故無變化)。
測試程序:
- #include<STC15.H>
- #include"stdio.h"
- #include<intrins.h>
- //位定義
- sbit DS3231_SDA=P3^3;
- sbit DS3231_SCL=P3^2;
- //運(yùn)行數(shù)組
- unsigned char DS3231_Time_Buffer[7]={0x00,0x48,0x11,0x02,0x12,0x02,0x19};
- unsigned char temp[2]={0,0};
- char buf[20]={0};
- //運(yùn)行標(biāo)志位
- bit busy=0;
- //運(yùn)行變量
- float v;
- /*##############################################################################
- 編寫/測試:凌凈清河
- 日期:2019年2月12日
- 測試平臺:IAP15W4K58S4
- 鳴謝:DS3231部分驅(qū)動(dòng)函數(shù)借用了51黑論壇上某位的程序,但是時(shí)間太久忘記是誰的了。
- 并未修改原作者的寫法,如果原作者認(rèn)出,鄙人在此表示感謝,或可聯(lián)系我提名。
- ##############################################################################*/
- /*###################以下為給DS3231定義的IIC通信函數(shù)################*/
- void DS3231_Delay()//使用空操作進(jìn)行短暫的延時(shí)
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- void DS3231_IIC_Start()//IIC總線的開始信號
- {
- DS3231_SCL=1;
- DS3231_SDA=1;
- DS3231_Delay();
- DS3231_SDA=0;
- DS3231_Delay();
- DS3231_SCL=0;
- }
- void DS3231_IIC_Stop()//IIC總線的停止信號
- {
- DS3231_SCL=0;
- DS3231_SDA=0;
- DS3231_Delay();
- DS3231_SCL=1;
- DS3231_Delay();
- DS3231_SDA=1;
- DS3231_Delay();
- }
- bit DS3231_IIC_Send_Byte(unsigned char dat)//寫操作
- {
- unsigned char mask;//定義一個(gè)掩碼用于進(jìn)行按位發(fā)送數(shù)據(jù)的操作
- bit ack;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if((mask&dat)==0)
- DS3231_SDA=0;
- else
- DS3231_SDA=1;
- DS3231_Delay();
- DS3231_SCL=1;
- DS3231_Delay();
- DS3231_SCL=0;
- }
- DS3231_SDA=1;
- DS3231_Delay();
- DS3231_SCL=1;
- ack=DS3231_SDA;
- DS3231_Delay();
- DS3231_SCL=0;
- return (~ack);
- }
- unsigned char DS3231_IIC_Read_Byte_NAK()//讀操作+非應(yīng)答
- {
- unsigned char mask;//定義一個(gè)用于累加的位存儲臨時(shí)變量
- unsigned char dat;
- DS3231_SDA=1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- DS3231_Delay();
- DS3231_SCL=1;
- if(DS3231_SDA==0)
- dat&=~mask;
- else
- dat|=mask;
- DS3231_Delay();
- DS3231_SCL=0;
- }
- DS3231_SDA=1;
- DS3231_Delay();
- DS3231_SCL=1;
- DS3231_Delay();
- DS3231_SCL=0;
- return dat;
- }
- unsigned char DS3231_IIC_Read_Byte_ACK()//讀操作+應(yīng)答
- {
- unsigned char mask;//定義一個(gè)用于累加的位存儲臨時(shí)變量
- unsigned char dat;
- DS3231_SDA=1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- DS3231_Delay();
- DS3231_SCL=1;
- if(DS3231_SDA==0)
- dat&=~mask;
- else
- dat|=mask;
- DS3231_Delay();
- DS3231_SCL=0;
- }
- DS3231_SDA=0;
- DS3231_Delay();
- DS3231_SCL=1;
- DS3231_Delay();
- DS3231_SCL=0;
- return dat;
- }
- /*#################以下為給DS3231封裝的寄存器通信函數(shù)###############*/
- void DS3231_Read_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//讀EEPROM中多個(gè)字節(jié)
- {
- do{
- DS3231_IIC_Start();
- if(DS3231_IIC_Send_Byte(0xD0))
- {
- break;
- }
- DS3231_IIC_Stop();
- }while(1);
- DS3231_IIC_Send_Byte(addr);
- DS3231_IIC_Start();
- DS3231_IIC_Send_Byte((0xD0)|0x01);//尋址,讀操作
- while(len>1)
- {
- *buf++=DS3231_IIC_Read_Byte_ACK();
- len--;
- }
- *buf=DS3231_IIC_Read_Byte_NAK();//讀一個(gè)字節(jié)
- DS3231_IIC_Stop();
- }
- void DS3231_Write_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//寫寄存器,傳入待寫入數(shù)組
- {
- while(len>0)
- {
- do{
- DS3231_IIC_Start();
- if(DS3231_IIC_Send_Byte(0xD0))
- {
- break;
- }
- DS3231_IIC_Stop();
- }while(1);
- DS3231_IIC_Send_Byte(addr);
- while(len>0)
- {
- DS3231_IIC_Send_Byte(*buf++);
- len--;
- addr++;
- if((addr&0x07)==0)
- {
- break;
- }
- }
- DS3231_IIC_Stop();
- }
- }
- void SendData(unsigned char dat)//串口1發(fā)送一個(gè)字節(jié)數(shù)據(jù)
- {
- while(busy);
- busy=1;
- SBUF=dat;
- }
- void SendString(char *p)//串口發(fā)送一個(gè)字符串
- {
- while(*p!='\0')
- {
- SendData(*p);
- p++;
- }
- }
- void UartInit(void) //9600bps@11.0592MHz
- {
- SCON = 0x50; //8位數(shù)據(jù),可變波特率
- AUXR |= 0x40; //定時(shí)器1時(shí)鐘為Fosc,即1T
- AUXR &= 0xFE; //串口1選擇定時(shí)器1為波特率發(fā)生器
- TMOD &= 0x0F; //設(shè)定定時(shí)器1為16位自動(dòng)重裝方式
- TL1 = 0xE0; //設(shè)定定時(shí)初值
- TH1 = 0xFE; //設(shè)定定時(shí)初值
- ET1 = 0; //禁止定時(shí)器1中斷
- TR1 = 1; //啟動(dòng)定時(shí)器1
- }
- void delay(unsigned long int i)//延時(shí)函數(shù)
- {
- while(i--);
- }
- void main()
- {
- P3M1=0x00;
- P3M0=0x00;//IO初始化,這個(gè)準(zhǔn)雙向的初始化操作是為STC15W4K32S4系列單片機(jī)特別準(zhǔn)備的
- UartInit();//串口初始化
- EA=1;//開總中斷
- ES=1;//開串口中斷
- DS3231_Write_Registers(DS3231_Time_Buffer,0x00,7);//向器件寫入有效的IIC地址,以保證驅(qū)動(dòng)振蕩器起振,防止讀出初始值0℃
- while(1)
- {
- DS3231_Read_Registers(temp,0x11,2);
- v=temp[0]*1.0+(temp[1]>>6)*0.25;//按照數(shù)據(jù)格式,將寄存器中的值放入一個(gè)有符號的float型數(shù)據(jù),就不必糾結(jié)于補(bǔ)碼的正負(fù)判別和轉(zhuǎn)換了
- sprintf(buf,"溫度值為:%6.2f",v);//字符串拼接輸出,用于串口觀察數(shù)據(jù)
- SendString(buf);//發(fā)送組合好的字符串
- delay(100000);//延時(shí)等待,以防止串口信息爆炸>v<
- }
- }
- void UART() interrupt 4//串口中斷服務(wù)函數(shù)
- {
- if(RI)//接收標(biāo)志位(未使用)
- {
- RI=0;
- }
-
- if(TI)//發(fā)送標(biāo)志位
- {
- TI=0;
- busy=0;
- }
- }
復(fù)制代碼
測試時(shí)的截圖:
測試中,對比室內(nèi)的酒精溫度計(jì),該轉(zhuǎn)換值偏大了約1.75℃
相關(guān)文件如下:
【測試工程】:工程中的延時(shí)函數(shù)形參編寫時(shí)出了一個(gè)小紕漏,應(yīng)該改成ulong型,并更改相應(yīng)實(shí)參值
DS3231溫度讀取 凌凈清河.zip
(99.37 KB, 下載次數(shù): 116)
2019-2-12 17:18 上傳
點(diǎn)擊文件名下載附件
【DS3231英文手冊】:英文手冊比中文的在某些細(xì)節(jié)描述更詳盡
DS3231.pdf
(361.01 KB, 下載次數(shù): 36)
2019-2-12 17:19 上傳
點(diǎn)擊文件名下載附件
【DS3231中文手冊】
DS3231中文手冊.pdf
(449.27 KB, 下載次數(shù): 85)
2019-2-12 17:19 上傳
點(diǎn)擊文件名下載附件
下載注明:可以回復(fù)本帖得到黑幣補(bǔ)貼(評分),本人現(xiàn)在最高能給15黑幣/帖,多次回復(fù)亦有補(bǔ)貼。
|
評分
-
查看全部評分
|