NTC热敏电阻温度采集与adc转换
前言:
ntc熱敏電阻的R值是10k,B值是3950
使用的是STM32F103RCT6的ADC
文章目錄
- 1.電路理論
- 2. NTC熱敏電阻阻值與溫度之間的轉換
- 3.NTC熱敏電阻溫度采集與adc轉換
其中最主要的是
溫度變化,引起了熱敏電阻的變化,然后導致的電壓的變化,從而導致了adc的值發生改變,所以核心變成了,怎樣根據adc值得到溫度值
1.電路理論
不要問我圖為啥是這個樣子,這是硬件工程師畫的板子
其中R_ntc指的是熱敏電阻,R1是個平衡電阻,電容不知道干啥子用的,覺得是防止信號干擾,但是電容并不影響理解,v_out就是ADC的輸出
每次熱敏電阻檢測到溫度變化的時候,輸出電壓都會隨之改變,通常使用分壓器
由于是串聯電路,電流相等,分壓,因此可得到公式
Vout/Rntc=VCC/(Rntc+R1)V_{out} /R_{ntc} = V_{CC}/(R_{ntc}+R_{1})Vout?/Rntc?=VCC?/(Rntc?+R1?)
由此可以得到:
VCC/Vout=(Rntc+R1)/RntcV_{CC}/V_{out} = (R_{ntc} + R_{1})/R_{ntc}VCC?/Vout?=(Rntc?+R1?)/Rntc?
在數學上成立下式:
Dmax/Dout=(Rntc+R1)/RntcD_{max}/D_{out} = (R_{ntc} + R_{1})/R_{ntc}Dmax?/Dout?=(Rntc?+R1?)/Rntc?
其中Dmax指的是最大的ADC值也就是在3.3V的時候ADC等于4096,Dout也就是實際電壓輸出的ADC值。
所以我們要得到的就變成了電阻與溫度之間的對應關系
2. NTC熱敏電阻阻值與溫度之間的轉換
有一個這樣子的公式
Rt=R?e(B?(1/T1?1/T2))Rt = R*e^{(B*{(1/T1-1/T2)})}Rt=R?e(B?(1/T1?1/T2))
其中:
Rt就是隨著溫度變化阻值
R就是25℃時的阻值,也就是開頭說的10k
B值等于3950
T1:指的時開爾文溫度等于273.15+熱敏電阻當前阻值對應的攝氏度
T2:273.15+25
看到網上有很多種辦法,最常規的一種就是寫代碼,加一個math庫
但是最后發現最好的辦法其實是EXCEL表,如下
最上面紅色方框是公式,下面紅色框中可以發現當25攝氏度時,阻值等于10k,溫度與阻值的變化曲線如下:
看看大致曲線就行了,其實靈敏度就沒那么好
電阻值與ADC的對應關系就是
Dmax/Dout=(Rntc+R1)/RntcD_{max}/D_{out} = (R_{ntc} + R_{1})/R_{ntc}Dmax?/Dout?=(Rntc?+R1?)/Rntc?
所以就得到了ADC值對應的溫度。ADC值得到的方式也是通過excel表計算得到
關系曲線如下:
3.NTC熱敏電阻溫度采集與adc轉換
這里是重點部分了
首先是ADC相關函數,這里我用的是PC4端口,主要是想用用新的,對應的通道關系如下:
所以PC4對應的通道14,使用的是ADC1,關于ADC的配置方式可以看我的另一篇博客【STM32】學習筆記之ADC(模擬/數字轉換)
下面是我的adc.c文件中的內容:(將溫度與adc值的對應關系保存在數組中,得到adc值之后只要在數組中查找,沒有考慮復雜度,要優化的話,查找算法可以改成更快的二分法查找,快速查找等等,如果得到的adc值在數組中沒有對應溫度,就取那個相近的溫度值)
#include "adc.h" #include "delay.h"const u16 ADC_NTC[NTC_ADC_MAX] = {2048 ,2043 ,2039 ,2034 ,2030 ,2025 ,2021 ,2016 ,2012 ,2007, //25-25.92003 ,1998 ,1994 ,1989 ,1985 ,1980 ,1976 ,1971 ,1967 ,1962, //26-26.91958 ,1953 ,1949 ,1944 ,1940 ,1935 ,1931 ,1926 ,1922 ,1917, //27-27.91913 ,1909 ,1904 ,1900 ,1895 ,1891 ,1886 ,1882 ,1878 ,1873, //28-28.91869 ,1864 ,1860 ,1856 ,1851 ,1847 ,1843 ,1838 ,1834 ,1829, //29-29.91825 ,1821 ,1816 ,1812 ,1808 ,1803 ,1799 ,1795 ,1790 ,1786, //30-30.91782 ,1778 ,1773 ,1769 ,1765 ,1760 ,1756 ,1752 ,1748 ,1743, //31-31.91739 ,1735 ,1731 ,1726 ,1722 ,1718 ,1714 ,1710 ,1705 ,1701, //32-32.91697 ,1693 ,1689 ,1684 ,1680 ,1676 ,1672 ,1668 ,1664 ,1660, //33-33.91655 ,1651 ,1647 ,1643 ,1639 ,1635 ,1631 ,1627 ,1623 ,1618, //34-34.91614 ,1610 ,1606 ,1602 ,1598 ,1594 ,1590 ,1586 ,1582 ,1578, //35-35.91574 ,1570 ,1566 ,1562 ,1558 ,1554 ,1550 ,1546 ,1542 ,1538, //36-36.91534 ,1530 ,1526 ,1523 ,1519 ,1515 ,1511 ,1507 ,1503 ,1499, //37-37.91495 ,1491 ,1488 ,1484 ,1480 ,1476 ,1472 ,1468 ,1464 ,1461, //38-38.91457 ,1453 ,1449 ,1445 ,1442 ,1438 ,1434 ,1430 ,1427 ,1423, //39-39.91419 ,1415 ,1412 ,1408 ,1404 ,1401 ,1397 ,1393 ,1389 ,1386, //40-40.91382 ,1378 ,1375 ,1371 ,1368 ,1364 ,1360 ,1357 ,1353 ,1349, //41-41.91346 ,1342 ,1339 ,1335 ,1332 ,1328 ,1324 ,1321 ,1317 ,1314, //42-42.91310 ,1307 ,1303 ,1300 ,1296 ,1293 ,1289 ,1286 ,1282 ,1279, //43-43.91275 ,1272 ,1269 ,1265 ,1262 ,1258 ,1255 ,1251 ,1248 ,1245 //44-44.9 };void Adc_Init(void) {ADC_InitTypeDef ADC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1 , ENABLE ); //使能 ADC1 通道時鐘RCC_ADCCLKConfig(RCC_PCLK2_Div6); //設置 ADC 分頻因子 6 ,72M/6=12,ADC 最大時間不能超過 14M//PC4 作為模擬通道輸入引腳GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化 GPIOC.4ADC_DeInit(ADC1); //復位 ADC1,將外設 ADC1 的全部寄存器重設為缺省值ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 獨立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE; //單通道模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //單次轉換模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//轉換由軟件而不是外部觸發啟動ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC 數據右對齊ADC_InitStructure.ADC_NbrOfChannel = 1; //順序進行規則轉換的ADC 通道的數目ADC_Init(ADC1, &ADC_InitStructure); //根據指定的參數初始化外設 ADCxADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1ADC_ResetCalibration(ADC1); //開啟復位校準while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校準結束ADC_StartCalibration(ADC1); //開啟 AD 校準while(ADC_GetCalibrationStatus(ADC1)); //等待校準結束 }//獲得 ADC 值 u16 Get_Adc(u8 ch) {//設置指定 ADC 的規則組通道,設置它們的轉化順序和采樣時間ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );//通道 1,規則采樣順序值為 1,采樣時間為 239.5 周期ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能軟件轉換功能while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束return ADC_GetConversionValue(ADC1); //返回最近一次 ADC1 規則組的轉換結果 }//多取幾次,取平均值 u16 Get_Adc_Average(u8 ch,u8 times) {u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times; }//這是一個ADC值轉溫度值的函數 float Get_temper(u16 adc_value) {int i;for(i=0;i<NTC_ADC_MAX;i++){if(adc_value >= ADC_NTC[i]) //當沒有ADC值對應溫度的時候,就取相近的,也就是大于的情況{return 0.1*i+25;break;}}return 65; }main函數不想貼上來了,因為我用的是工業級的屏幕,結果如下:
因為加了其他的外設,不方便把整個屏幕露出來
有問題記得給我指出來呀
總結
以上是生活随笔為你收集整理的NTC热敏电阻温度采集与adc转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql商城热销榜怎么实现_Redis
- 下一篇: java B2B2C Springclo