一、问题背景
1.1 硬件:
电池组,电子调速器(好盈电调 /ESC),接收机(HT32F52352),风扇。
1.2 软件 keil5
二、问题分析
通过1.1图中可知,我们只需要使用 HT32F52352 模拟 接收机 发送信号,就可以控制最后的风扇了。那么现在就只需要了解到接收机信号是什么就可以了。
2.1 接收机信号是什么?
我这里使用的是 R9DS接收机 。通过途中可知,我们使用的3通道是一个pwm信号。
2.2 电路图
画了一个简易的原理图,其实和1.1的图并没有区别,只是需要注意PA4。
2.3 电调解锁
如果直接输入PWM风扇并不会有反应,我们还需要解锁电调。
如图可知,我们尝试用 HT32F52352 模拟遥控器给一个油门最高点,再在反应后(哔-哔-)给一个油门最低点。
三、程序编写
我这里根据之前的 HT32F52352 PWM控制舵机 的基础进行的更改。
3.1 PWM配置
这里将 PA4 PA5 PA6 PA7 都配置上,可以随时更改
//PWM
//arr: 200-1
//psc: 4800-1
//GPIO PA4 PA5 PA6 PA7
//PA4
void time_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);
// PA4
OutIniture.Channel= TM_CH_0;
OutIniture.Control= TM_CHCTL_ENABLE; //GPIO使能通道
OutIniture.OutputMode=TM_OM_PWM1 ; //GPIO 通道 PWM1 输出模式 PWM2 翻转模式
OutIniture.Polarity= TM_CHP_INVERTED; //GPTO 通道极性是低电平或者下降沿
// OutIniture.Compare=200; // 配置占空比
TM_OutputModeConfig(HT_GPTM0,TM_CH_0,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA5
OutIniture.Channel=TM_CH_1;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
//OutIniture.Compare=200;
TM_OutputModeConfig(HT_GPTM0,TM_CH_1,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA6
OutIniture.Channel=TM_CH_2;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
//OutIniture.Compare=200;
TM_OutputModeConfig(HT_GPTM0,TM_CH_2,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA7
OutIniture.Channel=TM_CH_3;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
// 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); //使能计数
}
3.2 模拟遥控器(电调解锁)
这里按照电调要求,我们先配置出PWM信号,然后给一个PWM高点,等待一段时间后给一个PWM最低点,那么我们可控制的范围就是这个 最低点 到 最高点 之间的数。
void PWM_R9DS_init(void){
time_init();
//TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,180);
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,90);
delay_ms(3500);
//TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190);
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190);
delay_ms(3500);
}
3.3 油门模拟函数
结合3.2 ,我们在90-190间,但190是最低点,所以我们将其整理成我们熟悉的样子
i 取 0~100 越高风扇转速越快
void Fan_drive(int i){
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190-i);
}
3.4 主函数
int main(void)
{
PWM_R9DS_init();
//delay_ms(2000);
while (1)
{
//油门注意不要给大了,无刷电机威力还是挺大的
Fan_drive(1);
}
}
四、PWM_R9DS
4.1 PWM_R9DS.h
#ifndef __PWMR9DS_H_
#define __PWMR9DS_H_
#include "ht32f5xxxx_bftm.h"
#define HTGPIO_PIN (GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7)
void PWM_R9DS_init(void);
void time_init(void);
void Fan_drive(int i);
#endif
4.2 PWM_R9DS.c
#include "PWM_R9DS.h"
#include "delay.h" //此处的延时函数 在文章尾部相关资料中有
//PWM
//arr: 200-1
//psc: 4800-1
//GPIO PA4 PA5 PA6 PA7
//PA4
void time_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);
// PA4
OutIniture.Channel= TM_CH_0;
OutIniture.Control= TM_CHCTL_ENABLE; //GPIO使能通道
OutIniture.OutputMode=TM_OM_PWM1 ; //GPIO 通道 PWM1 输出模式 PWM2 翻转模式
OutIniture.Polarity= TM_CHP_INVERTED; //GPTO 通道极性是低电平或者下降沿
// OutIniture.Compare=200; // 配置占空比
TM_OutputModeConfig(HT_GPTM0,TM_CH_0,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA5
OutIniture.Channel=TM_CH_1;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
//OutIniture.Compare=200;
TM_OutputModeConfig(HT_GPTM0,TM_CH_1,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA6
OutIniture.Channel=TM_CH_2;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
//OutIniture.Compare=200;
TM_OutputModeConfig(HT_GPTM0,TM_CH_2,TM_OM_PWM1);
TM_OutputInit(HT_GPTM0,&OutIniture);
// PA7
OutIniture.Channel=TM_CH_3;
OutIniture.Control=TM_CHCTL_ENABLE;
OutIniture.OutputMode=TM_OM_PWM1;
OutIniture.Polarity=TM_CHP_INVERTED;
// 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); //使能计数
}
void PWM_R9DS_init(void){
time_init();
//TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,180);
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,90);
delay_ms(3500);
//TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190);
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190);
delay_ms(3500);
}
void Fan_drive(int i){
TM_SetCaptureCompare(HT_GPTM0,TM_CH_0,190-i);
}
五、相关资料
1. R9DS接收机+AT9S Pro --SBUS解析(STM32F103C8T6)
5. R9DS接收机说明书