本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发
后续项目主要在下面该专栏中发布:
感兴趣的点个关注收藏一下吧!
电机驱动开发可以跳转:
手把手教你嵌入式国产化-实战项目-无刷电机驱动(1)-CSDN博客
BMS电源系统开发可以跳转:暂未放链接
向上代码兼容GD32F303RCT6中使用
本项目配套开发板:
基于GD32F103RCT6国产GD32平台,以下教程编写基于该开发板
图片:
原理图以及例程请联系客服获取!
注意:
本教程致力于解决所有在调试中出现的所有问题,如有未包含在的问题,请联系QQ:2049363803,有奖更新文档!
群号:621154399
有问题欢迎大家加入我们一起交流,这个群是开源性技术交流群。
定时器介绍
本讲开始对GD32F10x系列的定时器进行介绍,首先让我们打开手册的第261页,GD32一共有五种不同类型:
通过以下表格,将会对GD32f10x的定时器功能有一定了解;
这里需要强调一下,和串口一样,GD32的定时器定义是从0为编号开始的!
GD32F10x系列微控制器具有多种类型的定时器,包括基本定时器(TIM)、通用定时器(GPTIM)、高级定时器(HTIM)和中断定时器(WDT)。这些定时器可以用于各种定时、计数、测量和PWM控制应用。
基本定时器(TIM)是一个简单而灵活的定时器,可用于产生定时脉冲、测量时间间隔、计数输入脉冲等。通用定时器(GPTIM)和高级定时器(HTIM)提供了更多功能和更高的精度,可用于高级PWM控制、输入捕获和输出比较等应用。
中断定时器(WDT)是一个用于监控系统运行状态的特殊定时器,可用于检测系统出现死锁或运行错误时自动重启系统。
GD32F10x系列微控制器的定时器具有灵活的配置选项和丰富的功能,可满足各种应用需求。用户可以通过寄存器配置完成定时器的初始化和操作,也可以使用CubeMX等工具进行图形化配置,简化开发流程。.useStatefulPlugin就是基于GD32F10x系列微控制器的定时器实现的功能。
相对于STM32系列微控制器,GD32F10x定时器具有以下特点:
1. 更多的定时器类型:GD32F10x系列微控制器具有基本定时器(TIM)、通用定时器(GPTIM)、高级定时器(HTIM)和中断定时器(WDT)等多种类型的定时器,提供更多选择以满足不同应用需求。
2. 兼容性:GD32F10x系列微控制器与STM32系列微控制器具有一定的软件和硬件兼容性,因此在使用定时器时,开发人员可以较为方便地迁移代码和工程。
3. 更多的定时器数量:GD32F10x系列微控制器在同一芯片上提供更多的定时器数量,支持更复杂的定时、计数和PWM控制应用。
4. 低成本:GD32F10x系列微控制器相对于STM32系列微控制器具有更低的成本,适合一些低成本的应用场景。
5. 更加丰富的文档和示例支持:GD32F10x系列微控制器提供了丰富的文档和示例代码,便于开发人员进行学习和开发。
总的来说,GD32F10x定时器在功能、数量和成本等方面可能具有一定的优势,同时也提供了丰富的支持文档,便于开发人员进行开发和调试。
高级定时器
高级定时器(TIMER0/7)是四通道定时器,支持输入捕获和输出比较。可以产生PWM信号控制电机和电源管理。高级定时器含有一个16位无符号计数器。
高级定时器是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。
高级定时器包含了一个死区时间插入模块,非常适合电机控制。
定时器和定时器之间是相互独立,但是他们可以被同步在一起形成一个更大的定时器,这些定时器的计数器一致地增加。
主要特征
总通道数:4;
计数器宽度:16位;
时钟源可选:内部时钟,内部触发,外部输入,外部触发;
多种计数模式:向上计数,向下计数和中央对齐计数;
正交编码器接口:被用来追踪运动和分辨旋转方向和位置;
霍尔传感器接口:用来做三相电机控制;
可编程的预分频器:16位,运行时可以被改变;
每个通道可配置:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式;
可编程的死区时间;
自动重装载功能;
可编程的计数器重复功能;
中止输入功能使定时器按照用户的配置输出;
中断输出和DMA请求:更新事件,触发事件,比较/捕获事件和中止事件;
多个定时器的菊型链接使得一个定时器可以同时启动多个定时器;
定时器的同步允许被选择的定时器在同一个时钟周期开始计数;
定时器主-从管理。
时钟源配置:
GD32F10X的高级定时器(HTIM)具有丰富的时钟源配置选项,可以根据不同的应用需求进行灵活配置。HTIM的时钟源通常来自内部时钟源或外部时钟源,具体配置如下:
- 内部时钟源: HTIM可以选择使用内部时钟源作为时钟输入。GD32F10X内部时钟源通常包括主时钟(HCLK)、系统时钟(SYSCLK)等。
- 外部时钟源: HTIM还可以选择使用外部时钟源作为时钟输入,外部时钟源可以是外部晶体振荡器或者外部时钟输入引脚。
手册上则已经明确写出需要操作的寄存器:
高级定时器可以由内部时钟源CK_TIMER或者由SMC(TIMERx_SMCFG寄存器位[2:0])控制 的复用时钟源驱动。
SMC[2:0]==3’b000,定时器选择内部时钟源(连接到RCU模块的CK_TIMER) 如果SMC[2:0]==3’b000,默认用来驱动计数器预分频器的是内部时钟源CK_TIMER。当CEN 置位,CK_TIMER经过预分频器(预分频值由TIMERx_PSC寄存器确定)产生PSC_CLK。 这种模式下,驱动预分频器计数的TIMER_CK等于来自于RCU模块的CK_TIMER。 如果将TIMERx_SMCFG寄存器的SMC[2:0]设置为0x1、0x2、0x3和0x7,预分频器被其他时钟 源(由TIMERx_SMCFG寄存器的TRGS [2:0]区域选择)驱动,在下文说明。当SMC位被设置为 0x4、0x5和0x6,计数器预分频器时钟源由内部时钟CK_TIMER驱动。
SMC[2:0]==3’b111(外部时钟模式0),定时器选择外部输入引脚作为时钟源 计数器预分频器可以在TIMERx_CI0/ TIMERx_CI1引脚的每个上升沿或下降沿计数。这种模式 可以通过设置SMC [2:0]为0x7的同时设置TRGS [2:0]为0x4、0x5或0x6来选择。 计数器预分频器也可以在内部触发信号ITI0/1/2/3的上升沿计数。这种模式可以通过设置SMC [2:0]为0x7的同时设置TRGS [2:0]为0x0、0x1、0x2或者0x3。
SMC1==1’b1(外部时钟模式1),定时器选择外部输入引脚ETI作为时钟源 计数器预分频器可以在外部引脚ETI的每个上升沿或下降沿计数。这种模式可以通过设置 TIMERx_SMCFG寄存器中的SMC1位为1来选择。另一种选择ETI信号作为时钟源方式是,设 置SMC [2:0]为0x7的同时设置TRGS [2:0]为0x7。注意ETI信号是通过数字滤波器采样ETI引脚 得到的。如果选择ETI信号为时钟源,触发控制器包括边沿监测电路将在每个ETI信号的上升沿 产生一个时钟脉冲来为计数器预分频器提供时钟。
时钟预分频器:
GD32F10X的高级定时器(HTIM)具有时钟预分频器,用于将输入的时钟源进行分频,以得到所需的计数时钟。时钟预分频器可以根据应用需求灵活地进行配置,以实现不同的计数频率和精度。
GD32F10X的高级定时器的时钟预分频器支持多种预分频模式,包括分频系数为1、2、4、8、16、32、64、128、256、512、1024、2048、4096等,用户可以根据具体的定时要求选择合适的分频系数。
时钟预分频器具有以下特点:
- 可以根据外部时钟源的频率和用户要求的定时器时钟频率进行合适的分频设置,灵活性高。
- 支持多种预分频系数,可实现精确的定时控制。
- 配合定时器的计数器模块,可以实现多种定时功能,如定时器中断、定时器触发等。
计数器向上计数模式
在计数器向上计数模式下,定时器的计数器从0开始,以设定的时钟频率向上递增,直到计数值达到设定的最大计数值(通常是定时器的最大计数值,比如16位定时器的最大计数值为65535,32位定时器的最大计数值为4294967295),然后重新从0开始。通过设定时钟频率和最大计数值,可以实现精确的定时控制。
在GD32F10X系列微控制器中,可以通过使用高级定时器的寄存器进行配置和控制计数器向上计数模式。用户可以设置时钟源,设置预分频系数以及设定最大计数值等参数,从而实现精确的定时控制。
计数器向上计数模式广泛应用于各种实时控制和定时任务中,如定时中断、PWM波形生成等。通过合理配置高级定时器的计数器向上计数模式,可以满足不同应用场景下的定时控制需求。
计数器从0开始向上连续计数到计数器自动加载值(定义在TIMERx_CAR寄存器中),一旦计数器计数到自动加载值,会重新从0开始向上计数,并且产生上溢事件。另外,在(TIMERx_CREP+1)次上溢后将会产生更新事件。在向上计数模式中,TIMERx_CTL0寄存器中的计数方向控制位DIR应该被设置成0。当通过TIMERx_SWEVG寄存器的UPG位置1来设置更新事件时,计数值会被清0,并产生更新事件。如果TIMERx_CTL0寄存器的UPDIS置1,则禁止更新事件。当发生更新事件时,所有影子寄存器(重复计数器,计数器自动重载寄存器,预分频寄存器)都将被更新。
计数器向下计数模式
该模式与计数器向上计数模式相对应
在计数器向下计数模式下,定时器的计数器从用户设定的最大计数值开始递减,直到计数值为0为止,然后重新从用户设定的最大计数值开始递减。用户可以通过设定最大计数值,时钟频率和预分频系数等参数,实现精确的计时控制和计数功能。
在GD32F10X系列微控制器中,用户可以通过特定的寄存器来配置高级定时器的计数器向下计数模式。用户可以设置时钟源、预分频系数、最大计数值等参数,从而实现灵活、精确的计数器向下计数功能。
计数器向下计数模式通常用于一些特殊的定时和计数应用,例如倒计时功能、定时清除特定事件等。通过合理配置高级定时器的计数器向下计数模式,用户可以实现灵活应用于不同场景下的定时和计数任务。
计数器从自动加载值(定义在TIMERx_CAR寄存器中)向下连续计数到0。一旦计数器计数到0,计数器会重新从自动加载值开始计数并且产生下溢事件。另外,在(TIMERx_CREP+1)次下溢后将会产生更新事件。在向下计数模式中,TIMERx_CTL0寄存器中的计数方向控制位DIR应该被设置成1。当通过TIMERx_SWEVG寄存器的UPG位置1来设置更新事件时,计数值会被初始化为自动加载值,并产生更新事件。如果TIMERx_CTL0寄存器的UPDIS置1,则禁止更新事件。当发生更新事件时,所有影子寄存器(重复计数器,计数器自动重载寄存器,预分频寄存器)都将被更新。
计数器中央对齐计数模式
在计数器中央对齐计数模式下,定时器的计数器在向上计数和向下计数之间会经历一个额外的计数状态,即在计数器计数值为最大值或最小值时,计数器计数方向会发生改变。这种特殊的计数方式使得在 PWM 波形生成时具有更高的精准度。用户可以选择使能或禁用计数器中央对齐模式,也可以设置计数器的对齐方式(例如对齐到上升沿、下降沿等)以满足具体的应用需求。
计数器交替的从0开始向上计数到自动加载值,然后再向下计数到0。向上计数模式中,定时器模块在计数器计数到自动加载值-1产生一个上溢事件;向下计数模式中,定时器模块在计数器计数到1时产生一个下溢事件。在中央对齐计数模式中,TIMERx_CTL0寄存器中的计数方向控制位DIR只读,指示了当前的计数方向。将TIMERx_SWEVG寄存器的UPG位置1可以初始化计数值为0,并产生一个更新事件,而无需考虑计数器在中央模式下是向上计数还是向下计数。上溢或者下溢时,TIMERx_INTF 寄存器中的 UPIF 位都会被置 1,然而 CHxIF 位置 1 与TIMERx_CTL0寄存器中CAM的值有关。具体细节参考图15-8. 中央计数模式计数器时序图。
如果 TIMERx_CTL0 寄存器的 UPDIS 置 1,则禁止更新事件。当发生更新事件时,所有影子寄存器(重复计数器,计数器自动重载寄存器,预分频寄存器)都将被更新
更新事件(来自上溢/下溢)频率配置
更新事件的生成频率(来自上溢和下溢事件)可以通过TIMERx_CREP寄存器进行配置。重复计数器是用来在N+1个计数周期之后产生更新事件,更新定时器的寄存器,N为TIMERx_CREP寄存器的CREP。重复计数器在每次计数器上溢和下溢时递减(向上计数模式中不存在下溢事件;向下计数模式中不存在上溢事件)。将TIMERx_SWEVG寄存器的UPG位置1可以重载TIMERx_CREP寄存器中CREP的值并产生一个更新事件。新写入的CREP值将在下一次更新事件到来时生效。当CREP的值为奇数,并且计数器在中央对齐模式下计数时,更新事件发生在上溢或下溢取决于写入的CREP值何时生效。如果在写入奇数到CREP寄存器后由软件生成更新事件,则在下溢时产生更新事件。如果在写入奇数到CREP寄存器后下一个更新事件发生在上溢,此后将在上溢时产生更新事件。
在GD32F10X系列微控制器的高级定时器中,可以配置定时器触发更新事件后产生中断,用户可以编写对应的中断服务函数来处理这些中断事件。
void TIMERx_IRQHandler(void)
{
if (TIMER_GetIntBitState(TIMERx, TIMER_INT_UP) == SET) // 处理定时器更新事件中断
{
TIMER_ClearIntBit(TIMERx, TIMER_INT_UP); // 清除中断标志位
}
}
TIMERx_IRQHandler 是定时器 TIMERx 的中断服务函数。当定时器产生更新事件中断时,中断服务函数会进入这个中断处理函数。 在中断服务函数中,首先通过 TIMER_GetIntBitState 函数判断是否是更新事件中断(TIMER_INT_UP)。如果是更新事件中断,则可以在中断服务函数中处理相应的操作,比如更新变量、执行特定功能或者调用其他函数来处理事件。 最后,通过 TIMER_ClearIntBit 函数清除更新事件中断标志位,确保下一次中断可以被正确触发。在编写中断服务函数时,需要确保函数名称和中断向量表中对应的中断标识一致,以确保正确的中断处理程序被调用。
针对特殊的中央计数模式的中断函数:
void TIMERx_IRQHandler(void)
{
if (TIMER_GetIntBitState(TIMERx, TIMER_INT_UP) == SET)
{
// 处理计数器向上计数中断
TIMER_ClearIntBit(TIMERx, TIMER_INT_UP);
}
else if (TIMER_GetIntBitState(TIMERx, TIMER_INT_DOWN) == SET)
{
// 处理计数器向下计数中断
TIMER_ClearIntBit(TIMERx, TIMER_INT_DOWN);
}
}
在中央对齐计数模式下,当计数器向上计数或向下计数时会分别产生向上计数中断和向下计数中断。中断服务函数首先根据中断标志位判断是向上计数中断(TIMER_INT_UP)还是向下计数中断(TIMER_INT_DOWN)。
输入捕获和输出比较通道
高级定时器拥有四个独立的通道用于捕获输入或比较输出是否匹配。每个通道都围绕一个通道捕获比较寄存器建立,包括一个输入级、通道控制器和输出级。
通道输入捕获功能
通道输入捕获功能允许通道测量一个波形时序、频率、周期、占空比等。输入级包括一个数字滤波器、一个通道极性选择、边沿检测和一个通道预分频器。如果在输入引脚上出现被选择的边沿,TIMERx_CHxCV寄存器会捕获计数器当前的值,同时CHxIF位被置1,如果CHxIE = 1则产生通道中断。
我们常见的示波器以及捕获上升/下降沿就是使用该模式
通道输出比较功能
我们本章实验将会围绕该模式进行!
三种输出比较模式
1.输出 PWM 功能
2.通道输出准备信号
3.通道输出互补 PWM
其他的功能例如:
正交译码器,霍尔传感器接口功能,主-从管理,单脉冲模式,定时器互连,定时器 DMA 模式,定时器调试模式。
我们在平常使用过程中使用频率较少,在这里就不做解释,具体想了解可以查看GD32官方用户手册。
库函数介绍
定时器的时间基准
初始化定时器参数
void timer_deinit(uint32_t timer_periph);
初始化定时器的init参数结构
void timer_struct_para_init(timer_parameter_struct* initpara);
初始化定时器计数器
void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);
启用/禁用定时器
void timer_enable(uint32_t timer_periph);
void timer_disable(uint32_t timer_periph);
启用/禁用自动重新加载阴影函数
void timer_auto_reload_shadow_enable(uint32_t timer_periph);
void timer_auto_reload_shadow_disable(uint32_t timer_periph);
启用/禁用更新事件
void timer_update_event_enable(uint32_t timer_periph);
void timer_update_event_disable(uint32_t timer_periph);
设置定时器计数器的对齐模式
void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned);
设置定时器计数器的向上方向
void timer_counter_up_direction(uint32_t timer_periph);
设置定时器计数器的向下方向
void timer_counter_down_direction(uint32_t timer_periph);
配置定时器预分频量
void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload);
配置定时器重复寄存器值
void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition);
配置定时器自动重新加载寄存器值
void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload);
配置定时器计数器寄存器值
void timer_counter_value_config(uint32_t timer_periph, uint32_t counter);
读取定时器计数器的值
uint32_t timer_counter_read(uint32_t timer_periph);
读取定时器分频量的值
uint16_t timer_prescaler_read(uint32_t timer_periph);
配置定时器单脉冲模式
void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode);
配置定时器更新源
void timer_update_source_config(uint32_t timer_periph, uint32_t update);
定时器DMA和事件
启用/禁用定时器DMA
void timer_dma_enable(uint32_t timer_periph, uint16_t dma);
void timer_dma_disable(uint32_t timer_periph, uint16_t dma);
通道DMA请求源选择
void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request);
配置定时器DMA传输
void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth);
软件生成的事件管理
void timer_event_software_generate(uint32_t timer_periph, uint16_t event);
定时器通道补充保护
初始化定时器中断参数
void timer_break_struct_para_init(timer_break_parameter_struct* breakpara);
配置定时器中断函数
void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara);
启用/禁用定时器中断功能
void timer_break_enable(uint32_t timer_periph);
void timer_break_disable(uint32_t timer_periph);
启用/禁用定时器自动输出功能
void timer_automatic_output_enable(uint32_t timer_periph);
void timer_automatic_output_disable(uint32_t timer_periph);
启用或禁用定时器主要输出功能
void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);
启用或禁用通道捕获/比较控制影子寄存器
void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue);
配置定时器通道控制影子寄存器更新控制
void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl);
定时器通道输出
初始化定时器通道输出参数
void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara);
配置定时器通道输出功能
void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara);
配置定时器通道输出比较模式
void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode);
配置定时器通道输出脉冲值
void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse);
配置定时器通道输出阴影函数
void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow);
配置定时器通道输出快速函数
void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast);
配置定时器通道输出清除功能
void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear);
配置定时器通道输出极性
void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity);
配置定时器通道互补输出极性
void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity);
配置定时器通道的启用状态
void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state);
配置定时器通道互补输出启用状态
void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate);
定时器中断和标志
启用/禁用定时器中断
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt);
获取定时器中断标志
FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt);
清除定时器中断标志
void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt);
获取定时器标志
FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag);
清除定时器标志
void timer_flag_clear(uint32_t timer_periph, uint32_t flag);
本小结主要使用到的函数有:
void timer_deinit(uint32_t timer_periph)
对应参数:
TIMER0、TIMER1、TIMER2、TIMER3、TIMER4、TIMER5、TIMER6、TIMER7
两个初始化结构体,完成对定时器的参数配置
typedef struct
{
uint16_t prescaler; 预分频值
uint16_t alignedmode; 对齐模式
uint16_t counterdirection; 输出反向
uint32_t period; 周期值
uint16_t clockdivision; 时钟分频值
uint8_t repetitioncounter; 计数器的重复值
}timer_parameter_struct;
typedef struct
{
uint16_t outputstate; 通道输出状态
uint16_t outputnstate; 通道互补输出状态
uint16_t ocpolarity; 通道输出极性
uint16_t ocnpolarity; 通道互补输出极性
uint16_t ocidlestate; 通道输出的空闲状态
uint16_t ocnidlestate; 通道互补输出的空闲状态
}timer_oc_parameter_struct;
配置定时器通道输出功能
void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)
参数2:channel
TIMER_CH_0
TIMER_CH_1
TIMER_CH_2
TIMER_CH_3
参数3:ocpara
前文所确定参数的结构体
配置定时器通道输出脉冲值
void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse)
参数2:channel
TIMER_CH_0
TIMER_CH_1
TIMER_CH_2
TIMER_CH_3
参数3:pulse
填入参数
配置定时器通道输出比较方式
void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode)
参数2:channel
TIMER_CH_0
TIMER_CH_1
TIMER_CH_2
TIMER_CH_3
参数3:ocmode
TIMER_OC_MODE_TIMING 定时模式
TIMER_OC_MODE_ACTIVE 激活模式
TIMER_OC_MODE_INACTIVE 非活动模式
TIMER_OC_MODE_TOGGLE 切换模式
TIMER_OC_MODE_LOW 强制低模式
TIMER_OC_MODE_HIGH 强制高模式
TIMER_OC_MODE_PWM0 PWM0模式
TIMER_OC_MODE_PWM1 PWM1模式
补充:
PWM模式1
向上计数:CNT<CCR时,REF置有效电平;CNT≥CCR时,REF置无效电平;向下计数:CNT>CCR时,REF置无效电平;CNT≤CCR时,REF置有效电平;
PWM模式1
向上计数:CNT<CCR时,REF置无效电平;CNT≥CCR时,REF置有效电平;向下计数:CNT>CCR时,REF置有效电平;CNT≤CCR时,REF置无效电平;
冻结
CNT=CCR时,REF保持为原状态
匹配时置有效电平
CNT=CCR时,REF置有效电亚
匹配时置无效电平
CNT=CCR时,REF置无效电平
匹配时电平翻转
CNT=CCR时,REF电平翻转
强制为无效电平
CNT与CCR无效,REF强制为无效电平
强制为有效电平
CNT与CCR无效,REF强制为有效电亚
使能更新中断
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt)
配置定时器通道使能状态
void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state)
参数2:channel
TIMER_CH_0
TIMER_CH_1
TIMER_CH_2
TIMER_CH_3
参数3:
TIMER_CCX_ENABLE
TIMER_CCX_DISABLE
PWM实验
编程要点:
1.初始化结构体
2.使能GPIO时钟
3.设置GPIO工作模式
4.使能复用时钟和定时器时钟
5.初始化定时器参数
6.使能通道输出
//定时器配置,TIM1,通道1,通道2,通道3
void timer_config(uint16_t arr,uint16_t psc)
{
//定义初始化结构体变量
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_GPIOA); //使能GPIOA时钟
rcu_periph_clock_enable(RCU_TIMER0); //使能TIMER0时钟
rcu_periph_clock_enable(RCU_AF); //使能AF时钟
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); //设置PA8复用推挽输出
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); //设置PA9复用推挽输出
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); //设置PA10复用推挽输出
timer_deinit(TIMER0); //复位TIMER0
timer_initpara.prescaler = psc; //设置预分频值
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; //设置对齐模式
timer_initpara.counterdirection = TIMER_COUNTER_UP; //设置向上计数模式
timer_initpara.period = arr; //设置自动重装载值
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; //设置时钟分频因子
timer_initpara.repetitioncounter = 0; //设置重复计数值
timer_init(TIMER0, &timer_initpara); //根据参数初始化定时器
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; //使能通道输出
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_LOW; //设置通道输出极性为低
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara); //定时器通道输出配置
timer_channel_output_config(TIMER0, TIMER_CH_1, &timer_ocinitpara); //定时器通道输出配置
timer_channel_output_config(TIMER0, TIMER_CH_2, &timer_ocinitpara); //定时器通道输出配置
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, arr/2); //设置占空比,这里默认设置比较值为自动重装载值的一半,即占空比为50%
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1); //设置通道比较模式为PWM模式1
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, arr/2); //设置占空比,这里默认设置比较值为自动重装载值的一半,即占空比为50%
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM1); //设置通道比较模式为PWM模式1
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, arr/2); //设置占空比,这里默认设置比较值为自动重装载值的一半,即占空比为50%
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM1); //设置通道比较模式为PWM模式1
timer_primary_output_config (TIMER0, ENABLE); //TIMER0所有的通道输出使能
timer_enable(TIMER0);
}
主函数中编写占空比递增函数:
for(;pulse1<800;pulse1++)
{
for(;pulse2<pulse1;pulse1++)
{
for(;pulse3<pulse2;pulse1++)
{
TIM_SetTIM0Compare1(pulse1);
TIM_SetTIM0Compare2(pulse2);
TIM_SetTIM0Compare3(pulse3);
if(pulse3==pulse2)
pulse1=0;
}
if(pulse2==pulse1)
pulse1=0;
}
if(pulse1==700)
pulse1=0;
}
测试结果:
群号:621154399
有问题欢迎大家加入我们一起交流,这个群是开源性技术交流群。