GD32F303高级定时器输出互补PWM

[复制链接]
5688|8
 楼主| o88ne 发表于 2024-3-31 11:43 | 显示全部楼层 |阅读模式
GD32F303高级定时器timer0输出3组互补PWM
主要特性
◼ 总通道数:4;
◼ 计数器宽度:16位;
◼ 时钟源可选:内部时钟,内部触发,外部输入,外部触发;
◼ 多种计数模式:向上计数,向下计数和中央计数;
◼ 正交编码器接口:被用来追踪运动和分辨旋转方向和位置;
◼ 霍尔传感器接口:用来做三相电机控制;
◼ 可编程的预分频器:16位,运行时可以被改变;
◼ 每个通道可配置:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式;
◼ 可编程的死区时间;
◼ 自动重装载功能;
◼ 可编程的计数器重复功能;
◼ 中止输入功能;
◼ 中断输出和DMA请求:更新事件,触发事件,比较/捕获事件,换相事件和中止事件;
◼ 多个定时器的菊链使得一个定时器可以同时启动多个定时器;
◼ 定时器的同步允许被选择的定时器在同一个时钟周期开始计数;
◼ 定时器主-从管理。

结构图
703816608dbd56b6a2.png



 楼主| o88ne 发表于 2024-3-31 11:43 | 显示全部楼层
 楼主| o88ne 发表于 2024-3-31 11:43 | 显示全部楼层
高级定时器timer0是挂在APB2上的,最大频率120MHz,这里使用120MHz。
385956608dbfa154bd.png 时钟使能,令RCU_APB2EN的11位bit为1即可。
 楼主| o88ne 发表于 2024-3-31 11:44 | 显示全部楼层
主要寄存器
125806608dc1073acc.png
需要配置的寄存器为上面框出来的。
 楼主| o88ne 发表于 2024-3-31 11:44 | 显示全部楼层
代码讲解(寄存器版)
pwm.c
  1. /*
  2. * Dasen - 2023/4/28
  3. * pwm.c - 产生三组互补PWM波
  4. */

  5. #include "pwm.h"

  6. void Pwm_gpioInit(void)
  7. {
  8.         //PA8(复用) - CH0                        |                PB13(复用) - CH0-N       
  9.         //PA9(复用) - CH1                        |                PB14(复用) - CH1-N
  10.         //PA10(复用) - CH2                |                PB15(复用) - CH2-N
  11.         RCU_APB2EN |=(1<<2);//GPIOA时钟使能
  12.         RCU_APB2EN |=(1<<3);//GPIOB时钟使能
  13.         RCU_APB2EN |=(1<<0);//复用IO时钟使能
  14.        
  15.        
  16.        
  17.         //PA8
  18.         GPIO_CTL1(GPIOA) &=~(0X0F<<0);//清除CTL配置
  19.         GPIO_CTL1(GPIOA) |=(3<<0);//输出模式,最大速度50MHz
  20.         GPIO_CTL1(GPIOA) |=(2<<2);//AFIO推挽输出
  21.        
  22.         //PA9
  23.         GPIO_CTL1(GPIOA) &=~(0X0F<<4);//清除CTL配置
  24.         GPIO_CTL1(GPIOA) |=(3<<4);//输出模式,最大速度50MHz
  25.         GPIO_CTL1(GPIOA) |=(2<<6);//AFIO推挽输出
  26.        
  27.         //PA10
  28.         GPIO_CTL1(GPIOA) &=~(0X0F<<8);//清除CTL配置
  29.         GPIO_CTL1(GPIOA) |=(3<<8);//输出模式,最大速度50MHz
  30.         GPIO_CTL1(GPIOA) |=(2<<10);//AFIO推挽输出
  31.        
  32.         //PB13
  33.         GPIO_CTL1(GPIOB) &=~(0X0F<<20);//清除CTL配置
  34.         GPIO_CTL1(GPIOB) |=(3<<20);//输出模式,最大速度50MHz
  35.         GPIO_CTL1(GPIOB) |=(2<<22);//AFIO推挽输出
  36.        
  37.         //PB14
  38.         GPIO_CTL1(GPIOB) &=~(0X0F<<24);//清除CTL配置
  39.         GPIO_CTL1(GPIOB) |=(3<<24);//输出模式,最大速度50MHz
  40.         GPIO_CTL1(GPIOB) |=(2<<26);//AFIO推挽输出
  41.        
  42.         //PB15
  43.         GPIO_CTL1(GPIOB) &=~(0X0F<<28);//清除CTL配置
  44.         GPIO_CTL1(GPIOB) |=(3<<28);//输出模式,最大速度50MHz
  45.         GPIO_CTL1(GPIOB) |=(2<<30);//AFIO推挽输出
  46.        
  47.         AFIO_PCF0 &=~(3<<6);
  48.         AFIO_PCF0 |=(0<<6);//没有重映射
  49. }

  50. void Timer0_InitPwm(uint16_t prescale, uint16_t period)
  51. {
  52.         RCU_APB2EN |=(1<<11);//TIMER0时钟使能
  53.        
  54.         Pwm_gpioInit();//gpio config
  55.        
  56.         TIMER_CTL0(TIMER0) = 0;//清除控制寄存器0配置
  57.         TIMER_CTL0(TIMER0) |=(0<<8);//通过软件配置CKDIV,规定定时器时钟(CK_TIMER) 与死区时间和数字滤波器采样时钟(DTS)之间的分频系数。:
  58.                                                                                                                         //00:fDTS=fCK_TIMER;
  59.                                                                                                                         //01:fDTS= fCK_TIMER /2;
  60.                                                                                                                         //10:fDTS= fCK_TIMER /4;
  61.                                                                                                                         //11:保留
  62.        
  63.         TIMER_CTL0(TIMER0) |=(1<<7);//1:使能TIMERx_CAR寄存器的影子寄存器(自动重载影子使能)
  64.         TIMER_CTL0(TIMER0) |=(0<<5);//计数器对齐模式选择:00:无中央对齐计数模式(边沿对齐模式)。 DIR位指定了计数方向。其他值为中央对齐模式
  65.         TIMER_CTL0(TIMER0) |=(0<<4);//0:向上计数;1:向下计数
  66.         TIMER_CTL0(TIMER0) |=(1<<2);//选择更新事件源。1:下列事件会产生更新中断或DMA请求:计数器溢出/下溢
  67.         TIMER_CTL0(TIMER0) |=(0<<1);//该位用来使能或禁能更新事件的产生。0:更新事件使能.1:更新事件禁能.
  68.        
  69.        
  70.        
  71.         TIMER_CTL1(TIMER0)=0;//清除控制寄存器1配置
  72.         TIMER_CTL1(TIMER0) |=(1<<3);//DMA请求源选择:0:当通道捕获/比较事件发生时,发送通道x的DMA请求 .1:当更新事件发生,发送通道x的DMA请求
  73.         TIMER_CTL1(TIMER0) |=(0<<2);//换相控制影子寄存器更新控制:当换相控制影子寄存器(CHxEN, CHxNEN和CHxCOMCTL位)使能(CCSE=1),这些影子寄存器更新控制如下:(当通道没有互补输出时,此位无效。)
  74.                                                                                                                         //0:CMTG位被置1时更新影子寄存器
  75.                                                                                                                         //1:当CMTG位被置1或检测到TRIGI上升沿时,影子寄存器更新
  76.                                                                                                                        
  77.         TIMER_CTL1(TIMER0) |=(1<<0);//换相控制影子使能:0:影子寄存器CHxEN, CHxNEN和CHxCOMCTL位禁能.
  78.                                                                                                                         //1:影子寄存器CHxEN, CHxNEN和CHxCOMCTL位使能.
  79.                                                                                                                         //如果这些位已经被写入了,换相事件到来时这些位才被更新
  80.                                                                                                                         //当通道没有互补输出时,此位无效
  81.                                                                                                                        
  82.         TIMER_SMCFG(TIMER0) =0;//清除从模式配置寄存器配置

  83.         TIMER_DMAINTEN(TIMER0) =0;//清除DMA和中断使能寄存器
  84.         TIMER_DMAINTEN(TIMER0) |=(0<<0);//0:禁止更新中断;1:使能更新中断
  85.        
  86.         TIMER_INTF(TIMER0) =0;//中断标志位清零 【TIMER_INTF(TIMER0)&(1<<0) 为UPIF更新中断标志位:1:发生更新中断;0:无更新中断发生。】
  87.        
  88.         TIMER_SWEVG(TIMER0) =0;//软件事件产生寄存器清零
  89.        
  90.        
  91.        
  92.         /******************************PWM通道配置 START*********************************/
  93.         //先把CHCTL2的CHxEN清零,才配置CHCTL0
  94.         TIMER_CHCTL2(TIMER0) =0;//通道控制寄存器2清零
  95.        
  96.         TIMER_CHCTL0(TIMER0) =0;//通道控制寄存器0清零
  97.         TIMER_CHCTL1(TIMER0) =0;//通道控制寄存器1清零
  98.         //CH0
  99.         TIMER_CHCTL0(TIMER0) |=(0<<0);//通道0 I/O模式选择:00:通道0配置为输出
  100.         TIMER_CHCTL0(TIMER0) |=(1<<3);//1:使能通道0输出/比较影子寄存器
  101.         TIMER_CHCTL0(TIMER0) |=(6<<4);//110:PWM 模式0。在向上计数时,一旦计数器值小于TIMERx_CH0CV时,O0CPRE为高电平,否则为低电平。在向下计数时,一旦计数器的值大于TIMERx_CH0CV时,O0CPRE 为低电平,否则为高电平。
  102.        
  103.         //CH1
  104.         TIMER_CHCTL0(TIMER0) |=(0<<8);
  105.         TIMER_CHCTL0(TIMER0) |=(1<<11);
  106.         TIMER_CHCTL0(TIMER0) |=(6<<12);
  107.        
  108.         //CH2
  109.         TIMER_CHCTL1(TIMER0) |=(0<<0);
  110.         TIMER_CHCTL1(TIMER0) |=(1<<3);
  111.         TIMER_CHCTL1(TIMER0) |=(6<<4);
  112.        
  113.         //CH0 EN
  114.         TIMER_CHCTL2(TIMER0) |=(1<<0);//1:使能通道x
  115.         TIMER_CHCTL2(TIMER0) |=(0<<1);//通道x极性:0:通道x高电平为有效电平;1:通道x低电平为有效电平
  116.         //CH0-N EN
  117.         TIMER_CHCTL2(TIMER0) |=(1<<2);//1:使能通道x互补输出
  118.         TIMER_CHCTL2(TIMER0) |=(0<<3);//通道x互补输出极性:0:通道x互补输出高电平为有效电平;1:通道x互补输出低电平为有效电平
  119.        
  120.         //CH1 EN
  121.         TIMER_CHCTL2(TIMER0) |=(1<<4);//1:使能通道x
  122.         TIMER_CHCTL2(TIMER0) |=(0<<5);//通道x极性:0:通道x高电平为有效电平;1:通道x低电平为有效电平
  123.         //CH1-N EN
  124.         TIMER_CHCTL2(TIMER0) |=(1<<6);//1:使能通道x互补输出
  125.         TIMER_CHCTL2(TIMER0) |=(0<<7);//通道x互补输出极性:0:通道x互补输出高电平为有效电平;1:通道x互补输出低电平为有效电平
  126.        
  127.         //CH2 EN
  128.         TIMER_CHCTL2(TIMER0) |=(1<<8);//1:使能通道x
  129.         TIMER_CHCTL2(TIMER0) |=(0<<9);//通道x极性:0:通道x高电平为有效电平;1:通道x低电平为有效电平
  130.         //CH2-N EN
  131.         TIMER_CHCTL2(TIMER0) |=(1<<10);//1:使能通道x互补输出
  132.         TIMER_CHCTL2(TIMER0) |=(0<<11);//通道x互补输出极性:0:通道x互补输出高电平为有效电平;1:通道x互补输出低电平为有效电平
  133.        
  134.         TIMER_SWEVG(TIMER0) |=(1<<5);//通道换相更新事件发生:1:产生通道控制更新事件。此位由软件置1,由硬件自动清0. 当此位被置1,通道捕获/比较控制寄存器 (CHxEN, CHxNEN 和CHxCOMCTL) 的互补输出被更新。
  135.         /******************************PWM通道配置 END*********************************/
  136.        
  137.         //时基配置
  138.         TIMER_CNT(TIMER0)=0;//计数器寄存器清零
  139.         TIMER_PSC(TIMER0) =prescale;//TIM_CLK=120MHz/(prescale+1)。计数器时钟等于TIMER_CK时钟除以(PSC+1),每次当更新事件产生时,PSC 的值被装入到对应的影子寄存器。
  140.         TIMER_CAR(TIMER0) =period;//计数器自动重载值
  141.         TIMER_CREP(TIMER0) = 5;//重复计数器的值;这些位定义了更新事件的产生速率。重复计数器计数值减为0时产生更新事件。影子寄存器的更新速率也会受这些位影响(前提是影子寄存器被使能)。
  142.        
  143.         //比较寄存器配置
  144.         TIMER_CH0CV(TIMER0) = period>>1;//当通道0配置为输出模式时,这些位包含了即将和计数器比较的值。使能相应影子寄存器后,影子寄存器值随每次更新事件更新。
  145.         TIMER_CH1CV(TIMER0) = period>>1;
  146.         TIMER_CH2CV(TIMER0) = period>>1;
  147.        
  148.         TIMER_CCHP(TIMER0) &=~(3<<8);//00:禁能保护模式。无写保护.
  149.         TIMER_CCHP(TIMER0) =0;//互补通道保护寄存器清零
  150.         TIMER_CCHP(TIMER0) |=(1<<15);//所有的通道输出使能
  151.         TIMER_CCHP(TIMER0) |=(0<<14);//自动输出使能:0:POEN位只能使用软件方式置1;1:如果中止输入无效,下一次更新事件发生时,POEN位将会置1
  152.                                                                                                                                 //此位只有在TIMERx_CCHP寄存器的PROT [1:0] =00时才可修改。
  153.        
  154.         TIMER_CCHP(TIMER0) |=(1<<11);//0:当POEN位被置1,通道输出信号 (CHx_O/ CHx_ON)被禁止;1:当POEN位被置1,通道输出信号 (CHx_O / CHx_ON)被使能,和TIMER0_CHCTL2寄存器CHxEN/CHxNEN位有关
  155.                                                                                                                         //此位在TIMERx_CCHP寄存器的PROT [1:0]=10或11时不能被更改。       

  156.         TIMER_CCHP(TIMER0) |=(0<<10);//0:当POEN位被清0,通道输出信号 (CHx_O/ CHx_ON)被禁止;1:当POEN位被清0,通道输出信号 (CHx_O / CHx_ON)被使能,和TIMER0_CHCTL2寄存器CHxEN/CHxNEN位有关
  157.                                                                                                                         //此位在TIMERx_CCHP寄存器的PROT [1:0]=10或11时不能被更改。
  158.                                                                                                                        
  159.         //死区时间
  160.         TIMER_CCHP(TIMER0) |=(96<<0);//DELAY >= 8.33ns*96=799.68ns
  161.        
  162.         TIMER_CFG(TIMER0)=0;
  163.         TIMER_CFG(TIMER0)|=1;//1:如果POEN位与IOS位均为0,则输出无效
  164.        
  165.        
  166.         TIMER_SWEVG(TIMER0) |=(1<<0);//更新事件产生:1:产生更新事件。此位由软件置1,被硬件自动清0。当此位被置1,如果选择了中央对齐或向上计数模式,计数器被清0。否则(向下计数模式)计数器将载入自动重载值,预分频计数器将同时被清除。
  167.         TIMER_CTL0(TIMER0) |=(1<<0);//计数器使能:0:计数器禁能;1:计数器使能
  168. }

 楼主| o88ne 发表于 2024-3-31 11:44 | 显示全部楼层
main.c
/*
CK_SYS is 120000000
CK_AHB is 120000000
CK_APB1 is 60000000
CK_APB2 is 120000000
CK_SYS is 120000000
CK_AHB is 120000000
CK_APB1 is 60000000
CK_APB2 is 120000000
*/

#include "gd32f30x.h"
#include <stdio.h>
#include "main.h"
#include "pwm.h"


/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/

int main(void)
{
        Timer0_InitPwm(0,4000-1);//120MHz/4000=30KHz       
    while (1);
}
 楼主| o88ne 发表于 2024-3-31 11:44 | 显示全部楼层
实验现象
接示波器观察,可以看到三组互补pwm波形,占空比为50%,频率30KHz。
shenxiaolin 发表于 2024-4-30 16:12 | 显示全部楼层
定时器实现LED灯闪烁
配置流程
1、 开启时钟(定时器时钟)
2、 配置定时器参数
3、使能中断事件和定时器
4、编写中断服务函数
为你转身 发表于 2024-6-30 15:28 | 显示全部楼层
Timer0具有4个通道和16位的计数器,可支持多路PWM输出或其他计时功能。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

426

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部