合泰HT32F52352(GPTM)多路PWM控制
关于合泰HT32F52352多路pwm的控制,困了几天,今天终于得到解决,不得不说合泰的相关资料太少了,并且很多博主分享的可能和我们的芯片型号不同差别还是有点大的,ht32f52352的使用倒和stm32形式上很像,所以在学习过程中,对于一些外设的控制我们同样可以借鉴一下stm32的使用规则,然后进行相关的修改。下面会以PWM产生和捕捉定时器(GPTM) 控制四路舵机进行分享,希望可以帮助到正在学习HT32的小伙伴们。
其他博主的分享
实验效果
ht32多路舵机控制
话规正题
前面已分享了基本定时器的使用,以及定时器的分类,这里就不在重复需要的小伙伴,同样对于舵机的控制在stm32多路舵机控制也有讲,使用方法是一模一样的只是调用函数和传参不同,进行移植还是很通用的,请前往另两篇博文
stm32多路舵机控制
ht32f52352基本定时器的使用
下面先给出GPTM定时器的配置然后进行相应的分析
这是我使用的是GPIOA 4/5/6/7引脚GPTM0进行配置的,很多引脚都可以进行配置 大家根据数据手册进行配置就好了
time.h
#ifndef _TIME_H_
#define _TIME_H_
#include "ht32f5xxxx_bftm.h"
#define HTGPIO_PIN (GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7)
void GPTM_PWM_init();
void Servo_Run(uint16_t angle);
void Servo_Run2(uint16_t angle);
void Servo_Run3(uint16_t angle);
void Servo_Run4(uint16_t angle);
#endif
time.c
从下面初始化函数中 不难看出Ht32GPTM pwm配置的时候和stm32真的很像,只是配置名称不同,所以如果有一定的32基础下面代码还是很容易看懂的
#include "time.h"
#include "delay.h"
//输出四路PWM波控制后轮两个电机
//arr:自动重装值
//psc:时钟预分频数
//GT0 PA4 PA5 PA6 PA7
//产生一个20ms 定时周期
void GPTM_PWM_init()
{
TM_TimeBaseInitTypeDef TimeBaseIniture; //结构体
TM_OutputInitTypeDef OutIniture;
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.PA = 1; //GPIOA时钟打开
CKCUClock.Bit.AFIO = 1; //复用时钟
CKCUClock.Bit.GPTM0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE); //时钟使能
AFIO_GPxConfig(GPIO_PA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, AFIO_MODE_4); //开启复用功能
GPIO_DirectionConfig(HT_GPIOA,HTGPIO_PIN,GPIO_DIR_OUT);
TM_ClearFlag(HT_GPTM0, TM_FLAG_UEV); //清除更新中断标志
TM_OutputStructInit(&OutIniture); //填写每个变量的默认值
//定时器时基以及计数方式初始化
TimeBaseIniture.CounterMode = TM_CNT_MODE_UP; //边沿对齐向上模式
TimeBaseIniture.CounterReload = 200-1; //计数重装载计数器
TimeBaseIniture.Prescaler = 4800 -1; //预分频系数
TimeBaseIniture.PSCReloadTime=TM_PSC_RLD_IMMEDIATE; //立即重装载
TM_TimeBaseInit(HT_GPTM0,&TimeBaseIniture);
// 0通道输出 PA4
OutIniture.Channel= TM_CH_0;
OutIniture.Control= TM_CHCTL_ENABLE; //GPTM通道使能
OutIniture.OutputMode=TM_OM_PWM1 ; //GPTM 通道 PWM1输出模式 PWM2模式翻转
OutIniture.Polarity= TM_CHP_INVERTED; //GPTM 通道极性是低电平或下降沿
// OutIniture.Compare=200; // 这个是配置占空比的
TM_OutputModeConfig(HT_GPTM0,TM_CH_0,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// 1通道输出 PA5
OutIniture.Channel=TM_CH_1;
OutIniture.Control=TM_CHCTL_ENABLE; //GPTM通道使能
OutIniture.OutputMode=TM_OM_PWM1; //GPTM 通道 PWM1输出模式 PWM2模式翻转
OutIniture.Polarity=TM_CHP_INVERTED; //GPTM 通道极性是低电平或下降沿
//OutIniture.Compare=200; // 这个是配置占空比的
TM_OutputModeConfig(HT_GPTM0,TM_CH_1,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// 2通道输出 PA6
OutIniture.Channel=TM_CH_2;
OutIniture.Control=TM_CHCTL_ENABLE; //GPTM通道使能
OutIniture.OutputMode=TM_OM_PWM1; //GPTM 通道 PWM1输出模式 PWM2模式翻转
OutIniture.Polarity=TM_CHP_INVERTED; //GPTM 通道极性是低电平或下降沿
//OutIniture.Compare=200; // 这个是配置占空比的
TM_OutputModeConfig(HT_GPTM0,TM_CH_2,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// 3通道输出 PA7
OutIniture.Channel=TM_CH_3;
OutIniture.Control=TM_CHCTL_ENABLE; //GPTM通道使能
OutIniture.OutputMode=TM_OM_PWM1; //GPTM 通道 PWM1输出模式 PWM2模式翻转
OutIniture.Polarity=TM_CHP_INVERTED; //GPTM 通道极性是低电平或下降沿
// OutIniture.Compare=200; // 这个是配置占空比的
TM_OutputModeConfig(HT_GPTM0,TM_CH_3,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
TM_IntConfig(HT_GPTM0, TM_INT_CH0CC|TM_INT_CH1CC|TM_INT_CH2CC|TM_INT_CH3CC, ENABLE); //中断
TM_Cmd(HT_GPTM0,ENABLE); //使能计数
}
/**
* 功能:舵机驱动(可从0~180,每45度旋转一次)
* 参数:angle ;舵机旋转度数(相对角度)
* 返回值:None
*/
void Servo_Run(uint16_t angle)
{
switch(angle)
{
case 180 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,175); break;//对应180度
case 135 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,180); break;//对应135度
case 90 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,185); break;//对应90度
case 45 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190); break;//对应45度
case 0 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,195); break;//对应0度
}
}
void Servo_Run2(uint16_t angle)
{
switch(angle)
{
case 180 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_1,175); break;//对应180度
case 135 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_1,180); break;//对应135度
case 90 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_1,185); break;//对应90度
case 45 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_1,190); break;//对应45度
case 0 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_1,195); break;//对应0度
}
}
void Servo_Run3(uint16_t angle)
{
switch(angle)
{
case 180 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_2,175); break;//对应180度
case 135 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_2,180); break;//对应135度
case 90 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_2,185); break;//对应90度
case 45 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_2,190); break;//对应45度
case 0 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_2,195); break;//对应0度
}
}
void Servo_Run4(uint16_t angle)
{
switch(angle)
{
case 180 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_3,175); break;//对应180度
case 135 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_3,180); break;//对应135度
case 90 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_3,185); break;//对应90度
case 45 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_3,190); break;//对应45度
case 0 :TM_SetCaptureCompare(HT_GPTM0,TM_CH_3,195); break;//对应0度
}
}
main.c
#include "ht32.h"
#include "ht32_board.h"
#include "led.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
/******************TH32 定时器GPTM多路舵机控制*******************
Author:小殷
Date:2022-4-28
***************************************************************/
int main()
{
Led_Init();
USARTx_Init();
GPTM_PWM_init();
Servo_Run(45);
printf("---------pwm Test------\n");
while(1)
{
Servo_Run(0);
delay_ms(500);
Servo_Run(45);
delay_ms(500);
Servo_Run2(0);
delay_ms(500);
Servo_Run2(45);
delay_ms(500);
Servo_Run3(0);
delay_ms(500);
Servo_Run3(45);
delay_ms(500);
Servo_Run4(0);
delay_ms(500);
Servo_Run4(45);
delay_ms(500);
}
}
所需函数分析
1.首先配置我们所需的时钟、GPIO、端口复用、定时器时钟
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.PA = 1; //GPIOA时钟打开
CKCUClock.Bit.AFIO = 1; //复用时 CKCUClock.Bit.GPTM0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE); //时钟使能
AFIO_GPxConfig(GPIO_PA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, AFIO_MODE_4); //开启复用功能
GPIO_DirectionConfig(HT_GPIOA,HTGPIO_PIN,GPIO_DIR_OUT);
/************************定时器结构体配置*******************/
typedef struct
{
TM_CH_Enum Channel; /*!< Channel selection refer to \ref TM_CH_Enum */
TM_OM_Enum OutputMode; /*!< Channel output mode selection refer to \ref TM_OM_Enum */
TM_CHCTL_Enum Control; /*!< CHxO output state refer to \ref TM_CHCTL_Enum */
TM_CHCTL_Enum ControlN; /*!< CHxO output state refer to \ref TM_CHCTL_Enum */
TM_CHP_Enum Polarity; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
TM_CHP_Enum PolarityN; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
MCTM_OIS_Enum IdleState; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
MCTM_OIS_Enum IdleStateN; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
u16 Compare; /*!< Value for CHxCCR register */
u16 AsymmetricCompare; /*!< Value for CHxCCR register */
} TM_OutputInitTypeDef;
//配置完成后初始化函数
void TM_TimeBaseInit(HT_TM_TypeDef* TMx, TM_TimeBaseInitTypeDef* TimeBaseInit)
/对于定时器的配置我们只需配置下面这几个参数就好,具体模式大家根据自己来就行
//定时器时基以及计数方式初始化
TimeBaseIniture.CounterMode = TM_CNT_MODE_UP; //边沿对齐向上模式
TimeBaseIniture.CounterReload = 200-1; //计数重装载计数器
TimeBaseIniture.Prescaler = 4800 -1; //预分频系数
TimeBaseIniture.PSCReloadTime=TM_PSC_RLD_IMMEDIATE; //立即重装载
TM_TimeBaseInit(HT_GPTM0,&TimeBaseIniture);
/***********************输出比较PWM配置结构体*********************/
typedef struct
{
TM_CH_Enum Channel; /*!< Channel selection refer to \ref TM_CH_Enum */
TM_OM_Enum OutputMode; /*!< Channel output mode selection refer to \ref TM_OM_Enum */
TM_CHCTL_Enum Control; /*!< CHxO output state refer to \ref TM_CHCTL_Enum */
TM_CHCTL_Enum ControlN; /*!< CHxO output state refer to \ref TM_CHCTL_Enum */
TM_CHP_Enum Polarity; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
TM_CHP_Enum PolarityN; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
MCTM_OIS_Enum IdleState; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
MCTM_OIS_Enum IdleStateN; /*!< CHxO polarity refer to \ref TM_CHP_Enum */
u16 Compare; /*!< Value for CHxCCR register */
u16 AsymmetricCompare; /*!< Value for CHxCCR register */
} TM_OutputInitTypeDef;
void TM_OutputModeConfig(HT_TM_TypeDef* TMx, TM_CH_Enum Channel, TM_OM_Enum Mod);
void TM_OutputInit(HT_TM_TypeDef* TMx, TM_OutputInitTypeDef* OutInit);
//同样对于这个结构体的配置我们也只需配置以下参数就可以了 和相关输出初始化函数
OutIniture.Channel= TM_CH_0;
OutIniture.Control= TM_CHCTL_ENABLE; //GPTM通道使能
OutIniture.OutputMode=TM_OM_PWM1 ; //GPTM 通道 PWM1输出模式 PWM2模式翻转
OutIniture.Polarity= TM_CHP_INVERTED; //GPTM 通道极性是低电平或下降沿
TM_OutputModeConfig(HT_GPTM0,TM_CH_0,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
//上面两个结构体配置完成后 记得一定要使能定时器
void TM_IntConfig(HT_TM_TypeDef* TMx, u32 TM_INT, ControlStatus NewState);
void TM_Cmd(HT_TM_TypeDef* TMx, ControlStatus NewState);
大家配置的时候一定要仔细检查有没有漏掉的我自己在配置的时候
GPIO_DirectionConfig(HT_GPIOA,HTGPIO_PIN,GPIO_DIR_OUT);
就把GPIO输出的配置给漏掉了 搞了好久才发现这个错误
加油耶