STC15單片機
實驗名稱:使用NTC電阻測量溫度
實驗內容:
使用NTC電阻測量溫度并顯示在數碼管上
讀取DS18B20模塊測量溫度作為參考
實驗器材:
STC15W408AS_DIP16 x1
DS18B20 x1
TM1637數碼管 x1
1%精度 熱敏電阻NTC-MF52-103/3435 10K 3435±1 x1
金屬膜電阻 1/4W 1% 五色環 10千歐 10K x1
在STC15單片機上使用NTC(10K)電阻測量溫度的基本方法:
電壓-->電阻-->溫度
1、先有一個準確且穩定的參考電壓,外部可以用TL431A,內部可以使用STC15系列芯片自帶的Bang Gap電壓;
2、如果用Bang Gap基準電壓,則需要使用第九通道讀取Bang Gap電壓相對于當前MCU供電電壓VDD的ADC讀數,然后計算出MCU供電電壓VDD;
3、有了Bang Gap電壓,再讀取NTC電阻電壓的ADC讀數,就可以計算出NTC電阻當前電壓;
4、有了NTC電阻電壓,MCU供電電壓VDD,就可以得到參考電阻(10k)的電壓,就可以計算出NTC電阻當前的阻值;
5、有了NTC電阻當前的阻值,查找溫度與NTC電阻阻值對應關系表,就可以得到溫度值;
實驗心得:
1、使用Bang Gap基準電壓,必須使用芯片內部IRC時鐘,不能使用外部晶振;
2、下載HEX時,需要勾選"在程序區的結束處添加重要測試參數"選項,才可在程序中讀取Bang Gap基準電壓;
3、溫度與NTC電阻阻值對應關系表,可用二分法查找提高速度;
4、查表得到的溫度精度只到整數位,可以用相鄰阻值區間估算小數位以提高準確度;
5、STC15W408AS的代碼空間僅8k,存不下字體數據,不適合使用液晶屏顯示輸出;
6、芯片的Band Gap基準電壓bdg_voltage可以視為常量,加電后讀取一次即可;
TM1637數碼管顯示效果如下:
51hei圖片_20201106221755.jpg (34.05 KB, 下載次數: 101)
下載附件
2020-11-6 22:22 上傳
下載HEX時,需要勾選"在程序區的結束處添加重要測試參數"選項,才可在程序中讀取Bang Gap基準電壓;
使用Bang Gap基準電壓,必須使用芯片內部IRC時鐘,不能使用外部晶振;
Screenshot 2020-11-06 170818.png (50.29 KB, 下載次數: 105)
下載附件
2020-11-6 22:21 上傳
通過 串口助手 可以觀察 NTC電阻和DS18B20測試的溫度數值對比
Screenshot 2020-11-06 173237.png (41.78 KB, 下載次數: 108)
下載附件
2020-11-6 22:21 上傳
- //主函數
- void main(void)
- {
- uint8 pdata uart_cmd_buf[64] = {0};
- //設置STC15W408AS單片機端口為標準模式
- Config_Port();
- //串口初始化,波特率9600
- UART_Config_1(9600);
-
- //定時器0設置,1ms循環
- Timer0Init();
- //ADC功能初始化
- ADC_Init();
- //啟動DS18B20
- DS18B20_Start();
- // 事件處理循環
- while(1)
- {
- UART_Cmd_Check(&uart_cmd_buf, sizeof(uart_cmd_buf)-1);
-
- if (timer_flag_10s) //每隔10s執行以下分支
- {
- printf("\r\n>timer_count %06u seconds.\r\n", 10*++timer_count);
- timer_flag_10s = 0;
- NTC_Update_Show();
- DS18B20_Update_Show();
- }
-
- }
- }
復制代碼- void NTC_Update_Show(void)
- {
- int16 ntc_t = 0;
- uint8 a, b, c;
- ntc_t = NTC_ReadT();
- sprintf(sbuf, "%4.1f", (float)ntc_t/10);
- printf(">>>NTC_T : %s c\r\n", sbuf);
- //TM1637數碼管顯示測試
- if(' ' == sbuf[0]) a = 22;
- else if('-' == sbuf[0]) a = 21;
- else a = sbuf[0] - '0';
- b = sbuf[1] - '0';
- c = sbuf[3] - '0';
- // 使用TM1637數碼管模塊顯示NTC溫度,最后一位顯示字母c表示℃
- TM1637_Display(a, b, c, 12);
- }
復制代碼- //溫度與NTC電阻阻值對應關系表
- //MF52 10K3435 溫度特性表
- uint16 code ntc10k_tab[] = {
- // 阻值(Ω),溫度
- // 190556, /* -40 */
- // 183413, /* -39 */
- // 175674, /* -38 */
- // 167647, /* -37 */
- // 159565, /* -36 */
- // 151598, /* -35 */
- // 143862, /* -34 */
- // 136436, /* -33 */
- // 129364, /* -32 */
- // 122668, /* -31 */
- // 116352, /* -30 */
- // 110410, /* -29 */
- // 104827, /* -28 */
- // 99585, /* -27 */
- // 94661, /* -26 */
- // 90033, /* -25 */
- // 85678, /* -24 */
- // 81575, /* -23 */
- // 77703, /* -22 */
- // 74044, /* -21 */
- // 70581, /* -20 */
- // 67299, /* -19 */
- // 64183, /* -18 */
- // 61223, /* -17 */
- // 58408, /* -16 */
- // 55728, /* -15 */
- // 53177, /* -14 */
- // 50746, /* -13 */
- // 48429, /* -12 */
- // 46222, /* -11 */
- //44120, /* -10 */
- 42118, /* -9 */
- 40212, /* -8 */
- 38399, /* -7 */
- 36675, /* -6 */
- 35036, /* -5 */
- 33480, /* -4 */
- 32004, /* -3 */
- 30603, /* -2 */
- 29275, /* -1 */
- 28017, /* 0 */
- 26826, /* 1 */
- 25697, /* 2 */
- 24629, /* 3 */
- 23618, /* 4 */
- 22660, /* 5 */
- 21752, /* 6 */
- 20892, /* 7 */
- 20075, /* 8 */
- 19299, /* 9 */
- 18560, /* 10 */
- 18482, /* 11 */
- 18149, /* 12 */
- 17632, /* 13 */
- 16992, /* 14 */
- 16280, /* 15 */
- 15535, /* 16 */
- 14787, /* 17 */
- 14055, /* 18 */
- 13354, /* 19 */
- 12690, /* 20 */
- 12068, /* 21 */
- 11490, /* 22 */
- 10954, /* 23 */
- 10458, /* 24 */
- 10000, /* 25 */
- 9576, /* 26 */
- 9184, /* 27 */
- 8819, /* 28 */
- 8478, /* 29 */
- 8160, /* 30 */
- 7861, /* 31 */
- 7579, /* 32 */
- 7311, /* 33 */
- 7056, /* 34 */
- 6813, /* 35 */
- 6581, /* 36 */
- 6357, /* 37 */
- 6142, /* 38 */
- 5934, /* 39 */
- 5734, /* 40 */
- 5541, /* 41 */
- 5353, /* 42 */
- 5173, /* 43 */
- 4998, /* 44 */
- 4829, /* 45 */
- 4665, /* 46 */
- 4507, /* 47 */
- 4355, /* 48 */
- 4208, /* 49 */
- 4065, /* 50 */
- 3927, /* 51 */
- 3794, /* 52 */
- 3664, /* 53 */
- 3538, /* 54 */
- 3415, /* 55 */
- 3294, /* 56 */
- 3175, /* 57 */
- 3058, /* 58 */
- 2941, /* 59 */
- 2825, /* 60 */
- 2776, /* 61 */
- 2718, /* 62 */
- 2652, /* 63 */
- 2582, /* 64 */
- 2508, /* 65 */
- 2432, /* 66 */
- 2356, /* 67 */
- 2280, /* 68 */
- 2207, /* 69 */
- 2135, /* 70 */
- 2066, /* 71 */
- 2000, /* 72 */
- 1938, /* 73 */
- 1879, /* 74 */
- 1823, /* 75 */
- 1770, /* 76 */
- 1720, /* 77 */
- 1673, /* 78 */
- 1628, /* 79 */
- 1586, /* 80 */
- 1546, /* 81 */
- 1508, /* 82 */
- 1471, /* 83 */
- 1435, /* 84 */
- 1401, /* 85 */
- 1367, /* 86 */
- 1334, /* 87 */
- 1301, /* 88 */
- 1268, /* 89 */
- 1236, /* 90 */
- 1204, /* 91 */
- 1171, /* 92 */
- 1139, /* 93 */
- 1107, /* 94 */
- 1074, /* 95 */
- 1042, /* 96 */
- 1010, /* 97 */
- 979, /* 98 */
- 948, /* 99 */
- // 918, /* 100 */
- // 889, /* 101 */
- // 861, /* 102 */
- // 835, /* 103 */
- // 810, /* 104 */
- // 787, /* 105 */
- // 767, /* 106 */
- // 749, /* 107 */
- // 733, /* 108 */
- // 721, /* 109 */
- // 713, /* 110 */
- };
復制代碼- int8 NTC_bSearch(uint16 *tab, uint8 tab_size, int16 val)
- {
- uint8 mid = 0;
- uint8 left = 0;
- uint8 right = tab_size - 1;
- if(val > tab[0]) return -1; // 溫度下限
- else if(val < tab[tab_size - 1]) return -2; // 溫度上限
- while(left <= right)
- {
- mid = (right + left) / 2;
- if(val == tab[mid])
- return mid;
- else if (val > tab[mid])
- right = mid - 1;
- else if (val < tab[mid])
- left = mid + 1;
- }
- return mid;
- }
- /*
- 根據ADC電壓值計算NTC10K電阻值
- r_ref為1%精度 10k電阻阻值,如 9963 Ω
- adc_voltage是讀取到的NTC10K電壓
- vdd_voltage是讀取到的系統電壓
- */
- uint16 NTC_ReadR(uint16 r_ref)
- {
- //計算ADC通道的電阻值(歐姆),參考分壓電阻值r_ref歐姆
- return r_ref * adc_voltage / (vdd_voltage - adc_voltage);
- }
- int16 NTC_ReadT(void)
- {
- uint16 ntc_r = 0;
- uint16 ref_r = 0;
- int16 ntc_t = 0;
- uint8 idx = 0;
- int16 dec = 0;
- ADC_ReadBandGapVoltage();
- if(DEBUG_MODE) printf(">>>NTC_ReadT: bdg_voltage = %5.2f mV\r\n", (float)bdg_voltage);
- ADC_ReadCh9Val();
- if(DEBUG_MODE) printf(">>>NTC_ReadT: adc_ch9_val = %u\r\n", adc_ch9_val);
- //指定ADC端口P1.4讀取NTC電阻電壓
- ADC_ReadChxVoltage(4);
- if(DEBUG_MODE) printf(">>>NTC_ReadT: adc_voltage = %5.2f mV\r\n", adc_voltage);
- ADC_ReadVddVoltage();
- if(DEBUG_MODE) printf(">>>NTC_ReadT: vdd_voltage = %5.2f mV\r\n", vdd_voltage);
-
- ntc_r = NTC_ReadR(NTC_R10K_REF);
- if(DEBUG_MODE) printf(">>>NTC_ReadT: ntc_r = %u ohm\r\n", ntc_r);
- idx = NTC_bSearch(ntc10k_tab, ARRAY_SIZE(ntc10k_tab), ntc_r);
- if(-1 == idx) return -99;
- else if(-2 == idx) return 999;
-
- if(DEBUG_MODE) printf(">>>NTC_bSearch: ntc10k_tab[%bu] = %d ohm\r\n", idx, ntc10k_tab[idx]);
- if(ntc_r != ntc10k_tab[idx])
- {
- // 使用相鄰阻值區間估算溫度值小數部分,四舍五入
- if(ntc_r > ntc10k_tab[idx] && idx > 0)
- {
- dec = 100 * (ntc_r - ntc10k_tab[idx])/(ntc10k_tab[idx-1] - ntc10k_tab[idx]);
- //if(DEBUG_MODE) printf(">>>NTC_ReadT: dec = %d = 100 * (%d)/(%d)\r\n", dec, (ntc_r - ntc10k_tab[idx]), (ntc10k_tab[idx-1] - ntc10k_tab[idx]));
- }
- else if(ntc_r < ntc10k_tab[idx] && idx < ARRAY_SIZE(ntc10k_tab))
- {
- dec = 100 * (ntc10k_tab[idx] - ntc_r)/(ntc10k_tab[idx] - ntc10k_tab[idx+1]);
- //if(DEBUG_MODE) printf(">>>NTC_ReadT: dec = %d = 100 * (%d)/(%d)\r\n", dec, (ntc10k_tab[idx] - ntc_r), (ntc10k_tab[idx] - ntc10k_tab[idx+1]));
- }
- if(5 < dec % 10) dec += 10;
- dec /= 10;
- if(ntc_r > ntc10k_tab[idx])
- {
- dec *= -1;
- }
- }
- if(DEBUG_MODE) printf(">>>NTC_ReadT: int = %4.1f c\r\n", (float)(idx-9));
- if(DEBUG_MODE) printf(">>>NTC_ReadT: dec = %2.1f c\r\n", (float)dec/10);
- ntc_t = 10*(idx-9) + dec;
- //if(DEBUG_MODE) printf(">>>NTC_ReadT: ntc_t = %4.1f c\r\n", (float)ntc_t/10);
- return ntc_t;
- }
復制代碼 完整代碼如下:
Screenshot 2020-11-06 223500.png (15.94 KB, 下載次數: 120)
下載附件
2020-11-6 22:35 上傳
uart_ntc10k_STC15W408AS.7z
(425.15 KB, 下載次數: 295)
2020-11-6 22:39 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|