你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32G0-Platformio+libopencm3-NTC温度采集

[复制链接]
STMCU小助手 发布时间:2023-2-22 17:09
使用Platformio平台的libopencm3开发框架来开发STM32G0,以下使用ADC进行NTC温度采集。

1 新建项目
  • 建立ntc_temp项目

在PIO的Home页面新建项目,项目名称ntc_temp,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;

  • 项目建立完成后在src目录下新建main.c主程序文件;
  • 修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:

  1. 1upload_protocol = cmsis-dap
  2. 2debug_tool = cmsis-dap
复制代码


  • 为了能使用printf的浮点功能,可以加入如下配置:

  1. 1build_flags =
  2. 2    -Wl,-u,_printf_float
复制代码


2 编写程序2.1 ADC设置
  1. 1void adc_setup()
  2. 2{
  3. 3    rcc_periph_clock_enable(RCC_GPIOA);
  4. 4    rcc_periph_clock_enable(RCC_ADC);
  5. 5
  6. 6    gpio_mode_setup(GPIOA,GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO0);
  7. 7
  8. 8    adc_power_off(ADC1);
  9. 9    adc_set_clk_prescale(ADC1,ADC_CCR_PRESC_DIV2);
  10. 10    adc_set_single_conversion_mode(ADC1);
  11. 11    adc_set_right_aligned(ADC1);
  12. 12    adc_set_sample_time_on_all_channels(ADC1,ADC_SMPTIME_160DOT5);
  13. 13    uint8_t channel = 0;
  14. 14    adc_set_regular_sequence(ADC1,1,&channel);
  15. 15    adc_set_resolution(ADC1,ADC_CFGR1_RES_12_BIT);
  16. 16
  17. 17    adc_power_on(ADC1);
  18. 18
  19. 19    delay_ms(10);
  20. 20
  21. 21}
复制代码


ADC设置按照之前文章介绍的方法设置PA0为ADC输入;

2.2 ADC读取
  1. 1uint16_t adc_sample()
  2. 2{
  3. 3    adc_start_conversion_regular(ADC1);
  4. 4    return adc_read_regular(ADC1);
  5. 5}
复制代码


2.3 ADC与NTC的温度转换
  • 首先根据所选的NTC规格的温度-电阻对应表得到其ADC值的关系表:

这里的NTC分压电阻为10K,ADC分辨率为12位,因此ADC采集值为:(NTC电阻 x 4095) ÷ (NTC电阻 + 10K),即可得到如下所示的表格:

微信图片_20230222170852.png


在EXCEL中计算出ADC采样数值-温度对应表,为了简单ADC进行取整,就可以得到电阻-55到125摄氏度的ADC对应表:
  1. 1const uint16_t ntcDATA[] = {
  2. 24040,4038,4035,4031,4027,4023,4018,4013,4007,4001,3994,3987,3980,3972,3964,3956,
  3. 3
  4. 43947,3937,3928,3917,3907,3896,3884,3872,3860,3847,3833,3819,3804,3789,3773,3757,
  5. 5
  6. 63740,3722,3703,3684,3664,3644,3622,3600,3577,3553,3528,3502,3475,3448,3419,3390,
  7. 7
  8. 83360,3329,3297,3264,3230,3195,3160,3123,3086,3048,3010,2970,2930,2889,2848,2806,
  9. 9
  10. 102763,2720,2676,2633,2588,2544,2499,2454,2408,2363,2317,2272,2226,2181,2136,2091,
  11. 11
  12. 122048,2001,1957,1913,1869,1826,1783,1741,1699,1658,1617,1576,1537,1498,1459,1422,
  13. 13
  14. 141385,1348,1312,1277,1243,1209,1176,1144,1112,1081,1051,1022,993,965,937,910,
  15. 15
  16. 16884,859,834,810,786,764,741,720,699,679,659,639,621,602,585,568,
  17. 17
  18. 18551,535,519,504,490,475,461,448,435,422,410,398,387,376,365,355,
  19. 19
  20. 20345,335,325,316,307,299,290,282,274,267,259,252,245,239,232,226,
  21. 21
  22. 22220,214,208,202,197,192,187,182,177,172,168,163,159,155,151,146,
  23. 23
  24. 24143,139,135,132,129
  25. 25};
复制代码

  • 然后根据表格获取温度,即每个ADC对应的索引即为温度值,如4040为索引0,对应第一个温度-55℃;
  • 表格中数据是有序的,因此这里可以使用二分法查找,对于两个数中间值则取其相近的那个值:

  1. 1#define TEMP_HEADER_VALUE   -55 //the first temp in table
  2. 2
  3. 3#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
  4. 4
  5. 5/**
  6. 6 * @brief search the table, return a midium value if not found
  7. 7 *
  8. 8 * @param table  the data to search
  9. 9 * @param len    the table length
  10. 10 * @param up    if data is min to max
  11. 11 * @return int32_t -1 -> if not found
  12. 12 */
  13. 13int32_t bsearch_ret_mid(const uint16_t *table, uint16_t len, bool up, uint16_t key)
  14. 14{
  15. 15    uint16_t bot;
  16. 16    uint16_t mid;
  17. 17    uint16_t check;
  18. 18    uint16_t top;
  19. 19
  20. 20    if (len == 0) {
  21. 21        return -1;
  22. 22    }
  23. 23
  24. 24    if (up) {
  25. 25        //the first data will be min
  26. 26        if (key < table[0]) {
  27. 27            return -1;
  28. 28        }
  29. 29
  30. 30        //bigger then the last data
  31. 31        if (key > table[len - 1]) {
  32. 32            return -1;
  33. 33        }
  34. 34    } else {
  35. 35        if (key > table[0]) {
  36. 36            return -1;
  37. 37        }
  38. 38
  39. 39        if (key < table[len - 1]) {
  40. 40            return -1;
  41. 41        }
  42. 42    }
  43. 43
  44. 44    bot = 0;
  45. 45    top = len - 1;
  46. 46
  47. 47    if (up) {
  48. 48        while (bot < top) {
  49. 49            mid = top - (top - bot) / 2;
  50. 50
  51. 51            if (key < table[mid]) {
  52. 52                top = mid - 1;
  53. 53            } else {
  54. 54                bot = mid;
  55. 55            }
  56. 56        }
  57. 57    } else {
  58. 58        while (bot < top) {
  59. 59            mid = top - (top - bot) / 2;
  60. 60
  61. 61            if (key > table[mid]) {
  62. 62                top = mid - 1;
  63. 63            } else {
  64. 64                bot = mid;
  65. 65            }
  66. 66        }
  67. 67    }
  68. 68
  69. 69    if (key == table[top]) {
  70. 70        return top;
  71. 71    }
  72. 72
  73. 73    //not equal the data in table
  74. 74    if (up) {
  75. 75        if (key > table[top]) {
  76. 76            return top;
  77. 77        }
  78. 78    } else {
  79. 79        if (key < table[top]) {
  80. 80            return top;
  81. 81        }
  82. 82    }
  83. 83
  84. 84    return -1;
  85. 85}
复制代码


  • 然后根据索引得到温度:

  1. 1//get temperature , x10
  2. 2int16_t ntc2tem(uint16_t adc)
  3. 3{
  4. 4    int32_t  index = 0;
  5. 5    int16_t temperature = 0;
  6. 6
  7. 7    index = bsearch_ret_mid(ntcDATA, ITEM_NUM(ntcDATA),false,adc);
  8. 8
  9. 9    //max, the first value
  10. 10    if(index==0){
  11. 11        temperature = TEMP_HEADER_VALUE*10;
  12. 12    }
  13. 13    //min, the last value
  14. 14    else if(index>= ITEM_NUM(ntcDATA)){
  15. 15        temperature = 10*(TEMP_HEADER_VALUE + ITEM_NUM(ntcDATA));
  16. 16    }
  17. 17    else{
  18. 18        //just get integer number
  19. 19        // temperature = TEMP_HEADER_VALUE + index;
  20. 20
  21. 21        //get approximation data
  22. 22        temperature = TEMP_HEADER_VALUE + index;
  23. 23
  24. 24        //at middle
  25. 25        temperature = (temperature+1)*10 - 10.0 * (adc-ntcDATA[index+1])/(ntcDATA[index]-ntcDATA[index+1]);
  26. 26    }
  27. 27
  28. 28    return temperature;
  29. 29
  30. 30}
复制代码


表格中的温度是1度进行变化的,如果需要稍微精确的,这里在1度中间的值近似看做线性进行计算;
这里为了减小计算误差,先对其扩大十倍计算,显示时候再转为小数:
  1. 1uint16_t adc = adc_sample();
  2. 2
  3. 3int16_t temp_int = ntc2tem(adc);
  4. 4float temp = temp_int/10.0;
  5. 5
  6. 6printf("adc: %d, temp: %.1f\r\n",adc, temp);
复制代码

3 连接硬件并测试
3.1 连接硬件
按照如下图,将NTC和10K电阻连接到PA0脚:
微信图片_20230222170842.png


3.2 测试
打开串口,当手放在NTC上可以看到温度变化:
微信图片_20230222170837.png

转载自:MakerInChina.cn


收藏 评论0 发布时间:2023-2-22 17:09

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版