本文记录ADC测试电压和测温度功能
1. 配置ADC规则组的单通道作为电压测试, 配置ADC注入组单通道作为温度测试
2. 获取电压 get_voltage(chn) 和获取温度get_temperature()在ADC初始化后随时调用
3. 获取温度并显示get_temp_and_display()在rtc中断处理函数中,每5秒调用一次
4. GD32的例程中,触发注入组温度转换后,等了2秒后才读寄存器值计算温度
源码如下:
#include "adc.h"
#include "gd32l23x_adc.h"
#include "lcd12864.h"
#define ADC_TEMP_CALIBRATION_VALUE REG16(0x1FFFF7F8)
/*!
\brief init adc channel_1 and temperature channel
\param[in] none
\param[out] none
\retval none
*/
void adc_config_ch1_temp(void)
{
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC);
/* config ADC clock */
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV16);
/* enable GPIOA clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* config the GPIO as analog mode */
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
/* configure the VREF */
vref_deinit();
vref_high_impedance_mode_disable();
vref_enable();
// soft trigger regular channel polling
/* ADC data alignment config */
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* ADC channel length config */
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1U);
/* ADC trigger config */
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
/* ADC external trigger config */
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
//-----------------
// soft trigger inserted channel
/* ADC channel length config */
adc_channel_length_config(ADC_INSERTED_CHANNEL, 1);
/* ADC temperature sensor channel config */
adc_inserted_channel_config(0U, ADC_CHANNEL_16, ADC_SAMPLETIME_239POINT5);
/* ADC trigger config */
adc_external_trigger_source_config(ADC_INSERTED_CHANNEL, ADC_EXTTRIG_INSERTED_NONE);
/* ADC temperature and Vrefint enable */
adc_channel_16_to_19(ADC_TEMP_CHANNEL_SWITCH, ENABLE);
adc_external_trigger_config(ADC_INSERTED_CHANNEL, ENABLE);
/* 64 times sample, 6 bits shift */
adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_8B, ADC_OVERSAMPLING_RATIO_MUL256);
adc_oversample_mode_enable();
//-----------------
/* enable ADC interface */
adc_enable();
delay_1ms(1U);
/* ADC calibration and reset calibration */
adc_calibration_enable();
/* ADC software trigger enable */
adc_software_trigger_enable(ADC_INSERTED_CHANNEL);
}
/*!
\brief ADC channel sample
\param[in] none
\param[out] none
\retval none
*/
uint16_t adc_channel_sample(uint8_t channel)
{
/* ADC regular channel config */
adc_regular_channel_config(0U, channel, ADC_SAMPLETIME_7POINT5);
/* ADC software trigger enable */
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
/* wait the end of conversion flag */
while(!adc_flag_get(ADC_FLAG_EOC));
/* clear the end of conversion flag */
adc_flag_clear(ADC_FLAG_EOC);
/* return regular channel sample value */
return (adc_regular_data_read());
}
/*!
\brief get voltage once
\param[in] none
\param[out] none
\retval none
*/
float get_voltage(uint8_t chn)
{
float v = 0.0f;
uint16_t adc_val = 0;
adc_val = adc_channel_sample(chn);
v = (float)adc_val*3.3f/4095.0f;
return v;
}
/*!
\brief get temperature and display, then trig inserted channel once
\param[in] none
\param[out] none
\retval none
*/
void get_temp_and_display(void)
{
float t;
int32_t value;
value = (int32_t)ADC_TEMP_CALIBRATION_VALUE;
t = ((float)((int32_t)ADC_IDATA0 - value) * 3.3f / 4095.0f * 1000.0f / 3.3f) + 30.0f;
LCD_printf_line(5,"* %.3f *", t);
/* ADC software trigger enable */
adc_software_trigger_enable(ADC_INSERTED_CHANNEL);
}
/*!
\brief get temperature once
\param[in] none
\param[out] none
\retval none
*/
float get_temperature(void)
{
float temperature;
int32_t value;
static uint8_t first_trig = 0;
/* ADC software trigger enable */
adc_software_trigger_enable(ADC_INSERTED_CHANNEL);
if (0 == first_trig)
{
first_trig = 1;
delay_1ms(2000U);
}
/* wait the end of conversion flag */
while(!adc_flag_get(ADC_FLAG_EOIC));
/* clear the end of conversion flag */
adc_flag_clear(ADC_FLAG_EOIC);
/* value convert */
value = (int32_t)ADC_TEMP_CALIBRATION_VALUE;
temperature = ((float)((int32_t)ADC_IDATA0 - value) * 3.3f / 4095.0f * 1000.0f / 3.3f) + 30.0f;
return temperature;
}
rtc中断处理函数
void RTC_Alarm_IRQHandler(void)
{
static uint8_t cnt = 0;
if (SET == rtc_flag_get(RTC_FLAG_ALARM0))
{
exti_flag_clear(EXTI_17);
rtc_flag_clear(RTC_FLAG_ALARM0);
get_rtc_time_and_display();
}
cnt++;
if(5 == cnt)
{
cnt = 0;
get_temp_and_display();
}
}
|