[麦麦茶水间] 【每周分享】沁恒CH592F开发中遇到的ADC采样不准及解决方案

[复制链接]
256|0
stb988 发表于 2025-9-16 13:00 | 显示全部楼层 |阅读模式
@21小跑堂 、#申请原创
        最近接到一个物联网项目,就是做一个蓝牙控制继电器的案例,主控芯片采用国产沁恒CH592F,之前从没有用这个芯片开发过,所以对芯片并不了解,项目中有两个温度传感器,需要用到单片机ADC采集并转换成温度值,本来这个都比较简单的,也没有什么好说的,但是采集过程却一波三折,下面我给大家细细道来。
       下面给大家看看今天的主角。

其中的温度adc电路如下

分别连接到PA12,PA13两个引脚,写了一个简单的代码,
  1. /*********************************************************************
  2. * @fn      NTC_SampleChannel_DMA_Block
  3. *
  4. * @brief   使用DMA阻塞方式采集指定通道的NTC数据
  5. *
  6. * @param   channel     - ADC通道
  7. * @param   buf         - 数据缓冲区
  8. * @param   len         - 缓冲区长度
  9. * @param   timeout_ms  - 超时时间(毫秒)
  10. *
  11. * @return  0-成功, -1-失败
  12. */
  13. int NTC_SampleChannel_DMA_Block(uint8_t channel, uint16_t *buf, uint16_t len, uint32_t timeout_ms)
  14. {
  15.     if((buf == NULL) || (len == 0))
  16.         return -1;

  17.     // 选择通道
  18.     ADC_ChannelCfg(channel);

  19.     // 设置自动转换周期
  20.     ADC_AutoConverCycle(192);

  21.     // 配置DMA
  22.     ADC_DMACfg(ENABLE, (uint32_t)buf, (uint32_t)(buf + len), ADC_Mode_Single);

  23.     // 启动自动DMA采样
  24.     ADC_StartAutoDMA();

  25.     // 等待DMA完成
  26.     uint32_t waited = 0;
  27.     const uint32_t poll_interval_ms = 10;

  28.     while(!ADC_GetDMAStatus())
  29.     {
  30.         mDelaymS(poll_interval_ms);
  31.         waited += poll_interval_ms;

  32.         if(waited >= timeout_ms)
  33.         {
  34.             // 超时: 禁用DMA并返回错误
  35.             ADC_DMACfg(DISABLE, 0, 0, 0);
  36.             return -1;
  37.         }
  38.     }

  39.     // 清理DMA
  40.     ADC_StopAutoDMA();
  41.     R16_ADC_DMA_BEG = ((uint32_t)buf) & 0xffff;
  42.     ADC_ClearDMAFlag();
  43.     ADC_DMACfg(DISABLE, 0, 0, 0);

  44.     return 0;
  45. }

  46. /*********************************************************************
  47. * @fn      NTC_GetAverage
  48. *
  49. * @brief   计算ADC采样平均值
  50. *
  51. * @param   buf - 数据缓冲区
  52. * @param   len - 缓冲区长度
  53. *
  54. * @return  平均值
  55. */
  56. uint16_t NTC_GetAverage(uint16_t *buf, uint16_t len)
  57. {
  58.     if((buf == NULL) || (len == 0))
  59.         return 0;

  60.     uint32_t sum = 0;
  61.     for(uint16_t i = 0; i < len; i++)
  62.     {
  63.         sum += (buf[i] & RB_ADC_DATA);
  64.     }
  65.     return (uint16_t)(sum / len);
  66. }
采集出来的信息通过CDC虚拟的串口打印,但是打印出来的却是明显与实际温度不对,


后面找了好久的错误,但一直都没有找到,本来想偷懒,不想看数据手册,现在没有办法了,只能拿出手册仔细查看了,不看不知道,一看吓一跳,这个ch592f与我们平时用的MCU的adc都不同,下面我贴出来,免得大家以后再继续踩坑。

原来它的ADC可以带放大的,还有参考电压不同,如是赶紧修改我的宏定义。

下面再编译下载,终于在串口打印出正常的室温了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

54

主题

402

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部