找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10051|回復(fù): 18
收起左側(cè)

DS3231溫度讀取實(shí)驗(yàn) 附單片機(jī)源程序

  [復(fù)制鏈接]
ID:362076 發(fā)表于 2019-2-12 17:21 | 顯示全部樓層 |閱讀模式
本帖最后由 凌凈清河 于 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í)際上溫度值的刷新速度還是很令人滿意(用手按住芯片,溫度值更改速度很快,下面的測試圖片是恒溫下檢測的,故無變化)。
測試程序:
  1. #include<STC15.H>
  2. #include"stdio.h"
  3. #include<intrins.h>
  4. //位定義
  5. sbit DS3231_SDA=P3^3;
  6. sbit DS3231_SCL=P3^2;

  7. //運(yùn)行數(shù)組
  8. unsigned char DS3231_Time_Buffer[7]={0x00,0x48,0x11,0x02,0x12,0x02,0x19};
  9. unsigned char temp[2]={0,0};
  10. char buf[20]={0};
  11. //運(yùn)行標(biāo)志位
  12. bit busy=0;
  13. //運(yùn)行變量
  14. float v;

  15. /*##############################################################################
  16. 編寫/測試:凌凈清河
  17. 日期:2019年2月12日
  18. 測試平臺:IAP15W4K58S4

  19. 鳴謝:DS3231部分驅(qū)動(dòng)函數(shù)借用了51黑論壇上某位的程序,但是時(shí)間太久忘記是誰的了。
  20. 并未修改原作者的寫法,如果原作者認(rèn)出,鄙人在此表示感謝,或可聯(lián)系我提名。
  21. ##############################################################################*/

  22. /*###################以下為給DS3231定義的IIC通信函數(shù)################*/
  23. void DS3231_Delay()//使用空操作進(jìn)行短暫的延時(shí)
  24. {
  25.         _nop_();
  26.         _nop_();
  27.         _nop_();
  28.         _nop_();
  29. }

  30. void DS3231_IIC_Start()//IIC總線的開始信號
  31. {
  32.         DS3231_SCL=1;
  33.         DS3231_SDA=1;
  34.         DS3231_Delay();
  35.         DS3231_SDA=0;
  36.         DS3231_Delay();
  37.         DS3231_SCL=0;
  38. }

  39. void DS3231_IIC_Stop()//IIC總線的停止信號
  40. {
  41.         DS3231_SCL=0;
  42.         DS3231_SDA=0;
  43.         DS3231_Delay();
  44.         DS3231_SCL=1;
  45.         DS3231_Delay();
  46.         DS3231_SDA=1;
  47.         DS3231_Delay();
  48. }

  49. bit DS3231_IIC_Send_Byte(unsigned char dat)//寫操作
  50. {
  51.         unsigned char mask;//定義一個(gè)掩碼用于進(jìn)行按位發(fā)送數(shù)據(jù)的操作
  52.         bit ack;

  53.         for(mask=0x80;mask!=0;mask>>=1)
  54.         {
  55.                 if((mask&dat)==0)
  56.                         DS3231_SDA=0;
  57.                 else
  58.                         DS3231_SDA=1;
  59.                 DS3231_Delay();
  60.                 DS3231_SCL=1;
  61.                 DS3231_Delay();
  62.                 DS3231_SCL=0;
  63.         }
  64.         DS3231_SDA=1;
  65.         DS3231_Delay();
  66.         DS3231_SCL=1;
  67.         ack=DS3231_SDA;
  68.         DS3231_Delay();
  69.         DS3231_SCL=0;

  70.         return (~ack);
  71. }

  72. unsigned char DS3231_IIC_Read_Byte_NAK()//讀操作+非應(yīng)答
  73. {
  74.         unsigned char mask;//定義一個(gè)用于累加的位存儲臨時(shí)變量
  75.         unsigned char dat;

  76.         DS3231_SDA=1;
  77.         for(mask=0x80;mask!=0;mask>>=1)
  78.         {
  79.                 DS3231_Delay();
  80.                 DS3231_SCL=1;
  81.                 if(DS3231_SDA==0)
  82.                         dat&=~mask;
  83.                 else
  84.                         dat|=mask;
  85.                 DS3231_Delay();
  86.                 DS3231_SCL=0;
  87.         }
  88.         DS3231_SDA=1;
  89.         DS3231_Delay();
  90.         DS3231_SCL=1;
  91.         DS3231_Delay();
  92.         DS3231_SCL=0;

  93.         return dat;
  94. }

  95. unsigned char DS3231_IIC_Read_Byte_ACK()//讀操作+應(yīng)答
  96. {
  97.         unsigned char mask;//定義一個(gè)用于累加的位存儲臨時(shí)變量
  98.         unsigned char dat;

  99.         DS3231_SDA=1;
  100.         for(mask=0x80;mask!=0;mask>>=1)
  101.         {
  102.                 DS3231_Delay();
  103.                 DS3231_SCL=1;
  104.                 if(DS3231_SDA==0)
  105.                         dat&=~mask;
  106.                 else
  107.                         dat|=mask;
  108.                 DS3231_Delay();
  109.                 DS3231_SCL=0;
  110.         }
  111.         DS3231_SDA=0;
  112.         DS3231_Delay();
  113.         DS3231_SCL=1;
  114.         DS3231_Delay();
  115.         DS3231_SCL=0;

  116.         return dat;
  117. }
  118. /*#################以下為給DS3231封裝的寄存器通信函數(shù)###############*/

  119. void DS3231_Read_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//讀EEPROM中多個(gè)字節(jié)
  120. {
  121.         do{
  122.                 DS3231_IIC_Start();
  123.                 if(DS3231_IIC_Send_Byte(0xD0))
  124.                 {
  125.                         break;
  126.                 }
  127.                 DS3231_IIC_Stop();
  128.           }while(1);
  129.         DS3231_IIC_Send_Byte(addr);
  130.         DS3231_IIC_Start();
  131.         DS3231_IIC_Send_Byte((0xD0)|0x01);//尋址,讀操作
  132.         while(len>1)
  133.         {
  134.                 *buf++=DS3231_IIC_Read_Byte_ACK();
  135.                 len--;
  136.         }
  137.         *buf=DS3231_IIC_Read_Byte_NAK();//讀一個(gè)字節(jié)
  138.         DS3231_IIC_Stop();
  139. }

  140. void DS3231_Write_Registers(unsigned char *buf,unsigned char addr,unsigned char len)//寫寄存器,傳入待寫入數(shù)組
  141. {
  142.         while(len>0)
  143.         {        
  144.                 do{
  145.                         DS3231_IIC_Start();
  146.                         if(DS3231_IIC_Send_Byte(0xD0))
  147.                         {
  148.                                 break;
  149.                         }
  150.                         DS3231_IIC_Stop();
  151.                   }while(1);

  152.                 DS3231_IIC_Send_Byte(addr);
  153.                 while(len>0)
  154.                 {
  155.                         DS3231_IIC_Send_Byte(*buf++);
  156.                         len--;
  157.                         addr++;
  158.                         if((addr&0x07)==0)
  159.                         {
  160.                                 break;
  161.                         }
  162.                 }
  163.                 DS3231_IIC_Stop();
  164.         }
  165. }

  166. void SendData(unsigned char dat)//串口1發(fā)送一個(gè)字節(jié)數(shù)據(jù)
  167. {
  168.         while(busy);
  169.         busy=1;
  170.         SBUF=dat;
  171. }

  172. void SendString(char *p)//串口發(fā)送一個(gè)字符串
  173. {
  174.         while(*p!='\0')
  175.         {
  176.                 SendData(*p);
  177.                 p++;
  178.         }
  179. }

  180. void UartInit(void)                //9600bps@11.0592MHz
  181. {
  182.         SCON = 0x50;                //8位數(shù)據(jù),可變波特率
  183.         AUXR |= 0x40;                //定時(shí)器1時(shí)鐘為Fosc,即1T
  184.         AUXR &= 0xFE;                //串口1選擇定時(shí)器1為波特率發(fā)生器
  185.         TMOD &= 0x0F;                //設(shè)定定時(shí)器1為16位自動(dòng)重裝方式
  186.         TL1 = 0xE0;                //設(shè)定定時(shí)初值
  187.         TH1 = 0xFE;                //設(shè)定定時(shí)初值
  188.         ET1 = 0;                //禁止定時(shí)器1中斷
  189.         TR1 = 1;                //啟動(dòng)定時(shí)器1
  190. }

  191. void delay(unsigned long int i)//延時(shí)函數(shù)
  192. {
  193.         while(i--);
  194. }

  195. void main()
  196. {
  197.         P3M1=0x00;
  198.         P3M0=0x00;//IO初始化,這個(gè)準(zhǔn)雙向的初始化操作是為STC15W4K32S4系列單片機(jī)特別準(zhǔn)備的
  199.         UartInit();//串口初始化
  200.         EA=1;//開總中斷
  201.         ES=1;//開串口中斷
  202.         DS3231_Write_Registers(DS3231_Time_Buffer,0x00,7);//向器件寫入有效的IIC地址,以保證驅(qū)動(dòng)振蕩器起振,防止讀出初始值0℃
  203.         while(1)
  204.         {
  205.                 DS3231_Read_Registers(temp,0x11,2);
  206.                 v=temp[0]*1.0+(temp[1]>>6)*0.25;//按照數(shù)據(jù)格式,將寄存器中的值放入一個(gè)有符號的float型數(shù)據(jù),就不必糾結(jié)于補(bǔ)碼的正負(fù)判別和轉(zhuǎn)換了
  207.                 sprintf(buf,"溫度值為:%6.2f",v);//字符串拼接輸出,用于串口觀察數(shù)據(jù)
  208.                 SendString(buf);//發(fā)送組合好的字符串
  209.                 delay(100000);//延時(shí)等待,以防止串口信息爆炸>v<
  210.         }
  211. }

  212. void UART() interrupt 4//串口中斷服務(wù)函數(shù)
  213. {
  214.         if(RI)//接收標(biāo)志位(未使用)
  215.         {
  216.                 RI=0;
  217.         }
  218.         
  219.         if(TI)//發(fā)送標(biāo)志位
  220.         {
  221.                 TI=0;
  222.                 busy=0;
  223.         }
  224. }
復(fù)制代碼


測試時(shí)的截圖:
測試截圖.png
測試中,對比室內(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)
【DS3231英文手冊】:英文手冊比中文的在某些細(xì)節(jié)描述更詳盡
DS3231.pdf (361.01 KB, 下載次數(shù): 36)
【DS3231中文手冊】
DS3231中文手冊.pdf (449.27 KB, 下載次數(shù): 85)

下載注明:可以回復(fù)本帖得到黑幣補(bǔ)貼(評分),本人現(xiàn)在最高能給15黑幣/帖,多次回復(fù)亦有補(bǔ)貼。


評分

參與人數(shù) 3黑幣 +70 收起 理由
NPC-1024 + 5 凌:由于站點(diǎn)對評分機(jī)制的修改,帖子不再給.
tieq1952 + 15 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

ID:253767 發(fā)表于 2019-2-13 08:00 | 顯示全部樓層
謝謝分享!!!

評分

參與人數(shù) 1黑幣 +15 收起 理由
凌凈清河 + 15 黑幣補(bǔ)貼

查看全部評分

回復(fù)

使用道具 舉報(bào)

ID:448212 發(fā)表于 2019-5-19 14:12 | 顯示全部樓層
感謝!學(xué)習(xí)了!
回復(fù)

使用道具 舉報(bào)

ID:184096 發(fā)表于 2019-5-20 12:12 | 顯示全部樓層
感謝了樓主 學(xué)到了
回復(fù)

使用道具 舉報(bào)

ID:581125 發(fā)表于 2019-7-9 18:40 | 顯示全部樓層
很強(qiáng)很強(qiáng)很強(qiáng)學(xué)到了感謝樓主
回復(fù)

使用道具 舉報(bào)

ID:483407 發(fā)表于 2019-7-9 21:45 | 顯示全部樓層
串口助手用得不錯(cuò),學(xué)習(xí)了。
回復(fù)

使用道具 舉報(bào)

ID:585103 發(fā)表于 2019-7-16 14:42 | 顯示全部樓層
謝謝分享。
回復(fù)

使用道具 舉報(bào)

ID:585374 發(fā)表于 2019-7-16 20:55 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:371527 發(fā)表于 2019-7-19 09:25 | 顯示全部樓層
多字節(jié)操作子程序清晰,讀取溫度運(yùn)算的方式比其它判符號程序簡潔
回復(fù)

使用道具 舉報(bào)

ID:111376 發(fā)表于 2019-8-13 11:02 | 顯示全部樓層
感謝樓主的無私奉獻(xiàn)精神
回復(fù)

使用道具 舉報(bào)

ID:91162 發(fā)表于 2019-12-22 16:01 | 顯示全部樓層
正想做一個(gè)精準(zhǔn)時(shí)鐘,謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

ID:4306 發(fā)表于 2020-1-18 20:47 | 顯示全部樓層
正在學(xué)習(xí)中,謝謝
回復(fù)

使用道具 舉報(bào)

ID:138937 發(fā)表于 2020-6-19 14:45 | 顯示全部樓層

謝謝分享。
回復(fù)

使用道具 舉報(bào)

ID:702127 發(fā)表于 2020-8-4 07:36 | 顯示全部樓層
剛弄好DS3231的時(shí)間,最近在弄溫度,總是出錯(cuò),看了你的貼子,嗯,找到錯(cuò)誤原因了,感謝
回復(fù)

使用道具 舉報(bào)

ID:491923 發(fā)表于 2021-1-3 11:37 | 顯示全部樓層
剛剛買了1個(gè)模塊,正在學(xué)習(xí)使用中,這個(gè)資料太有用了 謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

ID:90970 發(fā)表于 2021-4-15 13:26 | 顯示全部樓層
看看這個(gè)溫度是不是能用
回復(fù)

使用道具 舉報(bào)

ID:884042 發(fā)表于 2021-7-16 14:24 | 顯示全部樓層
樓主,我是直接讀取11H和12H這兩個(gè)寄存器的值然后顯示到屏幕上,在顯示小數(shù)點(diǎn)的,照樣用,應(yīng)該不要建變量吧?
回復(fù)

使用道具 舉報(bào)

ID:884042 發(fā)表于 2021-7-16 14:26 | 顯示全部樓層
我是這樣寫的:
OLED_P8x16(0,6,DS3231Time[7]/10);
          OLED_P8x16(8,6,DS3231Time[7]%10);
我通過溫度讀取函數(shù)直接將溫度值顯示在OLED屏幕上的
回復(fù)

使用道具 舉報(bào)

ID:972563 發(fā)表于 2021-11-19 11:18 | 顯示全部樓層
ds3231的溫度可是有點(diǎn)不靠譜,畢竟手冊上也是正負(fù)3度的誤差,3度的誤差不小了,沒辦法只能改用DS18B20
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表