[GD32L233C-START Review] 11. DAC output voltage value_ADC reads external voltage value
[Copy link]
This post was last edited by hehung on 2022-2-12 14:25
For previous posts, please refer to:
【GD32L233C-START Review】1. Unboxing
[GD32L233C-START Review] 2. Create a new project step by step
[GD32L233C-START Evaluation] 3. Porting FreeRTOS to GD32L233
【GD32L233C-START Review】4. Porting RT-Thread to GD32L233
【GD32L233C-START Review】5. IIC driving OLED
【GD32L233C-START Review】6. Get RTC time and display it through OLED
【GD32L233C-START Review】7. PWM LED Driver
[GD32L233C-START Review] 8. TRNG True Random Number Generation
【GD32L233C-START Review】9. CRC Check
【GD32L233C-START Review】10. ADC reads the internal temperature of the chip
This post explains how to use the DAC module to output voltage values and read the voltage value output by the DAC through the external pins of the ADC module.
I originally wanted to devote a chapter to describing how to use the external pins of the ADC to read voltage values. However, I don’t have a sensor with analog voltage output and cannot verify it. What should I do?
I thought that I could use the DAC module of the microcontroller to output the voltage value, and then use the ADC external pin to read it, so I did it right away.
1. Analog port query
We can see that the analog pins on the GD32L233C development board are PA1-PA5, and the corresponding ADC channels are 1-5, which can be found in the data sheet as follows:
2. ADC module
We have already had a preliminary understanding of the ADC module in the previous post, the difference is that this post uses external pins.
The ADC uses software triggering and 12-bit sampling width.
Use PA1 - Channel 1 of ADC as the sampling channel.
3. DAC module usage
See User Manual 14. Digital-to-Analog Converter (DAC)
The same applies for 12-bit width, software triggering, and no buffering.
Use the DAC output channel, namely PA4-DAC_OUT, as the analog voltage output channel, as shown below:
4. Code Editing
1. Clock initialization
Initialization requires initialization of GPIOA clock, ADC clock, APH clock, DAC clock
void rcu_config(void)
{
/* enable GPIOC clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC);;
/* config ADC clock */
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
/* enable DAC clock */
rcu_periph_clock_enable(RCU_DAC);
}
2. GPIO clock
void gpio_config(void)
{
/* config the GPIO as analog mode */
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1 | GPIO_PIN_4);
}
3. ADC initialization
void adc_config(void)
{
/* 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);
/* enable ADC interface */
adc_enable();
delay_1ms(1U);
/* ADC calibration and reset calibration */
adc_calibration_enable();
}
4. ADC reading
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());
}
5. DAC Initialization
void dac_config(void)
{
dac_deinit();
/* output buffer config */
dac_output_buffer_enable();
dac_output_buffer_disable();
/* trigger config */
dac_trigger_source_config(DAC_TRIGGER_SOFTWARE);
/* dac enable */
dac_enable();
/* enable software trigger */
dac_software_trigger_enable();
}
6. Output DAC analog voltage value
The DAC voltage is represented by a number, and because it is 12 bits, the maximum value is 4096.
Start outputting from 0, add 100 every second, and when it is greater than 4096, start outputting the voltage value again from 0.
if(dac_value > DAC_VALUE_MAX)
{
dac_value = 0;
}
else
{
dac_value += 100;
}
/* output data config */
dac_data_set(DAC_ALIGN_12B_R, dac_value);
7. Read the output analog voltage value and output it through the serial port
/* read adc value */
adc_value = adc_channel_sample(ADC_CHANNEL_1);
printf("read dac value:%d,voltage:%.2f\r\n", adc_value, dac_value/4096.0*3.3);
8.main function
int main(void)
{
/* system clocks configuration */
rcu_config();
/* systick configuration */
systick_config();
/* USART configuration */
gd_eval_com_init(EVAL_COM);
/* GPIO configuration */
gpio_config();
/* ADC configuration */
adc_config();
/* configure the DAC */
dac_config();
dac_value = 0;
while(1) {
if(dac_value > DAC_VALUE_MAX)
{
dac_value = 0;
}
else
{
dac_value += 100;
}
/* output data config */
dac_data_set(DAC_ALIGN_12B_R, dac_value);
printf("output dac value:%d, voltage:%.2f\r\n",dac_value, dac_value/4096.0*3.3);
/* read adc value */
adc_value = adc_channel_sample(ADC_CHANNEL_1);
printf("read dac value:%d,voltage:%.2f\r\n", adc_value, dac_value/4096.0*3.3);
printf("---\r\n");
delay_1ms(1000);
}
}
8. Use large global variables and macro definitions
#define DAC_VALUE_MAX (4096)
uint16_t adc_value;
uint16_t dac_value;
5. Effect Demonstration
As mentioned above, use PA4 to output analog voltage value 0-3.3V, and digital value 0-4095.
Use PA1 to read the analog voltage value, so you need to connect PA4 and PA1 together.
PA1 ---- PA4
As shown below:
The effect is as follows:
It can be seen that there is a difference of several values between the output analog voltage value and the read analog voltage value. However, after converting to voltage and taking two decimal places, the output analog voltage and the collected voltage are basically the same. The accuracy is still very high and can meet the usage requirements of most occasions.
|