兆易GD32H759I-EVAL ADC 单次转换和连续转换
[复制链接]
本帖最后由 御坂10032号 于 2024-5-30 02:04 编辑
题外话
在上一章USART的代码完成之后今天就可以正式的开始ADC的功能测验了。
将USART的代码拷贝一份命名为ADC. 我们需要串口来实时输出ADC的转换结果
正文
和上个章节一样,创建一个bsp_adc.h 和 bsp_adc.c 并且在主函数中引入bsp_adc.h
在我们开始编码之前,让我们看一下GD32 的用户手册的这一章节。
GD32这款芯片一共是有三个ADC,分别是ADC0, ADC1,和ADC2, 其中ADC0和ADC1 的分辨率是最高14位,最低8位。 ADC2 的分辨率是12位,最低6位。
如下资料详见用户手册 Page 537
接下来让我们来看一下ADC的模块框图。用户手册539页
首先,图的最左侧为ADC的触发源。可以选择IO通道,选择内部湿温度传感器的输入。或者是外部电池电压。左下角呢则是为参考电压的输入。
图的上半部分呢则是选择ADC的触发方式,分别是软件触发以及触发器触发。无论哪一种方式的触发都会触发ADC的转换,当转换完成之后(EOC end of conversion)则判断是否进入中断(是否被屏蔽等)
SAR ADC支持自动校准功能,用户上电之后应该进行ADC的校准,并且等待ADC的校准完毕。在此期间用户不应该再操作ADC进行转换。 之后会根据配置的过采样寄存器判断是否需要对当前的ADC采集进行过采样。ADC0和1 支持1-1024倍的过采样。而ADC1 支持 1 - 256倍的过采样。
而对于ADC的转换模式一共有四种,分别是单次运行模式(单次转换模式),连续运行模式(连续转换), 扫描运行模式(扫描转换模式) 和 间断运行模式(间断转换模式)
四个的区别很好理解,第一个单次转换。就是每次出发后ADC只转换一次。 而连续运行模式的话支持ADC对某个通道对进行连续转换。而扫描转换模式,允许ADC对多个通道进行连续扫描转换。第四个间断运行模式则是允许ADC周期性的对选择的通道进行转换,比如说间隔一分钟等等。
理论基础已经完善了,接下来我们看下编码部分,该如何实现一次ADC的转换.
编码
可以根据上述原理图得知ADC2的0通道被连接到了PC2上。同时上述还有个测试断点可以方便我们测试ADC。
接下来我们来初始化时钟,IO和ADC
void init_adc(void)
{
/* 使能 GPIOC 时钟 */
rcu_periph_clock_enable(RCU_GPIOC);
/* 使能 ADC 时钟 */
rcu_periph_clock_enable(RCU_ADC2);
/* 重置 ADC */
adc_deinit(ADC2);
/* 配置 ADC 时钟 */
adc_clock_config(ADC2, ADC_CLK_SYNC_HCLK_DIV16);
/* 禁用 ADC 连续模式 */
adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, DISABLE);
/* 禁用 ADC 扫描模式 */
adc_special_function_config(ADC2, ADC_SCAN_MODE, DISABLE);
/* 配置 ADC 分辨率 */
adc_resolution_config(ADC2, ADC_RESOLUTION_12B);
/* 配置 ADC 数据对齐 */
adc_data_alignment_config(ADC2, ADC_DATAALIGN_RIGHT);
/* 配置 ADC 通道长度 */
adc_channel_length_config(ADC2, ADC_REGULAR_CHANNEL, 1);
/* 配置 ADC 常规通道 , 和采样时间*/
adc_regular_channel_config(ADC2, 0, ADC_CHANNEL_0, 239);
/* 使能 ADC 接口 */
adc_enable(ADC2);
/* 等待 ADC 稳定 */
delay_1ms(1);
/* 配置 ADC 校准模式 */
adc_calibration_mode_config(ADC2, ADC_CALIBRATION_OFFSET);
/* 启用 ADC 校准并重置校准 */
adc_calibration_enable(ADC2);
}
主程序:
#include "gd32h7xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "bsp_adc.h"
static void cache_enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
int main(void)
{
/* Enable the CPU Cache */
cache_enable();
/* Configure systick */
systick_config();
/* Initialize USART */
usart_init();
usart_receive_init();
/* Initialize ADC */
init_adc();
while (1) {
//开启ADC
adc_enable(ADC2);
//触发转换
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
//等待转换完成
while (!adc_flag_get(ADC2, ADC_FLAG_EOC));
delay_1ms(300);
//获取转换数据
uint32_t adc_value = adc_regular_data_read(ADC2);
printf("ADC2 Channel 0 Value: %u\n", adc_value);
//停止
adc_disable(ADC2);
}
}
注意,在上述代码中,如果你配置的是ADC的单次转换模式的话,必须在每次转换完成之后关闭ADC,然后再重复启用ADC开启下一次转换。 无法在单次转换模式下清除ADC_FLAG_EOC
,如果不关闭再启动ADC可能会导致每次ADC的转换都会读取上一次的转换结果。
错误示例(不提供错误的代码):
WeChat_20240530015629
正确的单次转换:
1
如下是配置为连续转换模式的代码, 只需要修改 adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, DISABLE) 成 adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, ENABLE)。 并且在主程序中删除掉 adc_enable(ADC2); 和 adc_disable(ADC2);
连续单通道模式配置:
void init_adc(void)
{
/* 使能 GPIOC 时钟 */
rcu_periph_clock_enable(RCU_GPIOC);
/* 使能 ADC 时钟 */
rcu_periph_clock_enable(RCU_ADC2);
/* 重置 ADC */
adc_deinit(ADC2);
/* 配置 ADC 时钟 */
adc_clock_config(ADC2, ADC_CLK_SYNC_HCLK_DIV16);
/* 禁用 ADC 连续模式 */
adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, ENABLE);
/* 禁用 ADC 扫描模式 */
adc_special_function_config(ADC2, ADC_SCAN_MODE, DISABLE);
/* 配置 ADC 分辨率 */
adc_resolution_config(ADC2, ADC_RESOLUTION_12B);
/* 配置 ADC 数据对齐 */
adc_data_alignment_config(ADC2, ADC_DATAALIGN_RIGHT);
/* 配置 ADC 通道长度 */
adc_channel_length_config(ADC2, ADC_REGULAR_CHANNEL, 1);
/* 配置 ADC 常规通道 , 和采样时间*/
adc_regular_channel_config(ADC2, 0, ADC_CHANNEL_0, 239);
/* 使能 ADC 接口 */
adc_enable(ADC2);
/* 等待 ADC 稳定 */
delay_1ms(1);
/* 配置 ADC 校准模式 */
adc_calibration_mode_config(ADC2, ADC_CALIBRATION_OFFSET);
/* 启用 ADC 校准并重置校准 */
adc_calibration_enable(ADC2);
}
主函数:
#include "gd32h7xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "bsp_adc.h"
static void cache_enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
SCB_EnableDCache();
}
int main(void)
{
/* Enable the CPU Cache */
cache_enable();
/* Configure systick */
systick_config();
/* Initialize USART */
usart_init();
usart_receive_init();
/* Initialize ADC */
init_adc();
while (1) {
adc_software_trigger_enable(ADC2, ADC_REGULAR_CHANNEL);
while (!adc_flag_get(ADC2, ADC_FLAG_EOC));
delay_1ms(300);
uint32_t adc_value = adc_regular_data_read(ADC2);
printf("ADC2 Channel 0 Value: %u\n", adc_value);
}
}
连续转换
WeChat_20240530020130
代码如下:
|