1.接线原理图/实验现象如下:
2.代码部分:
主函数(main.c)代码部分:
#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Motor.h" #include "Key.h" uint8_t KeyNum; int8_t Speed;//有符合的变量 int main(void) { OLED_Init(); Motor_Init(); Key_Init(); OLED_ShowString(1, 1, "Speed:"); while(1) { KeyNum = Key_GetNum(); if (KeyNum == 1) { Speed += 20; if (Speed > 100) { Speed = -100; } } Motor_SetSpeed(Speed);//按键控制速度 OLED_ShowSignedNum(1, 7, Speed, 3); } }
PWM.c代码部分:
#include "stm32f10x.h" // Device header //操作思路可参考:(图PWM基本结构) //1.RCC开启时钟,把TIM外设和GPIO外设的时钟打开。 //2.初始化时基单元,选择内部时钟-----使用的还是TIM2,所以直接复制粘贴内部时钟部分代码 //3.初始化输出比较单元,(重要函数TIM_OC3Init)包括CCR的值,输出比较模式,极性选择,输出使能。(结构体) //4.初始化GPIO,(第三步的输出比较模式的值需要GPIO输出展示)TIM_OC3Init,GPIO口初始化为复用推挽输出 //5.运行控制,启动计数器。 void PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//第一步:开启APB1时钟,因为TIM2是APB1总线的外设 TIM_InternalClockConfig(TIM2);//第二步:选择内部时钟 //第二步:初始化时基单元----TIM_TimeBaseInit的第二个参数是结构体,配置结构体 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //TIM_CKD_DIV1,1分频,不分配;TIM_CKD_DIV2,2分频;TIM_CKD_DIV4,4分频----要求不高时,随意选择 TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM_CounterMode_Up向上计数;TIM_CounterMode_Down向下计数;TIM_CounterMode_CenterAligned1等为中央对齐 TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR的值 TIM_TimeBaseInitStructure.TIM_Prescaler=36-1;//PSC的值 TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//结构体 //第三步:初始化输出比较单元,总共有四个,需要3通道,初始化3函数 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值 //TIM_OCInitStructure.TIM_OCIdleState=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式 //TIM_OCInitStructure.TIM_OCNIdleState=;//高级定时器 //TIM_OCInitStructure.TIM_OCNPolarity=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出比较极性,TIM_OCPolarity_High有效电平为高电平 //TIM_OCInitStructure.TIM_OutputNState=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//设置输出使能,TIM_OutputState_Enable使能 TIM_OCInitStructure.TIM_Pulse=0;//设置CCR寄存器的值。 TIM_OC3Init(TIM2,&TIM_OCInitStructure); //TIM2的引脚复用在PA0上,在引脚说明手册里,默认复用功能对应的引脚不能更改, //但是,如果两个外设接在同一引脚,可查找重定义功能更改外设的引脚。 //如需要用TIM的CH1通道输出PWM.则只能在PA0引脚输出,或在重映射改为PA15,因此需要初始化GPIO的PA0 //4.初始化GPIO,(使用第三通道) 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;//直流电机在通道3输出的PWM GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //启动定时器 TIM_Cmd(TIM2,ENABLE); } //通道3 void PWM_SetCompare3(uint16_t Compare) { TIM_SetCompare3(TIM2,Compare); }
PWM.h代码部分:
#ifndef __PWM_H #define __PWM_H void PWM_Init(void); void PWM_SetCompare3(uint16_t Compare); #endif
直流电机(Motor.c)代码部分:
#include "stm32f10x.h" // Device header #include "PWM.h"//继承PWM模块 //初始化直流电机 void Motor_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA时钟 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;//电机方向控制脚4,5脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化电机方向控制脚 PWM_Init();//初始化PWM } void Motor_SetSpeed(int8_t Speed)//设置速度时要有正有负,表示反转。选择int8_t { if (Speed >= 0)//判断正反转 { GPIO_SetBits(GPIOA, GPIO_Pin_4);//设置一个正转,一个反转 GPIO_ResetBits(GPIOA, GPIO_Pin_5); PWM_SetCompare3(Speed); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_4); GPIO_SetBits(GPIOA, GPIO_Pin_5); PWM_SetCompare3(-Speed); } }
直流电机(Motor.h)代码部分:
#ifndef __MOTOR_H #define __MOTOR_H void Motor_Init(void); void Motor_SetSpeed(int8_t Speed); #endif