@21小跑堂 、#申请原创
最近接到一个物联网项目,就是做一个蓝牙控制继电器的案例,主控芯片采用国产沁恒CH592F,之前从没有用这个芯片开发过,所以对芯片并不了解,项目中有两个温度传感器,需要用到单片机ADC采集并转换成温度值,本来这个都比较简单的,也没有什么好说的,但是采集过程却一波三折,下面我给大家细细道来。
下面给大家看看今天的主角。
其中的温度adc电路如下
分别连接到PA12,PA13两个引脚,写了一个简单的代码,
- /*********************************************************************
- * @fn NTC_SampleChannel_DMA_Block
- *
- * @brief 使用DMA阻塞方式采集指定通道的NTC数据
- *
- * @param channel - ADC通道
- * @param buf - 数据缓冲区
- * @param len - 缓冲区长度
- * @param timeout_ms - 超时时间(毫秒)
- *
- * @return 0-成功, -1-失败
- */
- int NTC_SampleChannel_DMA_Block(uint8_t channel, uint16_t *buf, uint16_t len, uint32_t timeout_ms)
- {
- if((buf == NULL) || (len == 0))
- return -1;
- // 选择通道
- ADC_ChannelCfg(channel);
- // 设置自动转换周期
- ADC_AutoConverCycle(192);
- // 配置DMA
- ADC_DMACfg(ENABLE, (uint32_t)buf, (uint32_t)(buf + len), ADC_Mode_Single);
- // 启动自动DMA采样
- ADC_StartAutoDMA();
- // 等待DMA完成
- uint32_t waited = 0;
- const uint32_t poll_interval_ms = 10;
- while(!ADC_GetDMAStatus())
- {
- mDelaymS(poll_interval_ms);
- waited += poll_interval_ms;
- if(waited >= timeout_ms)
- {
- // 超时: 禁用DMA并返回错误
- ADC_DMACfg(DISABLE, 0, 0, 0);
- return -1;
- }
- }
- // 清理DMA
- ADC_StopAutoDMA();
- R16_ADC_DMA_BEG = ((uint32_t)buf) & 0xffff;
- ADC_ClearDMAFlag();
- ADC_DMACfg(DISABLE, 0, 0, 0);
- return 0;
- }
- /*********************************************************************
- * @fn NTC_GetAverage
- *
- * @brief 计算ADC采样平均值
- *
- * @param buf - 数据缓冲区
- * @param len - 缓冲区长度
- *
- * @return 平均值
- */
- uint16_t NTC_GetAverage(uint16_t *buf, uint16_t len)
- {
- if((buf == NULL) || (len == 0))
- return 0;
- uint32_t sum = 0;
- for(uint16_t i = 0; i < len; i++)
- {
- sum += (buf[i] & RB_ADC_DATA);
- }
- return (uint16_t)(sum / len);
- }
采集出来的信息通过CDC虚拟的串口打印,但是打印出来的却是明显与实际温度不对,
后面找了好久的错误,但一直都没有找到,本来想偷懒,不想看数据手册,现在没有办法了,只能拿出手册仔细查看了,不看不知道,一看吓一跳,这个ch592f与我们平时用的MCU的adc都不同,下面我贴出来,免得大家以后再继续踩坑。
原来它的ADC可以带放大的,还有参考电压不同,如是赶紧修改我的宏定义。
下面再编译下载,终于在串口打印出正常的室温了。
|