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