利用stm32高级定时器输出PWM,模拟呼吸灯的效果带刹车功能。由于没有示波器查看输出的pwm波形图,所以本次实验使用普通直流电机模拟的。
本文章为学习笔记,其中有些地方解释的不是那么的好,即本笔记可参考、可借鉴、可指点!
简单介绍: STM32F103C8T6采用 LQFP48方式封装,一共拥有 37个 I/O引脚,被分为PA(15个)、PB(15个)、PC(3个)、PD(2个)、PE(0个)五个组,所有 I/O接口可以映像到 16个外部中断,并且大部份端口都可以可以兼容5V信号。每个 I/O端口可以接受或输出8mA电流,灌电流则可达到20mA。 STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级 定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO 。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上 / 下计数的定时器,可以定时,可以输出比较, 可以输入捕捉,每个定时器有四个外部 IO 。高级定时器 TIM1/8 是一个 16 位的可以向上 / 下计数 的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定 时器有 8 个外部 IO 。 用到的相关结构体
typedef struct {
uint16_t TIM_Prescaler; // 预分频器
uint16_t TIM_CounterMode; // 计数模式
uint32_t TIM_Period; // 定时器周期
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter;// 重复计算器
} TIM_TimeBaseInitTypeDef;
备注:
只要用到了TIM定时器就会用到这个结构体
typedef struct {
uint16_t TIM_OCMode; // 比较输出模式
uint16_t TIM_OutputState; // 比较输出使能
uint16_t TIM_OutputNState; // 比较互补输出使能
uint32_t TIM_Pulse; // 脉冲宽度
uint16_t TIM_OCPolarity; // 输出极性
uint16_t TIM_OCNPolarity; // 互补输出极性
uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态
uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;
备注:
只要需要输出PWM波,就需要这个结构体
typedef struct {
uint16_t TIM_OSSRState; // 运行模式下的关闭状态选择
uint16_t TIM_OSSIState; // 空闲模式下的关闭状态选择
uint16_t TIM_LOCKLevel; // 锁定配置
uint16_t TIM_DeadTime; // 死区时间
uint16_t TIM_Break; // 断路输入使能控制
uint16_t TIM_BreakPolarity; // 断路输入极性
uint16_t TIM_AutomaticOutput; // 自动输出使能
} TIM_BDTRInitTypeDef;
备注:
这个是中断PWM输出的结构体,也叫PWM死区控制
直接上代码吧!
头文件里面定义的宏,为什么要这么定义,下面注释有解释
/*****************
根据实验所得,用TIM1(即PA引脚组)输出pwm的时候会影响串口1的通信
所以这里将PWM换至其他组,但会丢弃刹车功能
*****************/
#if 0 //修改这个参数选择TIM1高级定时器还是TIM3通用定时器
#define TIMX_Config 1
#define RCC_APBxPeriphClockCmd RCC_APB2PeriphClockCmd
#define RCC_APB2Periph_GPIOx RCC_APB2Periph_GPIOA
#define GPIO_Pin_x GPIO_Pin_11
#define GPIOx GPIOA
#define RCC_APBxPeriph_TIMx RCC_APB2Periph_TIM1
#define TIMx TIM1
#else
#define TIMX_Config 0
#define RCC_APBxPeriphClockCmd RCC_APB1PeriphClockCmd
#define RCC_APB2Periph_GPIOx RCC_APB2Periph_GPIOB
#define RCC_APBxPeriph_TIMx RCC_APB1Periph_TIM3
#define GPIO_Pin_x GPIO_Pin_1
#define GPIOx GPIOB
#define TIMx TIM3
#endif
下面代码解释:但选用高级定时器TIM1的时候,对应的输出引脚是PA11,刹车引脚是PB12;
当选用通用定时器TIM3的时候,对应PWM输出引脚PB1,通用没有刹车功能
关于pwm波输出引脚和刹车中断引脚的初始化
static void TIM_GPIO_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
//PWM输出引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_x;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOx,&GPIO_InitStructure);
#if TIMX_Config
//死区刹车引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_ResetBits(GPIOx,GPIO_Pin_12);
#endif
}
下面代码解释:配置的基本定时器的定时为
ARR+1:自动重装载寄存器的值;其中(ARR+1)为TIM_Period的值
PSC+1:预分频值 ;其中(PSC+1)为TIM_Prescaler的值
一个计数器单次计数的频率:Cnt_CLK=Tclk/(PSC+1)=72M/(PSC+1);周期 T=(PSC+1)/Tclk=(PSC+1)/72M;ARR+1为你需要定时这么多个单次计数频率或周期。
总定时时间: Tout(us) = (重装载值+1)*((预分频值+1) / 内部时钟 ) = (ARR+1)*(PSC+1)/Tclk(单位MHz) ;
即定时器(PWM)一个定时周期 :Tout=(ARR+1)*(PSC+1)/Tclk ;频率f=1/Tout=Tclk/(ARR+1)*(PSC+1) 。
占空比 P=CCR/(ARR+1)=TIM_Pulse/(ARR+1)=TIM_Pulse/TIM_Period。
下面配置的是(ARR+1)=10;(PSC+1)=72;即计算出定时周期为10us 频率为100KHz;
通过TIM_SetCompare1(TIM1, Compare1),来修改占空比的值;则占空比100%的时候Compare1=10;0%占空比的时候Compare1=0。
着重注意:例如 TIM_OC4Init(TIMx, &TIM_OCInitStructure); 初始化的时候,别把通道选错了
关于TIM、pwm、pwm死区等相关配置和初始化
static void TIM_Mode_Config()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//计时器结构体初始化
TIM_OCInitTypeDef TIM_OCInitStructure;//输出比较结构体
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;//刹车和死区结构体初始化
RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx,ENABLE);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
TIM_TimeBaseStructure.TIM_Period=10-1;// 自动重装载寄存器的值ARR
TIM_TimeBaseStructure.TIM_Prescaler= 72-1;// 时钟预分频值 PSC
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//不用管
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);//初始化
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择PWM1模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
TIM_OCInitStructure.TIM_Pulse = 5;// 设置占空比大小 50%
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;// 输出通道空闲电平极性配置
TIM_OC4Init(TIMx, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);//自动重装载
#if TIMX_Config
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;//运行模式下的关闭状态选择
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;//空闲模式下的关闭状态选择
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;//锁定级别配置
TIM_BDTRInitStructure.TIM_DeadTime = 11;// 输出比较信号死区时间配置 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;//刹车功能使能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;//刹车输入检测极性,即外部输入高电平为刹车还是低电平
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;//自动输出使能
TIM_BDTRConfig(TIMx, &TIM_BDTRInitStructure);
#endif
TIM_Cmd(TIMx, ENABLE); // 使能计数器
#if TIMX_Config
TIM_CtrlPWMOutputs(TIMx, ENABLE);// 主输出使能,高级定时器才需要配置下面的函数
#endif
}
下面代码解释:下面设置的每次增加的占空比为10%,如果需要更加细致的话,则需要修改上面的TIM相关参数,把每个PWM的分得更加细,这样就可以1%的步进进行调节了。
着重注意:选择通道几,就要对应配置这个函数的x “TIM_SetCompareX()"
/****************************
函数:uint8_t Motor_PWM_Fun(void)
参数:
功能:通过PWM实现类似呼吸灯效果的输出
说明://TIM_SetCompare1(TIM1, Compare1);//Compare1 范围0~10 自定义
只要配置好了,即可直接调用该函数
****************************/
uint8_t Motor_PWM_Fun(void)
{
value=pwm_value;
if(pwm_value>10)
{
if(pwm_value==20)
{
pwm_value=0;
value=0;
}
else
{
value=10-value%10;
}
TIM_SetCompare4(TIMx,value);//Compare1 范围0~10 自定义
}
else
{
TIM_SetCompare4(TIMx,value);//Compare1 范围0~10 自定义
}
sprintf(PWM_value,"\tPWM:value=%d%%\r\n",value*10);
Usart1_SendString(PWM_value);
pwm_value++;
return 0;
}
pwm简易模拟呼吸灯
关注显示器上面的PWM的值的变化,对比车轮的转速变化(这里可能看起不明显)
PWM调速电机
注意:STM32F103C8T6拥有 7个定时器:其中 1个用于电机控制的 16位 PWM高级控制定时器、3个 16位通用定时器、2个看门狗定时器(包含独立型的和窗口型)、1个 24位自减型系统嘀嗒定时器。
高级控制定时器 TIM1:TIM1可以被视为分配到 6个通道的三相 PWM发生器,具有带死区插入的互补 PWM输出,还可以用作完整的通用定时器;其四个独立通道可分别用于:输入捕获、输出比较、产生边缘或中心对齐模式的PWM、单脉冲输出。当配置为 16位普通定时器时,与TIM2、TIM3、TIM4具有相同功能;配置为 16位 PWM发生器时,具有0 ~ 100%的全调制能力。
通用定时器 TIM2、TIM3、TIM4:STM32F103C8T6内置有 3个可同步运行的标准定时器,每个定时器都拥有一个 16位自动加载递加/递减计数器、一个 16位预分频器、4个独立通道,每个通道都可用于输入捕获、输出比较、PWM、单脉冲输出,它们还可以通过定时器链接功能与高级控制定时器 TIM1协同工作,从而提供同步或事件链接功能。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)