目录
https://blog.csdn.net/m0_61712829/article/details/132434192?spm=1001.2014.3001.5501输出比较相关库函数1.OC初始化(掌握)
- // 配置输出比较模块,输出比较单元有四个,对应也有四个函数
- // 第二个参数是结构体,就是输出比较的一些参数
- 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);
-
- // 给输出比较结构体赋一个默认值(防止结构体的值不确定导致一些奇怪的问题)
- void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
2.OC参数更改(TIM_SetComparex函数最重要,其他的了解即可)
- // 使用高级定时器输出PWM波形时使能主输出,否则PWM波形不能正常输出
- void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
-
- // 单独设置输出比较的输出极性(带N的是高级定时器中互补通道的配置)
- // 在这里可以设置输出极性,在OC初始化函数中也可以用结构体设置输出极性,这里相当于将单独修改结构体中的某一参数封装到一个函数中
- //在结构体初始化的那个函数里也可以设置极性,这两个地方设置极性的作用是一样的,只不过是用结构体是一起初始化的,在这里是单独函数进行修改的
- //一般来说,结构体里的参数都会有一个单独的函数可进行更改
- 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);
-
- // 单独修改输出使能参数
- 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);
-
- // 单独更改CCR寄存器值的函数
- //在运行时,更改占空比,就需要用到这四个函数
- 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);
3.OC输出比较的一些小功能(不常用,了解即可)
- // 配置强制输出模式(运行中暂停输出波形且强制输出高/低电平)
- // 强制输出高电平和设置100%占空比等效,强制输出低电平和设置0%占空比等效
- 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);
-
- // 配置CCR寄存器的预装功能(影子寄存器,就是写入的值不会立即生效而是在更新事件才会生效,可以避免一些小问题)
- 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_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
- void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
- void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
- void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
-
- // 清除REF信号(手册中在“外部事件时清除REF信号”一节有介绍)
- 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);
4.补充
- //仅高级定时器使用
- //在使用高级定时器输出PWM时。需要调用这个函数,使能输出。否则PWM将不能正常输出
- void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
5.补充
//TIM_OCMode 输出比较模式中的选择
- TIM_OCMode_Timing//冻结模式
- TIM_OCMode_Active//相等时置有效电平
- TIM_OCMode_Inactive//相等时置无效电平
- TIM_OCMode_Toggle//相等时电平翻转
- TIM_OCMode_PWM1//PWM模式1,主要用
- TIM_OCMode_PWM2//PWM模式2
- TIM_ForcedAction_Active//强制输出模式,初始化时不使用
- TIM_ForcedAction_InActive
TIM_Output_Compare_Polarity 输出比较的极性选择
- TIM_OCPolarity_High //高极性,就是极性不翻转,REF波形直接输出,或者说是有效电平是高电平,REF有效时,输出高电平
- TIM_OCPolarity_Low //低极性,就是REF电平取反,或者说是有效电平为低电平
接线图如下:注意LED是正极接在PA0引脚,负极接在GND的驱动方法,这样就是高电平点亮,低电平熄灭,这是正极性的驱动方法,这样的话观察更直观一点,就是占空比越大LED越亮,占空比越小LED越暗 。

main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "PWM_LED.h"
-
- uint8_t i;
-
- int main(void)
- {
-
- OLED_Init(); //初始化OLED
- pwm_init();
-
- while(1)
- {
- //不断调用PWM_SetCompare1函数,更改CCR的值,实现LED呼吸灯的效果
- for(i=0;i<=100;i++)
- {
- PWM_SetCompare1(i);//设置CCR寄存器的值
- Delay_ms(10);
- }
- for(i=0;i<=100;i++)
- {
- PWM_SetCompare1(100-i);
- Delay_ms(10);
- }
- }
- }
PWM_LED.c
- #include "stm32f10x.h" // Device header
-
- /*
- pwm初始化函数基本步骤(参考笔记PWM基本结构图)
- 第一步,RCC开启时钟,把要用的TIM外设和GPIO外设的时钟打开
- 第二步,配置单元,包括时钟源选择和时基单元都配置好
- 第三步,配置输出比较单元,包括CCR值、输出比较模式、极性选择、输出使能这些参数,在库函数里也是用结构体统一来配置
- 第四步,配置GPIO,把PWM对应的GPIO口,初始化为复用推挽输出的配置,Pwm和GPIO的对应关系可以参考引脚定义表
- 第五步,运行控制,启动计数器,这样就能输出PWM了
- */
-
- void pwm_init(void)
- {
- //1.打开时钟,选择内部时钟
- //使用APB1的开启时钟函数,TIM2是APB1总线的外设
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开时钟
-
- //引脚重映射内容,将PA0引脚重映射到PA15,将下面GPIO改为PA15其它不动
- // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//引脚重映射;引脚重映射(TIM2的CH1本来是挂载在PA0引脚的,现在我想在其他引脚使用TIM2的CH1通道
- // GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//参考手册AFIO。将PA0引脚重映射到PA15,第一个参数可以是GPIO_PartialRemap1_TIM2或GPIO_FullRemap_TIM2
- // GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//取消调试端口复用JTAG,PA15端口默认使用JTAG调试端口,需要关闭;SWJ就是SWD和JTAG两种调试方式;若想用PA15\PB3\PB4三个引脚做GPIO使用,先打开AFIO再将JTAG复用解除
-
- //2.初始化时基单元
- //选择时基单元的时钟,选择内部时钟;若不调用这个函数,系统上电也是默认是内部时钟
- TIM_InternalClockConfig(TIM2);
-
- //3.配置时基单元
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式
- /*
- 公式:
- PWM频率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
- PWM占空比:Duty = CCR / (ARR + 1)
- PWM分辨率:Reso = 1 / (ARR + 1)
- 若PWM波形为频率为1KHz,占空比为50%,分辨率为1%
- CK_PSC=72MHz
- 代入公式:
- Freq =1000Hz=72MHz / 720 / 100
- Duty = 50% = 50 / 100
- Reso = 1% = 1 / 100
- 因此:PSC=719,ARR=99,ARR=50
- */
- TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR 周期
- TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC 预分频器
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值
- TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
- TIM_ClearFlag(TIM2,TIM_FLAG_Update);
-
- //4.初始化输出比较单元(通道)
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值;若不想把所有成员都列一遍赋值,就可以先用这个函数赋一个初始值,再更改你想改的值
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较的模式
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较的极性
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出使能(输出状态)
- TIM_OCInitStructure.TIM_Pulse = 50;//设置CCR,Pulse直译是脉冲
- TIM_OC1Init(TIM2, &TIM_OCInitStructure);//使用PA0口对应是第一个输出比较通道;在TIM2的OC1通道上就可以输出PWM波形了
-
- //5.初始化GPIO
- GPIO_InitTypeDef GPIO_InitStructure; //结构体变量名GPIO_InitStructure
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;PWM波形通过引脚输出,使用定时器来控制引脚,输出数据寄存器将被断开,输出控制权将转移给片上外设(这里片上外设引脚连接的就是TIM2的CH1通道)
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //默认50mhz输出
- GPIO_Init(GPIOA,&GPIO_InitStructure); //使用的是地址传递
-
- //6.启动定时器
- TIM_Cmd(TIM2,ENABLE);//PWM波形就能通过PA0输出了
- }
-
-
- //让LED呈现呼吸灯的效果,那就是不断更改CCR的值就行了
- //在运行过程更改CCR,使用函数TIM_SetCompare1封装用来单独更改通道1的CCR值
-
- //TIM_SetCompare1封装
- void PWM_SetCompare1(uint16_t Compare1)
- {
- TIM_SetCompare1(TIM2,Compare1);
-
- }

驱动舵机的关键就是输出一个下面一样的PWM波形,只要波形能够按照如下规定,准确的输出,那驱动舵机就非常简单了。

main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "serve.h"
- #include "key.h"
-
- uint8_t keynum; //按键键码
- float angle;//角度变量
-
- int main(void)
- {
-
- OLED_Init(); //初始化OLED
- serve_init();
- key_init();
-
- OLED_ShowString(1, 1 ,"angle:");
-
- //serve_setangle(120); //舵机设置角度
- //PWM_SetCompare2(500); //对应舵机0度的位置
- //建立一个舵机模块,封装函数。调用函数就能变为对应的角度,舵机设置角度,参数是0到180度
-
- while(1)
- {
- keynum = key_getnum();
- if(keynum == 1)
- {
- angle += 30;
- if(angle > 180)
- {
- angle = 0;
- }
- }
- serve_setangle(angle); //舵机设置角度
- OLED_ShowNum(1,7,angle,3);//一行七列显示angle变量长度为3
-
- }
- }
pwm_led.c
- #include "stm32f10x.h" // Device header
-
- /*
- pwm初始化函数基本步骤(参考笔记PWM基本结构图)
- 第一步,RCC开启时钟,把要用的TIM外设和GPIO外设的时钟打开
- 第二步,配置单元,包括时钟源选择和时基单元都配置好
- 第三步,配置输出比较单元,包括CCR值、输出比较模式、极性选择、输出使能这些参数,在库函数里也是用结构体统一来配置
- 第四步,配置GPIO,把PWM对应的GPIO口,初始化为复用推挽输出的配置,Pwm和GPIO的对应关系可以参考引脚定义表
- 第五步,运行控制,启动计数器,这样就能输出PWM了
- */
-
- //驱动舵机用的是PA1口的通道2
- void pwm_init(void)
- {
- //1.打开时钟,选择内部时钟
- //使用APB1的开启时钟函数,TIM2是APB1总线的外设
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开时钟
-
- //2.初始化时基单元
- //选择时基单元的时钟,选择内部时钟;若不调用这个函数,系统上电也是默认是内部时钟
- TIM_InternalClockConfig(TIM2);
-
- //3.配置时基单元
- /*
- **********************************************************
- 公式:
- PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
- PWM占空比:Duty = CCR / (ARR + 1)
- PWM分辨率:Reso = 1 / (ARR + 1)
- ************************************************************
- 若PWM波形为频率为1KHz,占空比为50%,分辨率为1%
- 舵机要求的周期是20ms,频率就是1/20ms=50hz;舵机要求高电平时间是0.5ms-2.5ms,也就是占空比
- ARR设置为20k对应20ms(计数器加一次就是1us)
- CCR设置500就是0.5ms,设置2500就是2.5ms
- */
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式
- TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR 周期
- TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC 预分频器
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值
- TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
- TIM_ClearFlag(TIM2,TIM_FLAG_Update);
-
- //4.初始化输出比较单元(通道)
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值;若不想把所有成员都列一遍赋值,就可以先用这个函数赋一个初始值,再更改你想改的值
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较的模式
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较的极性
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出使能(输出状态)
- TIM_OCInitStructure.TIM_Pulse = 50;//设置CCR,Pulse直译是脉冲
- TIM_OC2Init(TIM2, &TIM_OCInitStructure);//OC2是通道2;通道和引脚是对应的;对于同一个定时器的不同通道输出的PWM的特点如后:因为不同通道共用一个计数器,所以它们的频率必须是一样的,它们的占空比由各自的CCR决定的;由于计数器的更新,所有PWM同时跳变,所以它们的相位是同步的
-
- //5.初始化GPIO
- GPIO_InitTypeDef GPIO_InitStructure; //结构体变量名GPIO_InitStructure
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;PWM波形通过引脚输出,使用定时器来控制引脚,输出数据寄存器将被断开,输出控制权将转移给片上外设(这里片上外设引脚连接的就是TIM2的CH1通道)
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //默认50mhz输出
- GPIO_Init(GPIOA,&GPIO_InitStructure); //使用的是地址传递
-
- //6.启动定时器
- TIM_Cmd(TIM2,ENABLE);//PWM波形就能通过PA0输出了
- }
-
-
-
- //TIM_SetCompare2封装,使用通道2
- void PWM_SetCompare2(uint16_t Compare)
- {
- TIM_SetCompare2(TIM2,Compare);
-
- }
serve.c
- #include "stm32f10x.h" // Device header
- #include "PWM_LED.h" //继承pwm的功能
-
-
- //舵机初始化函数
-
- void serve_init(void)
- {
- pwm_init();//将pwm底层初始化
- }
-
- /*
- 0度 对应 CCR 500
- 180 2500
- 对angle进行缩放。0-180是180范围,500-2500是2000范围,所以angle / 180*2000 + 500偏移,就得到目标比例了完成0-180到500-2500的映射了
- */
-
- void serve_setangle(float angle) //舵机设置角度
- {
- PWM_SetCompare2(angle / 180 * 2000 + 500);//线性映射
- }

加大PWM频率,当PWM频率足够大时,超出人耳的范围,人耳就听不到了,人耳听到的范围是20Hz到20KHz。可以减小PSC来加大频率且不会影响占空比
main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "moter.h"
- #include "key.h"
-
- uint8_t keynum;//按键键码
- int8_t speed;//有符号的速度变量
-
-
- int main(void)
- {
-
- OLED_Init(); //初始化OLED
- moter_init();
- key_init();
-
- OLED_ShowString(1,1,"speed:");
-
- while(1)
- {
- keynum = key_getnum();
- if(keynum == 1)
- {
- speed += 20;
- if(speed > 100)
- {
- speed = -100;//speed从-100到100变化
- }
- }
- moter_setspeed(speed);//实现按键控制速度
- OLED_ShowSignedNum(1,7,speed,3);
- }
- }
-
PWM_LED.c
- #include "stm32f10x.h" // Device header
-
- /*
- pwm初始化函数基本步骤(参考笔记PWM基本结构图)
- 第一步,RCC开启时钟,把要用的TIM外设和GPIO外设的时钟打开
- 第二步,配置单元,包括时钟源选择和时基单元都配置好
- 第三步,配置输出比较单元,包括CCR值、输出比较模式、极性选择、输出使能这些参数,在库函数里也是用结构体统一来配置
- 第四步,配置GPIO,把PWM对应的GPIO口,初始化为复用推挽输出的配置,Pwm和GPIO的对应关系可以参考引脚定义表
- 第五步,运行控制,启动计数器,这样就能输出PWM了
- */
-
- //1.电机接在TIM2的通道3上。修改:GPIO_Pin_2。TIM_OC3Init。PWM_SetCompare3
- //2.对于直流电机也建立一个hardware模块
-
- void pwm_init(void)
- {
- //1.打开时钟,选择内部时钟
- //使用APB1的开启时钟函数,TIM2是APB1总线的外设
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开时钟
-
- //2.初始化时基单元
- //选择时基单元的时钟,选择内部时钟;若不调用这个函数,系统上电也是默认是内部时钟
- TIM_InternalClockConfig(TIM2);
-
- //3.配置时基单元
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式
- /*
- 公式:
- PWM频率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
- PWM占空比:Duty = CCR / (ARR + 1)
- PWM分辨率:Reso = 1 / (ARR + 1)
- 若PWM波形为频率为1KHz,占空比为50%,分辨率为1%
- CK_PSC=72MHz
- 代入公式:
- Freq =1000Hz=72MHz / 720 / 100
- Duty = 50% = 50 / 100
- Reso = 1% = 1 / 100
- 因此:PSC=719,ARR=99,ARR=50
- */
- TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR 周期
- TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC 预分频器,现在为20KHz
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值
- TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
- TIM_ClearFlag(TIM2,TIM_FLAG_Update);
-
- //4.初始化输出比较单元(通道)
- TIM_OCInitTypeDef TIM_OCInitStructure;
- TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值;若不想把所有成员都列一遍赋值,就可以先用这个函数赋一个初始值,再更改你想改的值
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较的模式
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较的极性
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出使能(输出状态)
- TIM_OCInitStructure.TIM_Pulse = 50;//设置CCR,Pulse直译是脉冲
- TIM_OC3Init(TIM2, &TIM_OCInitStructure);//TIM2通道3
-
- //5.初始化GPIO
- GPIO_InitTypeDef GPIO_InitStructure; //结构体变量名GPIO_InitStructure
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;PWM波形通过引脚输出,使用定时器来控制引脚,输出数据寄存器将被断开,输出控制权将转移给片上外设(这里片上外设引脚连接的就是TIM2的CH1通道)
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //默认50mhz输出
- GPIO_Init(GPIOA,&GPIO_InitStructure); //使用的是地址传递
-
- //6.启动定时器
- TIM_Cmd(TIM2,ENABLE);//PWM波形就能通过PA0输出了
- }
-
-
-
- //TIM_SetCompare1封装
- void PWM_SetCompare3(uint16_t Compare)
- {
- TIM_SetCompare3(TIM2,Compare);
-
- }
-
-
-
-
-
-
-
-
moter.c
- #include "stm32f10x.h" // Device header
- #include "PWM_LED.h" //继承PWM模块
-
-
- void moter_init(void) //初始化函数
- {
- pwm_init();//调用底层的PWM_init,初始化pwm
-
- //需要额外初始化方向控制的两个脚,即初始化GPIO引脚
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开时钟
- //配置端口模式
- GPIO_InitTypeDef GPIO_InitStructA; //结构体变量名GPIO_InitStructA
- GPIO_InitStructA.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructA.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5; //或运算,选择两个引脚
- GPIO_InitStructA.GPIO_Speed = GPIO_Speed_50MHz; //默认50mhz输出
- GPIO_Init(GPIOA,&GPIO_InitStructA); //使用的是地址传递
- }
-
-
- //设置速度的函数
- void moter_setspeed(int8_t speed)
- {
- //针对正转和翻转,用if来分别处理
- if(speed >= 0)//正转的逻辑
- {
- //首先将方向控制脚设置为一个高电平,一个低电平.哪个为高哪个为底无所谓
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
- GPIO_ResetBits(GPIOA,GPIO_Pin_5);
- //速度
- PWM_SetCompare3(speed);
- }
- else//speed就是负数,代表反转
- {
- //首先是正反转,将set和reset反过来就能反转了
- GPIO_ResetBits(GPIOA,GPIO_Pin_4);
- GPIO_SetBits(GPIOA,GPIO_Pin_5);
- PWM_SetCompare3(-speed);//此时speed为负数,必须为正数,在speed前加负号
- }
-
- }
-
-
-