-
输出比较(OC)功能介绍
-
pwm的介绍
-
输出比较通道的基本结构,以及pwm实现步骤
-
相关函数介绍
-
目标及代码
一、输出比较(OC)功能介绍
1.介绍:OC(Output Compare)输出比较,通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形(需要使用此功能输出pwm波)
2.资源说明:每个高级定时器和通用定时器都拥有4个输出比较通道,高级定时器的前3个通道额外拥有死区生成和互补输出的功能
二、pwm的基本结构,以及实现步骤
1.介绍:pwm(脉宽调制)利用微处理器的数字输出对模拟电路进行控制的一种技术,通过改变脉冲宽度改变电压的输出(改变高电平和低电平的时间,实现改变平均电压,可以控制led灯的亮度,马达转速,舵机等等)
2.pwm的相关参数
- 频率 = 1 /T 这个不用多说就是一个周期的倒数
- 占空比 = T'(高电平时间)/ T 高电平的时间毕上一个周期
- 分辨率 = 占空比变化步距 比如占空比从1%,2%...这样变化,分辨率就是1%
三、输出比较通道的基本结构,以及pwm实现步骤
1.输出比较通道的基本结构见下图
- 大致原理是通过配置输出模式控制器,然后比较CNT与CCR的值实现电平的操纵。配置完成后信号会输出到对应的通道
- 我们要实现pwm选择任意一个pwm模式就行(这里选择pwm模式1,向上计数。下图)
2.实现pwm的基本结构
- 如图所示,实现pwm需要以下的步骤:RCC配置需要的时钟-->配置好开启的时基单元和需要用到的GPIO口(GPIO改成复用推挽输出,将控制权交给片上外设的通道)-->配置输出比较单元-->使用TIM_Cmd运行
3.关于pwm的参数计算
- 如图所示,参数的计算与时基单元(上一节有介绍)有关
- 图中CNT一直增加到ARR(99)总共计了100次数,CCR设置为30
- 由图知pwm的频率对应着计数器更新频率
- 在CNT<CCR是时间内为高电平可以推出占空比
- ARR越大,CCR打范围就越大,对应的分辨率就越高
四、相关函数介绍
- TIM_InternalClockConfig:开启对应的定时器
- TIM_OC1Init:初始化输出比较单元(需要结构体参数,配置五),因为输出比较单元有4个,所以数字1改成2、3就可以配置别的输出比较单元
- TIM_OCStructInit:结构体初始化
- TIM_CCxCmd与TIM_CCxNCmd:单独修改输出使能
- TIM_SetCompare1:单独修改通道1CCR的值
- 注:PWM的输出需要使用GPIO口,具体那个GPIO能用记得查引脚定义表
五、目标及代码
1.使用pwm配置led呼吸灯
- 第一步,RCC配置
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//这里用的Tim2,是APB1的外设
/*注意pwm的输出波形输出在PA0上,这里再初始一下GPIOA*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置PA0,让它能输出pwm波
- 第二步,配置时基单元,和需要的GPIO口
/*配置时基单元*/
TIM_InternalClockConfig(TIM2);
/*配置时基单元,上节有*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//控制时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数器模式,向上计数这种
TIM_TimeBaseInitStructure.TIM_Period = 100-1;//ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1;//PSC预分频器值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计时器用的
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//需要结构体参数,记得取地址符
/*配置GPIO*/
GPIO_InitTypeDef GPIO_InitStruture;
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AF_PP;//改成复用推挽输出,将控制权交给片上外设TIM2的CH1通道
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_0;//在PA0上输出pwm波
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruture);
- 第三步,配置输出比较单元
/*配置结构体的时候有很多参数(带n的参数,ldleState的...)是高级定时器才用的,这里只配置了一些用的到的*/
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCStructInit(&TIM_OCInitStruct);//给结构体赋初始值,防止有的参数每赋值出现问题
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//模式,pwm1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//极性,决定有效电平是高是低
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 50;//CCR,如果将ARR+1配成100,那占空比就是CCR%
TIM_OC1Init(TIM2,&TIM_OCInitStruct);
- 第四步,Cmd运行
TIM_Cmd(TIM2,ENABLE);
- 为了实现呼吸灯程序,还需要一个函数实现CCR值的不断改变
/**
*@brief 更改CCR即更改pwm占空比
*@param CCR值
*@retval 无
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);//CCR更改位Compare,注意第一个参数
}
- 主函数如下,其他.h文件前几节都有,pwm的.c文件啥的再写一下就可以了
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "pwm.h"
uint8_t i;
int main(void)
{
pwm_Init();
while(1)
{
/*占空比升高变亮*/
for(i=0;i<=100;i++)
{
PWM_SetCompare1(i);
Delay_ms(10);//防止过快不明显
}
/*占空下降高变暗*/
for(i=100;i>0;i--)
{
PWM_SetCompare1(i);
Delay_ms(10);
}
}
}