OC (Output Compare) output comparison
The output comparison can set the output level to 1, set 0 or flip it by comparing the relationship between the CNT and CCR register values, and is used to output a PWM waveform with a certain frequency and duty cycle. (CCR is the value we give, when CNT is greater than, less than/equal to CCR, flip)
Each advanced timer and general timer has 4 output compare channels
The first 3 channels of the advanced timer additionally have the functions of dead zone generation and complementary output.
Introduction to PWM
PWM (Pulse Width Modulation) pulse width modulation
In a system with inertia, the required analog parameters can be obtained equivalently by modulating the width of a series of pulses, which is often used in fields such as motor speed control.
PWM parameters:
Frequency = 1 / TS Duty cycle = TON / TS Resolution = Duty cycle change step
The resolution is a variable name based on the changing value of the duty cycle. For example, from 1%, 2, 3%, etc., it jumps in steps of 1%, and the resolution is 1%.
model |
describe |
freeze |
When CNT=CCR , REF remains in its original state |
Set effective level when matching |
When CNT=CCR , REF is set to a valid level |
Set invalid level when matching |
When CNT=CCR , REF is set to an invalid level |
Level flip on match |
When CNT=CCR , the REF level flips |
Forced to invalid level |
CNT and CCR are invalid, REF is forced to an invalid level |
forced to active level |
CNT and CCR are invalid, REF is forced to a valid level |
PWM mode 1 |
Counting up: when CNT<CCR, REF is set to a valid level; when CNT≥CCR, REF is set to an inactive level. Counting down: when CNT>CCR, REF is set to an invalid level; when CNT≤CCR, REF is set to a valid level. |
PWM mode 2 |
Counting up: when CNT<CCR, REF is set to an invalid level; when CNT≥CCR, REF is set to a valid level. Counting down: when CNT>CCR, REF is set to a valid level; when CNT≤CCR, REF is set to an invalid level. |
PSC is the clock of the prescaler, CCR is the set comparison value, and ARR is the maximum overflow value of the counter.
Introduction to steering gear
The above values are substituted into the PWM formula to meet the requirements. 20K corresponds to 20ms.
There is this corresponding relationship:
20K=20ms
X=Required high level width Find X, X is the value of CCR
The formula for outputting the specified angle can also be derived: Angle/180*2000+500
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//需要复用推挽输出,因为此程序是CH1输出,是片上外设
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//根据GPIO引脚定义,此程序用的是OC2通道,对应的是CH2,由引脚图可知选PA1
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);//由内部时钟驱动
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //预分频系数1
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;// //PSC
TIM_TimeBaseInitStructure.TIM_Period=20000-1;// //ARR
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
TIM_Cmd(TIM2,ENABLE);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择PWM1模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//极性选择,这里是高极性,不翻转,按原来的高低电平输出
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能输出
TIM_OCInitStructure.TIM_Pulse=0; //设计CCR的值
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
}
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}
angle.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void)
{
PWM_Init();
}
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle/180*2000+500);
}
PWM.h
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);
#endif
angle.h
#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif
main
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
Servo_Init();
Key_Init();
OLED_ShowString(1,1,"Angle:");
while(1)
{
KeyNum=Key_GetNum();
if(KeyNum==1)
{
Angle+=15;
if(Angle>180)
{
Angle=0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1,7,Angle,3);
}
}
Introduction to DC motors and drives
driver chip.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Motor_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
PWM_Init();
}
void Motor_SetSpeed(int8_t Speed)
{
if(Speed>=0)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
PWM_SetCompare3(Speed);
PWM_SetCompare2(Speed);
}
else
{
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
PWM_SetCompare3(-Speed);
PWM_SetCompare2(-Speed);
}
}
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;//
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);//由内部时钟驱动
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //预分频系数1
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInitStructure.TIM_Prescaler=36-1;//
TIM_TimeBaseInitStructure.TIM_Period=100-1;//
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
TIM_Cmd(TIM2,ENABLE);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择PWM1模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//极性选择,这里是高极性,不翻转,按原来的高低电平输出
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能输出
TIM_OCInitStructure.TIM_Pulse=0; //设计CCR的值
TIM_OC3Init(TIM2,&TIM_OCInitStructure);
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
}
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2,Compare);//外部设计CCR的值
}
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}
This article was studied with Jiangsu University of Science and Technology and is my study notes. If there is any infringement, please contact me to delete it!