【STM32】标准库 输出比较

输出比较功能就是用来输出PWM波形的。

OC(Output Compare)输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形,每个高级定时器和通用定时器都拥有4个输出比较通道,高级定时器的前3个通道额外拥有死区生成和互补输出的功能。

PWM(Pulse Width Modulation)脉冲宽度调制 在具有惯性的系统中(具有惯性的系统才能使用PWM,比如led灯,断电不会立马就熄灭,电机,断电不会立马就停止转动)

可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域 PWM参数:    

【STM32】标准库 输出比较_第1张图片

PWM的输出波形相当于一个模拟量,当上部分的占空比大的时候,模拟量也就偏向于那一侧,如上图所示。

【STM32】标准库 输出比较_第2张图片

  频率 = 1 / TS            占空比 = TON / TS           分辨率 = 占空比变化步距

占空比就是高电平占整体周期的比例。

高电平是5V,低电平是0V,那50%占空比就相当于2.5V电压。

20%相当于1V。

分辨率就是占空比跳变的步距,比如百分之一,每一次占空比都变化百分之一。

输出比较电路部分是黄色框框的部分。

【STM32】标准库 输出比较_第3张图片

【STM32】标准库 输出比较_第4张图片

 ref是参考信号,可以把它映射到主模式的TRGO上面去,也可以到达极性选择那一路,机型选择给0,电平不翻转,给1就电平反转。输出使能电路选择要不要输出。oc1或者oc2等有对应的固定引脚,记得要先确定是什么引脚,再使用连接。

【STM32】标准库 输出比较_第5张图片

 输出比较模式指的是根据输入的CNT以及CCR,输出模式控制器选择的输出比较模式,用来确定参考信号的输入是高电平还是低电平。

 因为在输出比较器输出之后还能进行一次极性选择,所以PWM输出模式1的输出可以有两种,其中一种与PWM输出模式2的是一样的,无论是向上还是向下计数,其实也就是说用一种模式就可以了。

【STM32】标准库 输出比较_第6张图片

 时基单元的左边是时钟控制,CNT不断自增,与CCR作比较,然后根据所选模式输出相应电平,如右上角所示,黄色ARR,红色是CCR,蓝色是CNT,根据设定的模式确定在每个大小关系的是偶输出什么电平。

改变CCR或者改变ARR都可以改变占空比,所以REF是一个频率可调占空比可调的信号,经过极性选择,输出使能就可以输出到GPIO口了。

【STM32】标准库 输出比较_第7张图片

 PWM频率其实就是计数器更新的频率,就是到了99再更新变为0的频率。这个公式这样理解,每一次计数的时间乘以99,就是从0计数道99的时间,取倒数就是PWM的频率,每一次计数的时间就是输入频率,输入频率除以分频等于实际输入的频率,取倒数乘以ARR就等于每次更新的时间,再倒数就是PWM频率。

【STM32】标准库 输出比较_第8张图片

 【STM32】标准库 输出比较_第9张图片

 高电平导通,低电平断开,上下断开就是高阻态,这就是推完电路的输出模式,有两个这种电路就构成了H桥电路,H桥就可以控制直流电机的正反转了。三个这样的电路就构成三相无刷电机的驱动了。对于单片机来说,这样一个推挽电路,需要两个输入,而且是两个互补电路。上管导通下管断开,或者上管断开下管导通,但是有时候切换的时候来不及,会出现两者都处于导通的状态,就是直通状态,导致功率损耗,器件发热。所以就有个死区发生器,在导通的管断开瞬间,延迟一段时间,然后再让原本断开的二极管导通,避开直通现象。

PWM驱动舵机

PWM驱动舵机相当于一个通信协议,比如占空比多少就固定在什么角度。跟前面所说的把输出不同的占空比等效成模拟输出曲线不一样。舵机中自带驱动,而直流电机中没有驱动,需要外接驱动。

【STM32】标准库 输出比较_第10张图片

 如果输出要5V的电压,可以连接到STLINK的5V处获得供电,

 【STM32】标准库 输出比较_第11张图片

 【STM32】标准库 输出比较_第12张图片

 对于这个TB6612电机驱动来说,里面应该有两个H桥,H桥就是最右边的图,上边是电源,下边接地,当对角导通,另一个对角不导通的时候,电流从电源处流动到地上,以此来控制电机转动的方向。

O1,O2都是接的电机两端。

【STM32】标准库 输出比较_第13张图片

 PWMA与AIN2,AIN1输入限功率信号,驱动会从VM汲取电压,然后给电机供电。这样就是用小功率信号对大功率器件供电啦,两块阴影部分功能是完全一样的,STBY是待机控制引脚, 接GND就是待机控制,接VCC就是工作。

至于驱动如何控制正转反转,看右下角的表。

转动的速度取决于占空比,因为占空比大的电压比较大,电流也比较大。

【STM32】标准库 输出比较_第14张图片

猜想:大概是驱动里面有两个H桥,四个输入引脚,其实就是对应两个IN,然后两个IN分别在两边,每一边因为硬件电路的不一样,一个导通一个断开,另外一边也是,所以就能决定电机转动的方向。

所以就确定了转动的方向,但是转还是不转,得看PWM波是否是高电平,以及其占空比,占空比决定电压的大小,从而影响转动速度,高电平才有电压,才会转。两个IN以及PWM影响O1O2两个输出的高电平低电平,从而确定点击的转动方向以及装懂速度。其实PWM可以看做是一个控制电压大小的量,根据占空比的大小等量于不同的电压大小,从而影响转动的速度。

【STM32】标准库 输出比较_第15张图片

 【STM32】标准库 输出比较_第16张图片

 有箭头的两头分别是s跟g,箭头对着的要大于没有箭头对着的电压才能导通,根在一起的二极管也跟箭头的方向一致。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

//此四个函数是用来配置输出比较通道的,也就是下图的输出比较单元*4

【STM32】标准库 输出比较_第17张图片

 void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);//是给输出比较通道默认配置一个值的,具体是什么可以跳转查看,并且配置之后想要修改可以用别的函数单个修改覆盖。

void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

【STM32】标准库 输出比较_第18张图片

 第一个参数是输出模式,第二个参数是输出极性,第三个参数是输出使能,第四个参数是设定CCR,还有其他参数,带N的都是高级定时器具备的。我们一般不能只选择其中几个配置,会出现问题的,正确的做法是,先用另一个函数配置初始的值,然后再用上面这几个参数修改。

第一个参数就是冻结模式什么的里的。

第二个参数就是极性选择,高极性就是电平不翻转,低极性就是电平反转。

OC1也就是CH1,但是CH1是固定在PA0引脚上面的,要使用的话,只能使用PA0,其他的几个通道也是如此,但是可以经过重映射的功能就行修改,比如TIM_CH3对应PA2,在重定义功能可以对应PB10,所以可以经过重映射的功能更换端口,避免使用上的冲突。 【STM32】标准库 输出比较_第19张图片

 

用此函数:void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

具体配置成什么,可以选择跳转查看。

在运用输出比较功能的时候,配备引脚的时候,选择输出模式的时候,应该使用复用输出,应为普通的输出都来自数据寄存器,想要用定时器输出的话,应该使用复用输出,这样才能让输入信号来自片上外设。根据上图,片上外设的那条线来自TIM_的CH引脚,然后从对应的I/O口输出PWM信号。

重映射:

开启AFIO的时钟

用GPIO中的这个函数:void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);进行引脚重映射配置

第一个参数根据使用手册8.3中进行选择。第二个参数就是使能失能。

对于下图的这几个调试端口,如果想要把他们当做普通端口或者进行复用,应该也先解除调试端口在进行,用这个函数解除:

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState

   *     @arg GPIO_Remap_SWJ_NoJTRST      : 仅仅解除NJTRST
  *     @arg GPIO_Remap_SWJ_JTAGDisable  : 解除JTAG的所有端口,也就是38.39.40
  *     @arg GPIO_Remap_SWJ_Disable  :解除所有的端口,34,37,38,39,40都解除

SWJ的意思是SWD和JTAG,SWD 指的是34,37

注意自己的下载方式,不然把调试端口给解除掉了下载不进去,慎用。全接触了只能串口下载咯。

TIM_cmd启动定时器。

//这四个是强制改变输出模式,停止输出波形并且置为高电平或者低电平

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

//这四个函数是配置预重装功能的,也就是影子寄存器

void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

//清除REF信号

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

//用来修改通道的输出极性,带N的就是用来修改高级定时器的相反的信号的那个通道,通道4没有相反的,在结构体之中其实也有配置极性的选项,两者是一样的,一般来说结构体的元素都有单独的函数配置修改。

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

//修改使能控制的

void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

//选择输出比较模式

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

//改变CCR的值

void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

//这个函数仅仅高级定时器使用,输出PWM的时候,需要用这个函数使能一下,不然不態正常输出

PWM可以相当于把它看成是一个控制电压的值,占空比越大,输出电压就越大,按照百分比分压。

在实现呼吸灯的这种时候,应该有个延时函数给单片机一点反应的时间,不然太快啦。

 电机如果发出蜂鸣器费声响,可能是PWM频率在人耳范围内,20HZ到20KHz,把它改在范围之外就行了。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)