973|5

194

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

兆易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

 

 

代码如下:

04-ADC.zip (47.08 KB, 下载次数: 1)

最新回复

如果不飘,那它这个ADC做的还挺好。   详情 回复 发表于 2024-5-31 09:22
点赞 关注
 
 

回复
举报

7196

帖子

2

TA的资源

版主

沙发
 

可以给个中间一些的电压,看看采样会不会飘。

点评

我晚点还要再补充一下, 买了一点跳线帽,可以直接把滑动变阻器接到In通道上。我测试了。稳得很  详情 回复 发表于 2024-5-31 00:37
 
 
 

回复

194

帖子

4

TA的资源

纯净的硅(初级)

板凳
 
wangerxian 发表于 2024-5-30 18:28 可以给个中间一些的电压,看看采样会不会飘。

我晚点还要再补充一下, 买了一点跳线帽,可以直接把滑动变阻器接到In通道上。我测试了。稳得很

点评

如果不飘,那它这个ADC做的还挺好。  详情 回复 发表于 2024-5-31 09:22
 
 
 

回复

7196

帖子

2

TA的资源

版主

4
 
御坂10032号 发表于 2024-5-31 00:37 我晚点还要再补充一下, 买了一点跳线帽,可以直接把滑动变阻器接到In通道上。我测试了。稳得很

如果不飘,那它这个ADC做的还挺好。

点评

我补充了一个视频  详情 回复 发表于 2024-6-1 13:46
 
 
 

回复

194

帖子

4

TA的资源

纯净的硅(初级)

5
 

补充

 

1- 如果短接3v3和Vreference的话. 可以通过滑动变阻器来控制ADC的输入

2- 如果不使用3v3和Vreference的话,滑动变阻器不要处于处于最大值或者最小值,否则将会短路

 

WeChat_20240601133346

 

 
 
 

回复

194

帖子

4

TA的资源

纯净的硅(初级)

6
 
wangerxian 发表于 2024-5-31 09:22 如果不飘,那它这个ADC做的还挺好。

我补充了一个视频

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表