前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >M-Arch(番外8)GD32L233评测-ADC和DMA(官方没有例程哦)

M-Arch(番外8)GD32L233评测-ADC和DMA(官方没有例程哦)

作者头像
滚神大人
发布于 2022-04-18 06:16:20
发布于 2022-04-18 06:16:20
93100
代码可运行
举报
文章被收录于专栏:趣Python趣Python
运行总次数:0
代码可运行

前言

开工第一天,今天是DMA方式的ADC采样。

什么是ADC?

ADC即模拟数字转换器,ADC的精度一般用位来表示,位数越多,表示相同模拟量范围内的采样点数越多,那么相应的精度就越高。

比如:12位表示的范围是0 ~ 2^12 (4096),8位表示的范围是0 ~ 2^8 (256),前者的精度是后者的16倍。

ADC一般需要配置的内容包括:

  1. IO配置(时钟,模拟输入)
  2. ADC参数配置(模式-扫描模式,连续模式;触发方式;通道配置-规则组or注入组;ADC校正)
  3. 中断和DMA(使能)配置

【注】ADC的规则组和注入组的区别可简单理解为:规则组是周期执行的程序,注入组是中断程序。

什么是DMA?

DMA即直接存储器访问控制器,DMA提供了一种硬件的方式在外设和存储器之间或者存储器和存储器之间传输数据,而无需CPU的介入,避免了CPU多次进入中断进行大规模的数据拷贝,最终提高整体的系统性能。

简单而言,DMA相当于是外请(DMA硬件)的搬运工(数据拷贝),节约宝贵的CPU资源。

DMA一般需要配置的内容包括:

  1. IO配置(时钟)
  2. DMA参数配置(拷贝的方向,内容,地址,通道,模式和数量等)
  3. 中断(使能)配置

DMA的配置需要注意通道的匹配:

STM32F103 DMA通道配置

GD32F450 DMA通道配置

注意,在GD32L233中新增了一个DMAMUX的设计,即在DMA控制器前一级增加了的多路选择器,相比如上图,它的好处是更灵活,缺点当然也是更灵活了。

GD32L233 DMAMUX结构

从设计的角度来看,这种配置个人觉得固定成一张表更好理解和处理。

ADC如何DMA?

基本说明

先把DMA的概念代入,ADC属于外设,我们一般使用ADC的DMA是把ADC的采样数据传送到内存中供程序使用,那么它的处理数据链是:ADC通道数据地址-DMA缓存数据-滤波-业务层数据,DMA的确是省了很多软件的事

架构和流程

基本架构:

流程和数据结构

代码设计

由于单片机内置了CPU温度值,Vrefint和Vbatt(STM32无Vbatt)的采样通道,这里的示例用这几个通道来做示例。

GD32L233的温度计算公式跟GD32F450不一样,在用户手册中写清楚了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
温度(°C) = ((Dtemperature – D30) / Avg_Slope) + 30

D30在芯片内固定:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define ADC_TEMP_CALIBRATION_VALUE        REG16(0x1FFFF7F8)
adc和dma

adc配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void adc1_init(int32_t channel_num)
{
    /* enable ADC clock */
    rcu_periph_clock_enable(RCU_ADC);    
    rcu_periph_clock_enable(RCU_GPIOA);

    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
    /* config ADC clock */
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV16);
    /* ADC SCAN function enable */
    adc_special_function_config(ADC_SCAN_MODE, ENABLE);
    /* conyinuous mode */
    adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
    adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
    adc_channel_length_config(ADC_REGULAR_CHANNEL, channel_num);

    /* ADC temperature and Vrefint enable */
    adc_channel_16_to_19(ADC_TEMP_CHANNEL_SWITCH, ENABLE);
    adc_channel_16_to_19(ADC_INTERNAL_CHANNEL_SWITCH, ENABLE);
    adc_channel_16_to_19(ADC_VBAT_CHANNEL_SWITCH, ENABLE);

    adc_regular_channel_config(0, ADC_CHANNEL_adc_test,   ADC_SAMPLETIME_239POINT5);
    adc_regular_channel_config(1, ADC_CHANNEL_cpu_temper, ADC_SAMPLETIME_239POINT5);
    adc_regular_channel_config(2, ADC_CHANNEL_cpu_vref,   ADC_SAMPLETIME_239POINT5);
    adc_regular_channel_config(3, ADC_CHANNEL_vbatt,      ADC_SAMPLETIME_239POINT5);

    /* enable ADC interface */
    adc_enable();
    adc_dma_mode_enable();
    delay_ms(1U);

    /* ADC calibration and reset calibration */
    adc_calibration_enable();
    adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
}

DMA配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void adc1_dma_init(uint32_t addr, uint32_t number)
{
    /* ADC_DMA_channel configuration */
    dma_parameter_struct dma_parameter;

    /* enable DMA0 clock */
    rcu_periph_clock_enable(RCU_DMA);

    /* ADC DMA_channel configuration */
    dma_deinit(DMA_CH0);

    /* initialize DMA data mode */
    dma_struct_para_init(&dma_parameter);
    dma_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_parameter.periph_addr = (uint32_t)(&ADC_RDATA);
    dma_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
    dma_parameter.memory_addr = addr;
    dma_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT;
    dma_parameter.number = number;
    dma_parameter.priority = DMA_PRIORITY_HIGH;
    dma_parameter.request = DMA_REQUEST_ADC;
    dma_init(DMA_CH0, &dma_parameter);
    dma_circulation_enable(DMA_CH0);

    dma_interrupt_enable(DMA_CH0, DMA_CHXCTL_FTFIE);
    nvic_irq_enable(DMA_Channel0_IRQn, 2);
    
    dma_channel_enable(DMA_CH0);
}
业务代码

头文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

#define COFF_33_4096_10000000x          8057    ///< 3.3/4096 (10000000)

#if defined(GD32M0)

#define COFF_VBATT  3
#define CPU_TEMP_AD_BASE_1000x          30000   ///< 30度
#define ADC_TEMP_CALIBRATION_VALUE        REG16(0x1FFFF7F8)

#define GET_CPU_TEMPERATURE(data) CPU_TEMP_AD_BASE_1000x + (data - (int32_t)ADC_TEMP_CALIBRATION_VALUE) * COFF_1_4096_10000000x / 10
#define GET_CPU_VREF(data) COFF_33_4096_10000000x*data/10000
#define GET_CPU_VBATT(data) COFF_33_4096_10000000x*data*COFF_VBATT/10000

#define ADC_CHANNEL_adc_test    ((uint8_t)ADC_CHANNEL_1)
#define ADC_CHANNEL_cpu_temper  ((uint8_t)ADC_CHANNEL_16)
#define ADC_CHANNEL_cpu_vref    ((uint8_t)ADC_CHANNEL_17)
#define ADC_CHANNEL_vbatt       ((uint8_t)ADC_CHANNEL_18)

#endif

DMA中断函数:

测试结果

数据扩大1000倍,其中2~4依次是温度,参考电压和电池电压。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
adc = [1143] [23654] [1198] [3304]
adc = [1144] [22677] [1198] [3304]
adc = [1144] [22922] [1198] [3304]
adc = [1144] [23410] [1198] [3304]
adc = [1144] [23654] [1198] [3304]
adc = [1144] [22922] [1198] [3304]
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 趣Python 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
M-Arch(5)第四个示例:ADC&DMA
本文我们将总结下ADC和DMA的基本使用方法,并给出示例,从中我们可以看到GD和STM在设计上的差别。
滚神大人
2021/10/08
5700
【GD32L233C-START】7、使用内部参考电压校准adc,adc采样更准确
可以看出GD32L233C-START开发板,也就是芯片GD32L233CCT6有一个ADC外设,10个外部通道,4个内部通道; 10个外部通道,分别是ADC_IN0-ADC_IN9,对应GPIO为PA0-PA7,PB0-PB1; 4个内部通道,分别是ADC_IN16-ADC_IN19,对应内部温度传感器电压输出、内部参考电压输出、VBAT 引脚上电压除以3、VSLCD引脚上电压除以3。
ManInRoad
2022/04/04
2.3K0
【GD32L233C-START】7、使用内部参考电压校准adc,adc采样更准确
M-Arch(番外9)GD32L233评测-DAC波形发生器(三角波,方波,正弦波,任意波)
前面我们讲过了ADC是把模拟量转成数字量,那么DAC就是反过来,即把数字量转成模拟量。
滚神大人
2022/04/18
6540
M-Arch(番外9)GD32L233评测-DAC波形发生器(三角波,方波,正弦波,任意波)
M-Arch(番外4)GD32L233评测-系统资源主要频率获取和打印
白高兴了一番,详细查了datasheet,竟然不支持SLCD,白瞎了我买的一块68的裸屏,后面还得折腾一块LCD驱动。
滚神大人
2022/03/22
5080
M-Arch(番外4)GD32L233评测-系统资源主要频率获取和打印
M-Arch(8)第七个示例:串口和DMA
由于之前我们已经使用了串口1(STM中是USART1,GD中是USART0),本文中以串口2作为示例(STM中是USART2,GD中是USART1)。
滚神大人
2022/03/22
6280
M-Arch(8)第七个示例:串口和DMA
M-Arch(番外6)GD32L233评测-随机数(附 软件随机数生成算法)
先来啰嗦的说一下随机数的概念,真随机数指通过物理现象来产生的随机数,比如噪声,核裂变等,伪随机数是通过软件算法可重复生成的随机数。
滚神大人
2022/03/22
4810
M-Arch(番外6)GD32L233评测-随机数(附 软件随机数生成算法)
M-Arch(6)第五个示例:DAC
本文我们将总结下DAC的基本使用方法,并通过DAC生成任意频率的正弦波,三角波和方波。
滚神大人
2021/10/08
4940
M-Arch(番外10)GD32L233评测-SPI驱动DS1302
串行外设接口(Serial Peripheral Interface,缩写为SPI)提供了基于SPI协议的数据发送和接收功能,可以工作于主机或从机模式。SPI接口支持具有硬件CRC计算和校验的全双工和单工模式。有些SPI口还支持SPI四线主机模式。
滚神大人
2022/06/09
8700
M-Arch(番外10)GD32L233评测-SPI驱动DS1302
【GD32L233C-START】13、RT-Thread移植到GD32L233
或者离线下载安装: https://www.rt-thread.org/download/mdk/RealThread.RT-Thread.3.1.5.pack
ManInRoad
2022/04/04
9680
【GD32L233C-START】13、RT-Thread移植到GD32L233
【GD32L233C-START】3、pwm实现呼吸灯
1、硬件连接 2、PWM通道 可以看出,PC6对应的是TIME2的CH0通道。 3、实现方法 通过调节占空比,递增占空比,led逐渐变亮,视觉上是呼吸灯的效果。 4、核心代码 (1)pwm初始化 void PwmInit(void) { rcu_periph_clock_enable(RCU_GPIOC); /* TIMER1 GPIO */ gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6 );
ManInRoad
2022/02/09
7090
【GD32L233C-START】3、pwm实现呼吸灯
M-Arch(番外7)GD32L233评测-FLASH读写
闪存控制器(FMC),提供了片上闪存需要的所有功能。一般而言,MCU的Flash包括4个部分:
滚神大人
2022/03/22
6270
M-Arch(番外7)GD32L233评测-FLASH读写
M-Arch(2)第一个示例:串口和CRC
先把背景交代一下,上一篇讲了下基本的设计意图和框架,实际上整体框架已经有了,这篇先把整个框架再描述下,再来实现我们的第一个例子。
滚神大人
2021/09/10
4250
【STM32H7教程】第46章 STM32H7的ADC应用之DMA方式多通道采样
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第46章       STM32H7的ADC应用之DMA方式多通道采样
Simon223
2020/02/14
3.5K0
RT-Thread 移植到GD32F150系列mcu
https://www.rt-thread.org/page/download.html
ManInRoad
2021/10/20
1.1K0
RT-Thread 移植到GD32F150系列mcu
【GD32L233C-START】2、非阻塞方式点灯,blink,blink,blink……
官方的demo用的阻塞方式点灯,即就是死等,在等待期间mcu干不了其他事情(中断除外),这种方式不太友好,本文使用非阻塞方式点灯。
ManInRoad
2022/02/09
4480
【GD32L233C-START】2、非阻塞方式点灯,blink,blink,blink……
【GD32L233C-START】14、RT-Thread多线程、消息队列使用
三个线程,一个消息队列(大小是1,长度是12) 线程1:LED 500ms闪烁一次; 线程2:adc采样; 线程3:oled显示; 在线程2中,采样到数据后,通过消息队列发送到线程3,线程3收到消息后,更新oled显示。
ManInRoad
2022/04/04
4590
【GD32L233C-START】14、RT-Thread多线程、消息队列使用
【GD32L233C-START】8、按键—外部中断
可以看出,PA0通过R29下拉到GND,按键按下时, PA0的电压为3.3V,没有按下时,PA0的电压为0V,因此可以通过判断上升沿,判断按键是否按下。
ManInRoad
2022/04/04
8990
【GD32L233C-START】8、按键—外部中断
M-Arch(10)第九个示例:SPI与DS1302
本文我们将介绍下SPI的概念,以及如何使用三线SPI的时序驱动DS1302时钟芯片,同时我们也将给出用模拟IO方式驱动DS1302的方法。
滚神大人
2021/11/02
8920
stm32_DMA采集一个AD数据_并通过DMA向串口发送
这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影。关于dma网上有许多的资料,关于dma采集ad网上也有很多。亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但
杨奉武
2018/04/18
1.1K0
stm32_DMA采集一个AD数据_并通过DMA向串口发送
怎样更好的利用DMA来实现采样数据的直接搬运存储
尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了。
用户6754675
2020/07/20
6810
推荐阅读
相关推荐
M-Arch(5)第四个示例:ADC&DMA
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验