找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7778|回复: 7
打印 上一主题 下一主题
收起左侧

51单片机学习实践:用NTC电阻测温并显示在TM1637数码管 附程序

  [复制链接]
跳转到指定楼层
楼主
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数码管显示效果如下:


下载HEX时,需要勾选"在程序区的结束处添加重要测试参数"选项,才可在程序中读取Bang Gap基准电压;
使用Bang Gap基准电压,必须使用芯片内部IRC时钟,不能使用外部晶振;


通过 串口助手 可以观察 NTC电阻和DS18B20测试的温度数值对比




  1. //主函数
  2. void main(void)
  3. {
  4.         uint8 pdata uart_cmd_buf[64] = {0};

  5.         //设置STC15W408AS单片机端口为标准模式
  6.         Config_Port();

  7.         //串口初始化,波特率9600
  8.         UART_Config_1(9600);
  9.         
  10.         //定时器0设置,1ms循环
  11.         Timer0Init();

  12.         //ADC功能初始化
  13.         ADC_Init();

  14.         //启动DS18B20
  15.         DS18B20_Start();

  16.         // 事件处理循环
  17.         while(1)
  18.         {        
  19.                 UART_Cmd_Check(&uart_cmd_buf, sizeof(uart_cmd_buf)-1);
  20.                
  21.         if (timer_flag_10s)  //每隔10s执行以下分支
  22.         {
  23.                         printf("\r\n>timer_count %06u seconds.\r\n", 10*++timer_count);
  24.             timer_flag_10s = 0;

  25.                         NTC_Update_Show();
  26.                         DS18B20_Update_Show();
  27.                 }
  28.                
  29.         }   
  30. }
复制代码
  1. void NTC_Update_Show(void)
  2. {
  3.         int16 ntc_t = 0;
  4.         uint8 a, b, c;

  5.         ntc_t = NTC_ReadT();

  6.         sprintf(sbuf, "%4.1f", (float)ntc_t/10);

  7.         printf(">>>NTC_T   : %s c\r\n", sbuf);

  8.         //TM1637数码管显示测试
  9.         if(' ' == sbuf[0]) a = 22;
  10.         else if('-' == sbuf[0]) a = 21;
  11.         else a = sbuf[0] - '0';
  12.         b = sbuf[1] - '0';
  13.         c = sbuf[3] - '0';

  14.         // 使用TM1637数码管模块显示NTC温度,最后一位显示字母c表示℃
  15.         TM1637_Display(a, b, c, 12);
  16. }
复制代码
  1. //温度与NTC电阻阻值对应关系表
  2. //MF52 10K3435 温度特性表
  3. uint16 code ntc10k_tab[] = {

  4. // 阻值(Ω),温度
  5. // 190556, /* -40 */
  6. // 183413, /* -39 */
  7. // 175674, /* -38 */
  8. // 167647, /* -37 */
  9. // 159565, /* -36 */
  10. // 151598, /* -35 */
  11. // 143862, /* -34 */
  12. // 136436, /* -33 */
  13. // 129364, /* -32 */
  14. // 122668, /* -31 */
  15. // 116352, /* -30 */
  16. // 110410, /* -29 */
  17. // 104827, /* -28 */
  18. // 99585, /* -27 */
  19. // 94661, /* -26 */
  20. // 90033, /* -25 */
  21. // 85678, /* -24 */
  22. // 81575, /* -23 */
  23. // 77703, /* -22 */
  24. // 74044, /* -21 */
  25. // 70581, /* -20 */
  26. // 67299, /* -19 */
  27. // 64183, /* -18 */
  28. // 61223, /* -17 */
  29. // 58408, /* -16 */
  30. // 55728, /* -15 */
  31. // 53177, /* -14 */
  32. // 50746, /* -13 */
  33. // 48429, /* -12 */
  34. // 46222, /* -11 */
  35. //44120, /* -10 */
  36. 42118, /* -9 */
  37. 40212, /* -8 */
  38. 38399, /* -7 */
  39. 36675, /* -6 */
  40. 35036, /* -5 */
  41. 33480, /* -4 */
  42. 32004, /* -3 */
  43. 30603, /* -2 */
  44. 29275, /* -1 */
  45. 28017, /* 0 */
  46. 26826, /* 1 */
  47. 25697, /* 2 */
  48. 24629, /* 3 */
  49. 23618, /* 4 */
  50. 22660, /* 5 */
  51. 21752, /* 6 */
  52. 20892, /* 7 */
  53. 20075, /* 8 */
  54. 19299, /* 9 */
  55. 18560, /* 10 */
  56. 18482, /* 11 */
  57. 18149, /* 12 */
  58. 17632, /* 13 */
  59. 16992, /* 14 */
  60. 16280, /* 15 */
  61. 15535, /* 16 */
  62. 14787, /* 17 */
  63. 14055, /* 18 */
  64. 13354, /* 19 */
  65. 12690, /* 20 */
  66. 12068, /* 21 */
  67. 11490, /* 22 */
  68. 10954, /* 23 */
  69. 10458, /* 24 */
  70. 10000, /* 25 */
  71. 9576, /* 26 */
  72. 9184, /* 27 */
  73. 8819, /* 28 */
  74. 8478, /* 29 */
  75. 8160, /* 30 */
  76. 7861, /* 31 */
  77. 7579, /* 32 */
  78. 7311, /* 33 */
  79. 7056, /* 34 */
  80. 6813, /* 35 */
  81. 6581, /* 36 */
  82. 6357, /* 37 */
  83. 6142, /* 38 */
  84. 5934, /* 39 */
  85. 5734, /* 40 */
  86. 5541, /* 41 */
  87. 5353, /* 42 */
  88. 5173, /* 43 */
  89. 4998, /* 44 */
  90. 4829, /* 45 */
  91. 4665, /* 46 */
  92. 4507, /* 47 */
  93. 4355, /* 48 */
  94. 4208, /* 49 */
  95. 4065, /* 50 */
  96. 3927, /* 51 */
  97. 3794, /* 52 */
  98. 3664, /* 53 */
  99. 3538, /* 54 */
  100. 3415, /* 55 */
  101. 3294, /* 56 */
  102. 3175, /* 57 */
  103. 3058, /* 58 */
  104. 2941, /* 59 */
  105. 2825, /* 60 */
  106. 2776, /* 61 */
  107. 2718, /* 62 */
  108. 2652, /* 63 */
  109. 2582, /* 64 */
  110. 2508, /* 65 */
  111. 2432, /* 66 */
  112. 2356, /* 67 */
  113. 2280, /* 68 */
  114. 2207, /* 69 */
  115. 2135, /* 70 */
  116. 2066, /* 71 */
  117. 2000, /* 72 */
  118. 1938, /* 73 */
  119. 1879, /* 74 */
  120. 1823, /* 75 */
  121. 1770, /* 76 */
  122. 1720, /* 77 */
  123. 1673, /* 78 */
  124. 1628, /* 79 */
  125. 1586, /* 80 */
  126. 1546, /* 81 */
  127. 1508, /* 82 */
  128. 1471, /* 83 */
  129. 1435, /* 84 */
  130. 1401, /* 85 */
  131. 1367, /* 86 */
  132. 1334, /* 87 */
  133. 1301, /* 88 */
  134. 1268, /* 89 */
  135. 1236, /* 90 */
  136. 1204, /* 91 */
  137. 1171, /* 92 */
  138. 1139, /* 93 */
  139. 1107, /* 94 */
  140. 1074, /* 95 */
  141. 1042, /* 96 */
  142. 1010, /* 97 */
  143. 979, /* 98 */
  144. 948, /* 99 */
  145. // 918, /* 100 */
  146. // 889, /* 101 */
  147. // 861, /* 102 */
  148. // 835, /* 103 */
  149. // 810, /* 104 */
  150. // 787, /* 105 */
  151. // 767, /* 106 */
  152. // 749, /* 107 */
  153. // 733, /* 108 */
  154. // 721, /* 109 */
  155. // 713, /* 110 */
  156. };
复制代码
  1. int8 NTC_bSearch(uint16 *tab, uint8 tab_size, int16 val)
  2. {
  3.     uint8 mid        = 0;
  4.     uint8 left        = 0;
  5.         uint8 right        = tab_size - 1;

  6.         if(val > tab[0]) return -1; // 温度下限
  7.         else if(val < tab[tab_size - 1]) return -2; // 温度上限

  8.     while(left <= right)
  9.         {
  10.         mid = (right + left) / 2;
  11.         if(val == tab[mid])
  12.             return mid;
  13.         else if (val > tab[mid])
  14.             right = mid - 1;
  15.         else if (val < tab[mid])
  16.             left = mid + 1;
  17.         }

  18.     return mid;
  19. }

  20. /*
  21. 根据ADC电压值计算NTC10K电阻值
  22. r_ref为1%精度 10k电阻阻值,如 9963 Ω
  23. adc_voltage是读取到的NTC10K电压
  24. vdd_voltage是读取到的系统电压
  25. */
  26. uint16 NTC_ReadR(uint16 r_ref)
  27. {
  28.     //计算ADC通道的电阻值(欧姆),参考分压电阻值r_ref欧姆
  29.         return r_ref * adc_voltage / (vdd_voltage - adc_voltage);
  30. }

  31. int16 NTC_ReadT(void)
  32. {
  33.         uint16 ntc_r = 0;
  34.         uint16 ref_r = 0;
  35.         int16  ntc_t = 0;
  36.         uint8 idx  = 0;
  37.         int16 dec  = 0;

  38.         ADC_ReadBandGapVoltage();
  39.         if(DEBUG_MODE) printf(">>>NTC_ReadT: bdg_voltage = %5.2f mV\r\n", (float)bdg_voltage);

  40.         ADC_ReadCh9Val();
  41.         if(DEBUG_MODE) printf(">>>NTC_ReadT: adc_ch9_val = %u\r\n", adc_ch9_val);

  42.         //指定ADC端口P1.4读取NTC电阻电压
  43.         ADC_ReadChxVoltage(4);
  44.         if(DEBUG_MODE) printf(">>>NTC_ReadT: adc_voltage = %5.2f mV\r\n", adc_voltage);

  45.         ADC_ReadVddVoltage();
  46.         if(DEBUG_MODE) printf(">>>NTC_ReadT: vdd_voltage = %5.2f mV\r\n", vdd_voltage);
  47.         
  48.         ntc_r = NTC_ReadR(NTC_R10K_REF);
  49.         if(DEBUG_MODE) printf(">>>NTC_ReadT: ntc_r = %u ohm\r\n", ntc_r);

  50.         idx = NTC_bSearch(ntc10k_tab, ARRAY_SIZE(ntc10k_tab), ntc_r);

  51.         if(-1 == idx)                 return -99;
  52.         else if(-2 == idx)        return 999;
  53.         
  54.         if(DEBUG_MODE) printf(">>>NTC_bSearch: ntc10k_tab[%bu] = %d ohm\r\n", idx, ntc10k_tab[idx]);

  55.         if(ntc_r != ntc10k_tab[idx])
  56.         {
  57.                 // 使用相邻阻值区间估算温度值小数部分,四舍五入

  58.                 if(ntc_r > ntc10k_tab[idx] && idx > 0)
  59.                 {
  60.                         dec = 100 * (ntc_r - ntc10k_tab[idx])/(ntc10k_tab[idx-1] - ntc10k_tab[idx]);
  61.                         //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]));
  62.                 }
  63.                 else if(ntc_r < ntc10k_tab[idx] && idx < ARRAY_SIZE(ntc10k_tab))
  64.                 {
  65.                         dec = 100 * (ntc10k_tab[idx] - ntc_r)/(ntc10k_tab[idx] - ntc10k_tab[idx+1]);
  66.                         //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]));
  67.                 }
  68.                 if(5 < dec % 10) dec += 10;
  69.                 dec /= 10;

  70.                 if(ntc_r > ntc10k_tab[idx])
  71.                 {
  72.                         dec *= -1;
  73.                 }
  74.         }

  75.         if(DEBUG_MODE) printf(">>>NTC_ReadT:   int = %4.1f c\r\n", (float)(idx-9));
  76.         if(DEBUG_MODE) printf(">>>NTC_ReadT:   dec = %2.1f c\r\n", (float)dec/10);

  77.         ntc_t = 10*(idx-9) + dec;

  78.         //if(DEBUG_MODE) printf(">>>NTC_ReadT: ntc_t = %4.1f c\r\n", (float)ntc_t/10);

  79.         return ntc_t;
  80. }

复制代码
完整代码如下:



uart_ntc10k_STC15W408AS.7z (425.15 KB, 下载次数: 253)



评分

参与人数 1黑币 +80 收起 理由
admin + 80 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏17 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:65956 发表于 2020-11-7 08:38 | 只看该作者
下载参考一下,谢谢分享
回复

使用道具 举报

板凳
ID:328014 发表于 2020-11-7 16:37 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

地板
ID:856401 发表于 2020-12-17 01:48 | 只看该作者
单片机高手
回复

使用道具 举报

5#
ID:856401 发表于 2021-1-10 11:12 | 只看该作者
感谢楼主分享,我也要做一个
回复

使用道具 举报

6#
ID:366464 发表于 2021-1-30 20:14 | 只看该作者
老芯片,新光彩!
回复

使用道具 举报

7#
ID:704837 发表于 2022-5-19 19:19 | 只看该作者
一看就发现错误的计算,return r_ref * adc_voltage / (vdd_voltage - adc_voltage);(我个人判断)
回复

使用道具 举报

8#
ID:344646 发表于 2022-11-18 13:51 | 只看该作者
看看1637怎么驱动显示
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表