吐槽写在前面
不知道是我的使用方法不对,还是华大这个内部温度传感器是真的难用。反正我现在认为华大的MCU设计还是有待提高。下面的内容,如果有华大的技术人员看到了,劳烦你解释一下原因或者更优的解决办法。
起因是我的应用电路里面,有一路ADC需要MCU采集, 同时,我还需要使用MCU内部温度传感器。 虽然MCU的内部温度传感器是内部的,但可以说我有两路ADC需要采集。也可以说我有多路ADC需要采集。 我使用ADC的单次模式,只对内部温度传感器通道采集温度,是没有问题的,已经用红外热像仪检验过了。
之前我用驱动库example里面的,顺序扫描模式和插队扫描模式,得到的温度采集通道结果都不对(超过100℃大得离谱,反正正常智商都能判断结果是不对的)。
我原本以为是顺序扫描和插队扫描这扫描模式本身的问题。所以我尝试用单次模式实现多通道的读取。(思路是:我每次只采集一次,转换完把数据读取之后,我把单次采集的通道号换成另一个需要采集的通道。然后再去采集。)
但是我发现,结果和两种扫描模式的结果并无不同。 也就是说温度值不对,与ADC的单次模式与扫描模式本身是无关的。
------------------------------------------
卡了很久,苦思不得其解。 后面尝试调整ADC配置的两个参数,才逐步找到问题。
第一个参数是 ADC采样分频, 它只有4个选项:
我选择了8分频
第二个采样参数是ADC采样周期,它也只有4个选项
我选择 12个转换周期。
经过上述的ADC控制参数的调整,温度的测量结果 和 使用单次采样模式只测量温度时已经接近了,但还是存在大约3℃的偏差。 从上面的调参来看,我把采样的时间调长一点,温度的测量就会越准确。 那么问题就可以确定在采样时长上了。
为了更准确, 我把MCU的PCLK再次调低。 发现此时的温度测量 和 使用单次采样模式只测量温度时的测量结果就一致了。
------------------------------------------
按理说这个问题已经解决了, 为什么存在本文开篇的吐槽呢。
就是当我降低了PCLK主频之后, 串口通信不正常了, 115200的波特率已经不支持了。I2C的通信也不正常了, 1000000的波特率也不支持了。如果产品没有要求115200的通信波特率也就罢了, 产品甚至要求更高的230400的波特率。那么此次就出现了矛盾, 我必须在内部温度传感器 与 串口之间做一个折衷选择。这怎么选?
还是说,我的解决思路有问题,那么请华大的技术人员给点建议,谢谢。
------------------------------------------
下面先给出目前使用单次采样模式的多通道采样程序,这东西还是有参考价值的。
使用顺序扫描和插队扫描应该也能实现的,参考驱动与例子库的 example。
main.c
#include "ddl.h"
#include "uart.h"
#include "gpio.h"
#include "dac.h"
#include "flash.h"
#include "i2c.h"
#include "user_gpio.h"
#include "user_uart.h"
#include "user_dac.h"
#include "user_adc.h"
#include "user_i2c.h"
#include "execute_pc_cmd.h"
#include "execute_fpga_cmd.h"
uint8_t Whoiam;
uint8_t i2cdata;
en_result_t I2CRet = Error;
float Vapd = 0.0;
int16_t DAC_OUT_TEMP = 0;
int32_t main(void)
{
sys_clk_init();
user_apdgpio_init();
user_uart_init();
user_dac_init();
user_adc_init();
user_i2c_init();
kx023_1025_config();
apd_enable();
while(Ok != Flash_Init(1, TRUE)){
;
}
while(1)
{
if(FpgaRxQueue.size > 0){
QueuePop(&FpgaRxQueue, fpgaRx);
fpgaRxFlag = 1;
}
if(PcRxQueue.size > 0){
QueuePop(&PcRxQueue, pcRx);
pcRxFlag = 1;
}
if(fpgaRxFlag == 1){
fpga_cmd_ret = execute_fpga_cmd();
// send_data_to_fpga(fpgaRx, 8);
fpgaRxFlag = 0;
}
if(pcRxFlag ==1 ){
pc_cmd_ret = execute_pc_cmd();
//send_data_to_pc(pcRx, 8);
pcRxFlag = 0;
}
user_apd_output_set(140);
get_apd_adc(); // ▲ 重点是这
get_temperature_adc(); // ▲ 和这
kx023_1025_read();
send_data_to_pc(angle_data,8);
delay1ms(1);
}
}
user_adc.c
#include "user_adc.h"
#include "gpio.h"
#include "bgr.h"
#include "adc.h"
uint8_t ADC_UNIT = ERROR_UNIT;
uint8_t ADC_FLAG = ADC_WAITING;
uint16_t Trim = 0;
uint32_t u32AdcRestult0;
uint32_t u32AdcRestultTemperature;
float Vapd_sense = 0;
float temperature = 0;
// ADC端口 配置
void adc_gpio_config(void)
{
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); // 开启ADC/BGR GPIO外设时钟
Gpio_SetAnalogMode(GpioPortA, GpioPin0); // PA00 (AIN0)
}
// ADC模块 初始化
void adc_config(void)
{
stc_adc_cfg_t stcAdcCfg;
DDL_ZERO_STRUCT(stcAdcCfg);
// 开启ADC/BGR外设时钟
Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);
Bgr_BgrEnable(); // 开启BGR
Bgr_TempSensorEnable(); // 【开启温度传感器】
// ADC 初始化配置
stcAdcCfg.enAdcMode = AdcSglMode; // 采样模式-单次
stcAdcCfg.enAdcclkDiv = AdcMskClkDiv8; // 采样分频-1
stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk; // 采样周期数-12
stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelInBgr2p5; // 参考电压选择-内部2.5V
stcAdcCfg.enAdcopBuf = AdcMskBufEnable; // OP BUF配置-开
stcAdcCfg.enInRef = AdcMskInRefEnable; // 内部参考电压使能-开 AdcMskInRefdisable AdcMskInRefEnable
stcAdcCfg.enAdcAlign = AdcAlignRight; // 转换结果对齐方式-右
Adc_Init(&stcAdcCfg);
}
// ADC 温度单次采样模式 配置
void get_temperature_adc(void)
{
Adc_CfgSglChannel(AdcAiTsInput);
// 启动单次转换采样
Adc_SGL_Start();
ADC_FLAG = ADC_WAITING;
while(ADC_FLAG == ADC_WAITING){
if(TRUE == Adc_GetIrqStatus(AdcMskIrqSgl))
{
Adc_ClrIrqStatus(AdcMskIrqSgl); ///< 清除中断标志位
u32AdcRestultTemperature = Adc_GetSglresult();
Trim = *((uint16_t *)(0x00100C36));
temperature = 25 + 0.2135 * (float)(u32AdcRestultTemperature - Trim );
ADC_FLAG = ADC_COMPLETED;
// Adc_SGL_Stop(); ///< ADC 单次转换停止
}
}
}
// ADC 温度单次采样模式 配置
void get_apd_adc(void)
{
Adc_CfgSglChannel(AdcExInputCH0);;
// 启动单次转换采样
Adc_SGL_Start();
ADC_FLAG = ADC_WAITING;
while(ADC_FLAG==ADC_WAITING){
if(TRUE == Adc_GetIrqStatus(AdcMskIrqSgl))
{
Adc_ClrIrqStatus(AdcMskIrqSgl); ///< 清除中断标志位
u32AdcRestult0 = Adc_GetSglresult();
Vapd_sense = (float)u32AdcRestult0*0.054267632; // 2.5V内部参考电压
ADC_FLAG = ADC_COMPLETED;
// Adc_SGL_Stop(); ///< ADC 单次转换停止
}
}
}
void user_adc_init(void){
adc_gpio_config();
adc_config();
}
user_adc.h
#ifndef _USER_ADC_H_
#define _USER_ADC_H_
#include "ddl.h"
#define ERROR_UNIT 0
#define TEMPERATURE_UNIT 1
#define APD_UNIT 2
#define ADC_WAITING 0
#define ADC_COMPLETED 1
extern float temperature;
extern float Vapd_sense;
extern uint8_t ADC_UNIT;
extern uint8_t ADC_FLAG;
void adc_gpio_config(void);
void adc_config(void);
void user_adc_init(void);
void get_temperature_adc(void);
void get_apd_adc(void);
#endif
感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。
原文地址:https://www.jb51.cc/wenti/3285208.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。