欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
DS3231溫度讀取實驗 附單片機源程序
[打印本頁]
作者:
凌凈清河
時間:
2019-2-12 17:21
標題:
DS3231溫度讀取實驗 附單片機源程序
本帖最后由 凌凈清河 于 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黑幣/帖,多次回復亦有補貼。
作者:
tieq1952
時間:
2019-2-13 08:00
謝謝分享!!!
作者:
persistence
時間:
2019-5-19 14:12
感謝!!學習了!
作者:
big土坑
時間:
2019-5-20 12:12
感謝了樓主 學到了
作者:
大魔導師劉秀
時間:
2019-7-9 18:40
很強很強很強學到了感謝樓主
作者:
wangwing
時間:
2019-7-9 21:45
串口助手用得不錯,學習了。
作者:
sdlovelife
時間:
2019-7-16 14:42
謝謝分享。
作者:
wangtttt
時間:
2019-7-16 20:55
謝謝分享
作者:
1113634577
時間:
2019-7-19 09:25
多字節操作子程序清晰,讀取溫度運算的方式比其它判符號程序簡潔
作者:
stlong
時間:
2019-8-13 11:02
感謝樓主的無私奉獻精神
作者:
流淌的歌聲
時間:
2019-12-22 16:01
正想做一個精準時鐘,謝謝樓主分享
作者:
wdh9203
時間:
2020-1-18 20:47
正在學習中,謝謝
作者:
逍遙宿元
時間:
2020-6-19 14:45
謝謝分享。
作者:
ii11nnocent
時間:
2020-8-4 07:36
剛弄好DS3231的時間,最近在弄溫度,總是出錯,看了你的貼子,嗯,找到錯誤原因了,感謝
作者:
benniu
時間:
2021-1-3 11:37
剛剛買了1個模塊,正在學習使用中,這個資料太有用了 謝謝樓主分享
作者:
stone528
時間:
2021-4-15 13:26
看看這個溫度是不是能用
作者:
xjx51
時間:
2021-7-16 14:24
樓主,我是直接讀取11H和12H這兩個寄存器的值然后顯示到屏幕上,在顯示小數點的,照樣用,應該不要建變量吧?
作者:
xjx51
時間:
2021-7-16 14:26
我是這樣寫的:
OLED_P8x16(0,6,DS3231Time[7]/10);
OLED_P8x16(8,6,DS3231Time[7]%10);
我通過溫度讀取函數直接將溫度值顯示在OLED屏幕上的
作者:
土老冒527
時間:
2021-11-19 11:18
ds3231的溫度可是有點不靠譜,畢竟手冊上也是正負3度的誤差,3度的誤差不小了,沒辦法只能改用DS18B20
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1