本帖最后由 siliconnect 于 2021-6-4 16:36 编辑
void adc_base_config(void)
{
/* 复位ADC外设 */
adc_deinit();
adc_disable();
/* 温度传感器和Vrefint通道禁能 */
adc_tempsensor_vrefint_disable();
/* 使能ADC 时钟*/
rcu_periph_clock_enable(RCU_ADC);
/* 配置ADC 时钟*/
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV8);
/* ADC 扫描模式禁止*/
adc_special_function_config(ADC_SCAN_MODE,DISABLE);
/* ADC 连续模式使能*/
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
/* ADC 数据对齐配置:右对齐*/
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* ADC 通道长度配置:1 */
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
adc_channel_length_config(ADC_INSERTED_CHANNEL, 1);
/* ADC 规则通道: CPU内部温度,规则组软件触发*/
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_SWRCST);
/* ADC 注入通道:ADC采集,注入组软件触发*/
adc_external_trigger_source_config(ADC_INSERTED_CHANNEL, ADC_EXTTRIG_INSERTED_SWRCST);
/* ADC 规则通道配置:规则组0、ADC通道16、采样时间*/
adc_regular_channel_config(0, ADC_CHANNEL_16, ADC_SAMPLETIME_55POINT5);
/* ADC 注入通道配置:注入组0、ADC通道1、采样时间*/
adc_inserted_channel_config(ADC_INSERTED_CHANNEL_0, ADC_CHANNEL_1, ADC_SAMPLETIME_28POINT5);
/* ADC 使能触发允许:规则组 */
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
/* ADC 使能触发允许:注入组 */
adc_external_trigger_config(ADC_INSERTED_CHANNEL, ENABLE);
/* 温度传感器和Vrefint通道使能 */
adc_tempsensor_vrefint_enable();
adc_enable();
delay_1ms(10); //wait≥1ms
adc_calibration_enable();
}
/*!
\brief pd_get_adc
\param[in] none
\param[out] none
\retval vol_value
*/
uint16_t adc_get_adc(uint8_t chn)
{
uint16_t adc_value;
adc_flag_clear(ADC_FLAG_EOC); //清除EOC 标志位
adc_software_trigger_enable(ADC_INSERTED_CHANNEL);
while(SET != adc_flag_get(ADC_FLAG_EOC)); //等待ADC 转换完成
adc_value = adc_inserted_data_read(chn);
return adc_value;
}
/*!
\brief adc_rcu_config
\param[in] none
\param[out] none
\retval none
*/
void adc_rcu_config(void)
{
rcu_periph_clock_enable(ADC_IN1_GPIO_CLK);
rcu_periph_clock_enable(RCU_ADC);
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
}
/*!
\brief adc_gpio_config
\param[in] none
\param[out] none
\retval none
*/
void adc_gpio_config(void)
{
/* config the GPIO as analog mode */
gpio_mode_set(ADC_IN1_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_IN1_GPIO_PIN);
}
void main(void)
{
uint16_t val;
//外部24MHz晶振,已正确倍频到72MHz
systick_config();
adc_rcu_config();
adc_gpio_config();
adc_base_config();
//.....
while(1)
{
//PA1是ADC管脚输入, 为了测试方便我固定接了一个2V的文博极低的电压测试
val=adc_get_adc(ADC_INSERTED_CHANNEL_0); //......
delay_ms(100);
}
}
问题描述,我就一个通道软件注入方式采集ADC,
还有一个是规则组的内部温度通道16,也是软件触发读
那这样配置没毛病吧?,但是如下配置每次复位CPU或者断电再上电ADC值 一部分情况2V,10次通断电或者软复位就有2次至少变 2.2V
adc_special_function_config(ADC_SCAN_MODE,DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, DISABLE);
但现在, 连续模式要设置enable才能正确读ADC值 每次都是 2.0V; 试过几百次都是正确的2.0Vadc_special_function_config(ADC_SCAN_MODE,DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
否则
这是为何呢?不要连续读,为何只能ADC_CONTINUOUS_MODE设置ENABLE才能正确读?百思不得解,还请帮忙看下哪里不对呢?
另外说明:CPU测温可以读出正确的,但应为CPU温度会变动些,这里我先没去关注它 是否对错。
CPU读温代码也贴下,如下:
/*!
\brief gd32_cpu_temperature
\param[in] none
\param[out] none
\retval (CPU实际温度值+273°C)x10倍 25.5°C=10*(25.5+273)=0BA9
*/
uint16_t gd32_cpu_temperature(void)
{
uint16_t adc_value;
uint16_t t_value;
float vol_value;
float cpu_temp;
adc_flag_clear(ADC_FLAG_EOC); //清除EOC 标志位
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
while(SET != adc_flag_get(ADC_FLAG_EOC)); //等待ADC 转换完成
adc_value = adc_regular_data_read();
vol_value = (float)adc_value*(3.3/4096); //转换为电压值
cpu_temp = ((1.43-(float)vol_value)/0.0043)+25; //计算温度
t_value=((int)(cpu_temp*10))%10; //取一位小数
t_value=(cpu_temp)*10; //扩大10倍
return t_value;
}
|