GD32 MCU 常见外设介绍(TIMER\ADC)

[复制链接]
260|1
手机看帖
扫描二维码
随时随地手机跟帖
智芯云技术|  楼主 | 2023-12-27 11:36 | 显示全部楼层 |阅读模式
AD, ADC, MCU, TI, dc
本帖最后由 智芯云技术 于 2023-12-27 11:42 编辑

本帖介绍TIMER、 ADC外设,提供样品技术支持

欢迎联系,q 1392254786

TIMER 模块介绍

TIMER 基础知识
TIMER分高级定时器,通用定时器L0,L1,L2和基本定时器。 90937658b98317e50c.png

硬件连接说明
TIMER 属于片内外设,对于外部硬件设计,只需要单独IO口外接信号线即可。

GD32 TIMER 外设原理简介

GD32 TIMER 主要特性

◼ 总通道数: 4;
◼ 计数器宽度: 16位;
◼ 定时器时钟源可选:内部时钟,内部触发,外部输入,外部触发;
◼ 多种计数模式:向上计数,向下计数和中央计数;
◼ 正交编码器接口:用来追踪运动和分辨旋转方向和位置;
◼ 霍尔传感器接口:用来做三相电机控制;
◼ 可编程的预分频器: 16位。运行时可以被改变;
◼ 每个通道可配置:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式;
◼ 可编程的死区时间;
◼ 自动重装载功能;
◼ 可编程的计数器重复功能;
◼ 中止输入功能;
◼ 中断输出和DMA请求:更新事件,触发事件,比较/捕获事件和中止事件;
◼ 多个定时器的菊链使得一个定时器可以同时启动多个定时器;
◼ 定时器的同步允许被选择的定时器在同一个时钟周期开始计数;
◼ 定时器主/从模式控制器。

TIMER 结构框图介绍
206658b98c715705.png

软件配置说明

定时中断 TIMER4

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。这一章,将使用定时器产生中断,然后在中断服务函数里面翻转 LED上的电平,来指示定时器中断的产生。接下来我们以通用定时器 TIMER4 为实例,来说明要经过哪些步骤,才能达到这个要求,并产生中断。定时器配置步骤如下:

1)TIMER4 时钟使能
13280658b99038fa99.png
2) 初始化定时器参数,设置自动重装值, 分频系数,计数方式等
在库函数中,定时器的初始化参数是通过初始化函数 timer_parameter_struct 实现的:
void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);
第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结构体指针,结构体类型为 timer_parameter_struct ,下面我们看看这个结构体的定义:
42171658b9942c0f41.png
41586658b994fb69f9.png
针对 TIMR4 初始化范例代码格式
92606658b9963c540a.png
3)设置 TIMER 允许更新中断
因为我们要使用 TIMER4 的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定时器中断使能是通过 timer_interrupt_enable函数来实现的:
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
第一个参数是选择定时器号,这个容易理解。第二个参数非常关键,是用来指明我们使能的定时器中断的类型。
4) TIMER4 中断优先级设置
在定时器中断使能之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,设置中断优先级。通过nvic_irq_enable 函数实现中断优先级的设置。针对 TIMR4 初始化范例代码格式
nvic_irq_enable(TIMER4_IRQn, 1, 1);
5)允许 TIMER工作,也就是使能 TIMER
光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,在固件库里面使能定时器的函数是通过timer_enable函数来实现的
void timer_enable(uint32_t timer_periph)
这个函数非常简单,比如我们要使能TIMER4,方法为:
timer_enable(TIMER4);
6)编写中断服务函数
在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,在处理完中断之后应来清除该中断标志。
在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:
FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)
该函数的作用是,判断定时器 TIMER 的中断类型,并判断是否发生中断。针对 TIMR4 中断服务函数范例代码:
96565658b99fdd35d7.png

PWM 输出 TIMER0
高级定时器(TIMER0和TIMER7)是四通道定时器,支持输入捕获和输出比较。可以产生PWM信号控制电机和电源管理。高级定时器含有一个16位无符号计数器。高级定时器是可编程的,可以用来计数,其外部事件可以驱动其他定时器。高级定时器包含了一个死区时间插入模块,非常适合电机控制。本章,我们使用的是 TIMER0的通道0 输出 PWM(脉冲宽度调制)。下面我们介绍通过库函数来配置该功能的步骤:
(1)开启 TIMER0 和 GPIO 时钟,配置 PA8复用功能输出。
4005658b9a22c4f61.png
这里还需要说明一下, 对于定时器通道的引脚关系,引脚的IO口
98564658b9a36b97d6.png
这里补充说明下关于TIMER的相关GPIO口的命名
TIMERx_CHx : 定时器通道x
TIMERx_CHx_ON :定时器反向通道
TIMERx_BRKIN :刹车引脚
TIMERx_ETI:外部时钟输入
(2)初始化 TIMER0 ,设置 TIMER0 的预分频和周期等参数, ,在上一节定时器中断章节我们已经有讲解,这里就不详细讲解,调用的格式为

86275658b9a7104090.png
3)设置 TIMER0_CH0 的 PWM 模式, 使能 TIMER0 的 CH0 输出。在库函数中, PWM 通道设置是通过函数 timer_channel_output_config来设置的
void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)
我们直接来看看结构体timer_oc_parameter_struct的定义:
13685658b9a948bfb0.png
针对 TIMR0 CH0 初始化范例代码格式
     /* CH0, CH1 and CH2 configuration in PWM mode */
     timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
     timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE;
     timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
     timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
     timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
     timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);
4)设置PWM输出以及脉冲宽度占空比
6396658b9afbbf72f.png
5)使能 TIMER0
在完成以上设置了之后,我们需要使能 TIMER0。使能 TIMER0 的方法前面已经讲解过:
timer_enable(TIMER0);
通过以上 5 个步骤,我们就可以控制 TIMER0的 CH0 输出 PWM 波了。这里特别提醒一下大家,高级定时器虽然和通用定时器类似,但是高级定时器要想输出 PWM,必须多额外加一条函数
void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);

输入捕获 TIMER2

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。
本章要实现通过输入捕获,来获取TIMER2_CH0(PA6)上面的下降沿,下面我们介绍库函数配置上述功能输入捕获的步骤:
1)开启 TIMER2 时钟,配置 PA6为复用功能,并开启上拉电阻。
99903658b9b53f3646.png
跟上一讲 PWM 输出类似,这里我们使用的是定时器2的通道 0,所以我们从对应的数据手册可以查看到对应的 IO 口为 PA6:
96230658b9b688599b.png
2) 初始化定时器参数,设置自动重装值, 分频系数,计数方式等
35919658b9b791ac9d.png
3)设置 TIMER2 的输入捕获参数,开启输入捕获
库函数是通过 timer_input_capture_config 函数来初始化输入比较参数的:
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
同样,我们来看看参数设置结构体 TIM_ICInitTypeDef 的定义:
49791658b9b9eb22c8.png
我们的配置代码是: 598658b9bc1c4f26.png
4) 使能捕获中断和NVIC
timer_interrupt_enable(TIMER2,TIMER_INT_CH0);
nvic_irq_enable(TIMER2_IRQn, 1, 1);
5) 编写中断服务函数
void TIMER2_IRQHandler(void){……}
6) 使能定时器
timer_enable(TIMER2);
通过以上 6 步设置,定时器 2 的通道 0 就可以开始输入捕获了

外部时钟输入 TIMER1

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。
本章要实现使用TIMER1 PA0 作为时钟输入引脚
配置流程:
(1)使能GPIO,TIMER 时钟和GPIO口复用配置  
79610658b9c2e447e8.png
96485658b9c3fa1bb2.png
(2)通过查看数据手册,可以看到TIMER1_CH0_ETI,根据前面所讲,是可以支持外部时钟输入的。
TIMER的结构体,初始化定时器参数,设置自动重装值, 分频系数,计数方式等
22669658b9c57064ea.png
54026658b9c5db5e06.png
(3)配置TIMER的时钟来源和时钟源处理的配置
timer_input_trigger_source_select(TIMER1,TIMER_SMCFG_TRGSEL_ETIFP);
timer_external_clock_mode1_config(TIMER1, TIMER_EXT_TRI_PSC_OFF, TIMER_ETP_RISING, 0);
(4)使能TIMER
timer_enable(TIMER1);

TIMER 使用注意事项

TIMER 高级定时器 做定时用的时候(使用到UPDAT中断),在产生中断之后,高级定时器的其他所有的状态标志位会被置位,但是不会置位中断标志位。


使用特权

评论回复
智芯云技术|  楼主 | 2024-1-3 17:42 | 显示全部楼层
                                       ADC 模块介绍

ADC 基础知识
12位ADC是一种采用逐次逼近方式的模拟数字转换器。
转换模式:
– 转换单个通道,或者扫描一序列的通道;
– 单次模式,每次触发转换一次选择的输入通道;
– 连续模式,连续转换所选择的输入通道;
– 间断模式;
– 同步模式(适用于具有两个或多个ADC的设备)。

GD32 ADC 外设原理

GD32 ADC 主要特性
◼ 高性能:
– 可配置12位、 10位、 8位、或者6位分辨率;
– 自校准;
– 可编程采样时间;
– 数据寄存器可配置数据对齐方式;
– 支持规则数据转换的DMA请求。
◼ 模拟输入通道:
– 16个外部模拟输入通道;
– 1个内部温度传感器输入通道(VSENSE);
– 1个内部参考电压输入通道(VREFINT)。
◼ 转换开始的发起:
– 软件;
– 硬件触发。
◼ 转换模式:
– 转换单个通道,或者扫描一组通道;
– 单次模式,每次触发转换一次选择的输入通道;
– 连续模式,连续转换所选择的输入通道;
– 间断模式;
– 同步模式(适用于具有两个或多个ADC的设备)。
◼ 模拟看门狗。
◼ 中断的产生:
– 规则组或注入组转换结束;
– 模拟看门狗事件。
◼ 过采样:
– 16位的数据寄存器;
– 可调整的过采样率,从2x到256x;
– 高达8位的可编程数据移位。
◼ ADC供电要求:
– 2.4V到3.6V,一般供电电压为3.3V。
◼ ADC输入范围: VREF- ≤VIN ≤VREF+。

ADC结构框图介绍
7640165952a6c47e65.png

硬件连接说明
7510265952a848a9cd.png
ADC的检测需要将输入阻抗和采样周期保持一定的关系,下表列出了以GD32E103为例
2268765952a9f22ae0.png

软件配置说明

查询法
查询法采用的是转换单个通道,或者扫描一序列的通道,通过不断切换通道的方式去读取对应通道的ADC数值。我们介绍使用库函数来设置 ADC0 的通道来进行 AD 转换的步骤,下面讲解其详细设置步骤:
开启 GPIO口时钟和 ADC0 时钟,设置GPIO口为模拟输入。
3227865952ad991a26.png
这里需要说明一下, ADC 的通道与引脚的对应关系在数据手册可以查到
6191965952ae65df86.png
(1)配置 ADC 输入时钟分频,模式为独立模式,转换长度以及触发方式等
6872865952afbaca09.png
1610365952b09a508b.png
(2)开启 AD 转换器在设置完了以上信息后,我们就开启 AD 转换器了
/* enable ADC interface */
adc_enable(ADC0);
(3)读取 ADC 值
在上面的步骤完成后, ADC 就算准备好了。所谓的查询法就是不断地进行通道切换,
3852465952b3ae822f.png
这里还需要说明一下ADC的参考电压,是以Vref作为参考电压。

常规通道转换 DMA 搬运

通过ADC转换,在ADC 转换完成后 触发DMA 进行数据搬运。
DMA 请求,可以通过设置 ADC_CTL1 寄存器的 DMA 位来使能,它用于规则组多个通道的转换结果。 ADC 在规则组一个通道转换结束后产生一个 DMA 请求, DMA 接受到请求后可以将转换的数据从 ADC_RDATA 寄存器传输到用户指定的目的地址。
在和查询法一节的差别,主要在于ADC 的配置方面和DMA的配置
(1)ADC的配置
6925365952b862a87f.png
6775765952b8d9d6cd.png
(2)DMA的配置
139465952ba13bab5.png
(3)触发ADC 转换
adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);

注入通道-中断

在和查询法一节的差别,主要在于ADC 的配置方面和注入通道会产生中断
(1)ADC 的配置
7889065952bd1102ba.png
adc_interrupt_enable(ADC0, ADC_INT_EOIC);//使能注入通道的中断
(2)ADC 注入通道转换转换完成服务函数
5282865952beac8db7.png

ADC 使用注意事项
1. ADC通道的采集引脚未配置为模拟输入,GD32要求通道IO口必须配置为模拟输入;
2. ADC时钟过高,ADC采样时钟高于ADC最高采样时钟获取到的数据不具有参考意义,需要手动分频到合适的ADC 要求的频率;
3. ADC采样值偏小或不稳定,应该适当的降低ADC时钟,加大采样周期的值;
4. ADC的查询法在获取ADC数值的时候,不允许重入,即不允许在同一时间调用ADC的数据读取函数;
5. ADC在使能之后需要进行短暂的延时,时间周期约为2毫秒左右,以保证ADC能正常启动。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

125

帖子

7

粉丝