电子烂人 · 2023年12月12日 · 山东

【GD32F303苹果派开发板试用】基于GD32驱动BLDC电机(1)定时器和PWM

最近收到了极术社区的GD32F303苹果派开发板,开箱如图
微信图片_20231212181050.jpg

微信图片_20231212181054.jpg“苹果派”这块板子的官方例程很多,仅仅是出版书籍就有三本,涵括了初级、进阶和微机原理等不同领域,据官方说后续还会出版freeRTOS相关的书籍。综合看来很适合小白学习单片机。
上电会有一个精美的GUI例程,涵括了该板子的所有功能:
微信图片_20231212180949.jpg
心血来潮买了几个BLDC电机,准备这次就使用苹果派这块板子试一下BLDC电机的控制。
苹果派这块板子的书籍和例程很多,要驱动电机首先要配置定时器,产生可控的PWM脉冲。
趁快递还没到,先学习一下PWM的生成方式:
按照例程和书籍配置寄存器TIMER2:

static  void ConfigTimer2(unsigned short arr, unsigned short psc)
{
  timer_parameter_struct timer_initpara;               //timer_initpara用于存放定时器的参数

  //使能RCU相关时钟 
  rcu_periph_clock_enable(RCU_TIMER2);                 //使能TIMER2的时钟

  timer_deinit(TIMER2);                                //设置TIMER2参数恢复默认值
  timer_struct_para_init(&timer_initpara);             //初始化timer_initpara

  //配置TIMER2
  timer_initpara.prescaler         = psc;              //设置预分频器值
  timer_initpara.counterdirection  = TIMER_COUNTER_UP; //设置向上计数模式
  timer_initpara.period            = arr;              //设置自动重装载值
  timer_initpara.clockdivision     = TIMER_CKDIV_DIV1; //设置时钟分割
  timer_init(TIMER2, &timer_initpara);                 //根据参数初始化定时器

  timer_interrupt_enable(TIMER2, TIMER_INT_UP);        //使能定时器的更新中断
  nvic_irq_enable(TIMER2_IRQn, 1, 0);                  //配置NVIC设置优先级
  timer_enable(TIMER2);                                //使能定时器
}

配置PWM输出模式:

static void ConfigTIMER1ForPWMPB10(unsigned short arr, unsigned short psc)
{
  //定义初始化结构体变量
  timer_oc_parameter_struct timer_ocinitpara;
  timer_parameter_struct timer_initpara;
  
  rcu_periph_clock_enable(RCU_GPIOB);    //使能GPIOB时钟
  rcu_periph_clock_enable(RCU_TIMER1);   //使能TIMER1时钟
  rcu_periph_clock_enable(RCU_AF);       //使能TIMER1时钟
  
  gpio_pin_remap_config(GPIO_TIMER1_PARTIAL_REMAP1, ENABLE);  //TIMER1部分重映射TIMER1_CH2->PB10
  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);  //设置GPIO输出模式及速度

  timer_deinit(TIMER1);                                  //将TIMER1配置为默认值
  timer_struct_para_init(&timer_initpara);               //timer_initpara配置为默认值
    
  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(TIMER1, &timer_initpara);                   //初始化定时器
    
  //将结构体参数初始化为默认值
  timer_channel_output_struct_para_init(&timer_ocinitpara);  
    
  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(TIMER1, TIMER_CH_2, &timer_ocinitpara);  //初始化结构体
     
  timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, 0);                   //设置占空比
  timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_PWM0);         //设置通道比较模式
  timer_channel_output_shadow_config(TIMER1, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);  //失能比较影子寄存器
  timer_auto_reload_shadow_enable(TIMER1);                                          //自动重载影子使能 

  timer_enable(TIMER1);  //使能定时器
}

void  InitPWM(void)
{
  ConfigTIMER1ForPWMPB10(599, 999);  //配置TIMER1,120000000/(999+1)/(599+1)=200Hz
}

void SetPWM(signed short val)
{
  s_iDutyCycle = val;                   //获取占空比的值
  
  timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, s_iDutyCycle);  //设置占空比
}

设置主函数:

#include "Main.h"
#include "gd32f30x_conf.h"
#include "SysTick.h"
#include "RCU.h"
#include "NVIC.h"
#include "Timer.h"
#include "PWM.h"

int main(void)
{
  SystemInit();      
  InitRCU();          
  InitNVIC();           
  InitTimer();         
  InitSysTick();       
  InitPWM();          
  
  SetPWM(100);
  
  while(1)
  {  
     
  }
}

在KEIL中编写好代码后,连接板子上的GD-LINK接口
由于使用GDlink烧录,故在"Target"标签页选择"DEBUG"为“CMSIS-DAP Debugger”
经实测GDLINK的烧录速度较慢,这里可以把时钟频率调整为10MHZ以增快烧录速度
image.png
1702377055707.png

烧录完成后用示波器的探头连接PB10引脚,如图,可以看到清晰的PWM波型
微信图片_20231212183455.jpg
有了PWM之后,控制电机就显得极其简单了

推荐阅读
关注数
1
内容数
1
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息