OC (Output Compare) 出力比較
出力比較は、CNT レジスタと CCR レジスタの値の関係を比較することにより、出力レベルを 1 に設定、0 に設定、または反転することができ、特定の周波数とデューティ サイクルの PWM 波形を出力するために使用されます。(CCR は、CNT が CCR より大きい、以下、または等しい場合に与える値であり、反転します)
各アドバンスト タイマーと一般タイマーには 4 つの出力比較チャネルがあります。
アドバンストタイマーの最初の 3 チャネルには、デッドゾーン生成と相補出力の機能が追加されています。
PWM の概要
PWM(パルス幅変調)パルス幅変調
慣性のあるシステムでは、一連のパルスの幅を変調することで必要なアナログパラメータを等価的に取得でき、モーター速度制御などの分野でよく使用されます。
PWMパラメータ:
周波数 = 1 / TS デューティ サイクル = TON / TS 分解能 = デューティ サイクル変更ステップ
分解能はデューティ比の変化値に応じた変数名で、例えば1%、2、3%…と1%刻みでジャンプし、分解能は1%となります。
モデル |
説明する |
氷結 |
CNT=CCRの場合、REF は元の状態のままになります。 |
マッチング時の有効レベルを設定する |
CNT=CCRの場合、REF は有効なレベルに設定されます |
マッチング時に無効なレベルを設定する |
CNT=CCRの場合、REF は無効なレベルに設定されます |
マッチ時のレベル反転 |
CNT=CCRの場合、REF レベルが反転します |
強制的に無効なレベルに設定されました |
CNTと CCR は無効であり、REF は強制的に無効なレベルに設定されます |
アクティブレベルに強制される |
CNTと CCR は無効であり、REF は強制的に有効なレベルに設定されます |
PWMモード1 |
カウントアップ:CNT<CCRの場合、REFは有効レベルに設定され、CNT≧CCRの場合、REFは非アクティブレベルに設定されます。 カウントダウン: CNT>CCR の場合、REF は無効レベルに設定され、CNT ≦ CCR の場合、REF は有効レベルに設定されます。 |
PWMモード2 |
カウントアップ:CNT<CCRの場合、REFは無効レベルに設定され、CNT≧CCRの場合、REFは有効レベルに設定されます。 カウントダウン: CNT>CCR の場合、REF は有効レベルに設定され、CNT ≦ CCR の場合、REF は無効レベルに設定されます。 |
PSC はプリスケーラのクロック、CCR は設定された比較値、ARR はカウンタの最大オーバーフロー値です。
ステアリングギアの紹介
上記の値は要件を満たすために PWM 式に代入され、20K は 20ms に相当します。
次のような対応関係があります。
20K=20ミリ秒
X=必要な高レベル幅 X を求めます。X は CCR の値です
指定した角度を出力する式も導出できます: 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的值
}
角度.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
角度.h
#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif
主要
#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);
}
}
DC モーターとドライブの紹介
ドライバーチップ.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的值
}
この記事は江蘇科技大学と共同で研究したものであり、私の研究ノートです。侵害がある場合は、削除するために私に連絡してください。