智能小家居------舵机开门,电机做风扇 or 拉窗帘、呼吸灯做提示,小OLED屏幕显示当前状态。
直接上代码
背景:我觉得我看了那么多教程了,然而只会玩单个东西,串起来就不太懂。
本项目的代码部分实现用到了2个时钟,TIM2 和 TIM3。
经历的问题:原本我是想只用一个时钟,不同通道来实现PWM的输出,但是我发现 我如果把TIM_TimeBaseInitStructure.TIM_Period = ARR ; //ARR 自动重装器的值
ARR = 20000 -1 时,只能驱动舵机,不能驱动电机。
ARR = 100 -1 时,只能驱动电机,不能驱动舵机。
后来发现: SG90舵机接收的PWM信号频率为50HZ,T=1/f,所以周期为20ms。 当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。
解决方案:所以后来使用了2个时钟,分别输出上面这2个ARR的PWM。
明天准备再加一个呼吸灯功能。
如果你有更好的方案,可以留言或者私信我哦,我们可以交流交流哈哈哈,一起进步呀。
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "Servo.h"
#include "PWM.h"
#include "Motor.h"
extern void Motor_Set_Dir(int8_t Speed);
extern void Exti_Test_Pull_Level_Set(void);
//extern void PWM_SetCompare3(uint16_t Compare);
uint8_t i,KeyNum;
int main(void)
{
Key_Init();
OLED_Init();
Servo_Init();
Motor_Init();
OLED_ShowString(1,1,"Angle:");
OLED_ShowString(2,1,"KeyNum:");
OLED_ShowString(3,1,"Speed:");
Servo_Set_Angle(0);//设置舵机初始角度
while (1)
{
KeyNum = Key_GetNum();
Servo_Turn(KeyNum);
Motor_Speed_Set(KeyNum);
}
}
pwm.h
#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h" // Device header
void Servo_PWM_Init();
void Motor_PWM_Init();
void PWM_SetCompare_Servo(uint16_t Compare);//实际为void PwmCompare()函数
void PWM_SetCompare_Motor(uint16_t Compare);//实际为void PwmCompare()函数
#endif
pwm.c
#include "stm32f10x.h" // Device header
#define TIM2_CH2 GPIO_Pin_1
#define TIM3_CH1 GPIO_Pin_6
void Servo_PWM_Init()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体变量
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //开启定时器2
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//通道2时钟使能函数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置GPIO为推挽输出模式
GPIO_InitStructure.GPIO_Pin = TIM2_CH2; //PA1 PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度设置为 50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //按照以上参数进行 GPIO的初始化
TIM_InternalClockConfig(TIM2);//TIM的时基单元由内部时钟控制
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 预分频器的值 对72M(720000000)进行 7200分频 即10K的频率下 计10000个数 1s的时间
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值 CCR
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
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 = 20;//CCR,即占空比为 10%
TIM_OC2Init(TIM2,&TIM_OCInitStructure);//OC编号要与通道编号对应
TIM_Cmd(TIM2,ENABLE);
}
void Motor_PWM_Init()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体变量
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启定时器3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//通道2时钟使能函数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置GPIO为推挽输出模式
GPIO_InitStructure.GPIO_Pin = TIM3_CH1; //PA6
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度设置为 50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //按照以上参数进行 GPIO的初始化
TIM_InternalClockConfig(TIM3); //内部时钟配置
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR 自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC 预分频器的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值 CCR
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
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,即占空比为 10%
TIM_OC1Init(TIM3,&TIM_OCInitStructure);//OC编号要与通道编号对应
TIM_OC2Init(TIM3,&TIM_OCInitStructure);//OC编号要与通道编号对应
TIM_Cmd(TIM3,ENABLE);
}
void PWM_SetCompare_Servo(uint16_t Compare)
{//TIM2_CH2 GPIO_Pin_1
TIM_SetCompare2(TIM2, Compare);
}
void PWM_SetCompare_Motor(uint16_t Compare)
{//TIM3_CH1 GPIO_Pin_6
TIM_SetCompare1(TIM3, Compare);
servo.h
#ifndef __Servo_H
#define __Servo_H
#include "stm32f10x.h" // Device header
void Servo_Init(void);
void Servo_Set_Angle(float Angle);
void Servo_Turn(uint8_t KeyNum);
#endif
servo.c
#include "stm32f10x.h" // Device header
#include "PWM.H"
#include "OLED.h"
float Angle;
void Servo_Init(void)
{
Servo_PWM_Init();
}
void Servo_Set_Angle(float Angle)
{
PWM_SetCompare_Servo(Angle / 180 * 2000 +500);
}
void Servo_Turn(uint8_t KeyNum)
{
//因为我板子上只有1个按键可以用,所以我用这两个引脚模拟按键
if(KeyNum == 1)//PB1
{
Angle = 0;
}
if(KeyNum == 2)//PB11
{
Angle = 180;
}
Servo_Set_Angle(Angle);//执行电机转角
OLED_ShowNum(1,7,Angle,3);
}
motor.h
#ifndef __MOTOR_H
#define __MOTOR_H
#include "stm32f10x.h" // Device header
void Motor_Init();
void Motor_Set_Dir(int8_t Speed);
void Motor_Speed_Set(uint8_t KeyNum);
#endif
motor.c
该功能有用到TB6612FNC电机驱动模块,用PWM来控制 直流电机的转速
#include "stm32f10x.h" // Device header
#include "PWM.h"
#include "Delay.h"
#include "OLED.h"
uint8_t Speed;
void Motor_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//通道2时钟使能函数
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //设置GPIO为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;//电机方向控制脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度设置为 50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //按照以上参数进行 GPIO的初始化
Motor_PWM_Init();
}
void Motor_Set_Dir(int8_t Speed)
{
if(Speed >= 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare_Motor(Speed);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
GPIO_SetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare_Motor(-Speed);
}
}
void Motor_Speed_Set(uint8_t KeyNum)
{
if(KeyNum == 3)
{
Delay_ms(200);
Speed += 20;
if(Speed > 100)
{
Speed = -100;
}
}
OLED_ShowNum(3,7,Speed,3);
OLED_ShowNum(2,8,KeyNum,1);
Motor_Set_Dir(Speed);
}
上一篇:STM32跑马灯实验——库函数版本
下一篇:STM32 PWM周期与频率的计算
推荐阅读最新更新时间:2024-11-12 20:13
设计资源 培训 开发板 精华推荐
- 频率选择、RMS 响应射频检波器,动态范围为 90 dB,从 35 MHz 到 4.4 GHz
- ZSR300GTA 3伏可调正电压调节器的典型应用
- 电源管理PCA9460评估板
- MIC4742 的典型应用:2MHz 双路 2A 集成开关降压稳压器
- 小猫眨眼练习
- LTM4677EY 4 并联的典型应用电路在高达 144A 时产生 1Vout 集成电源系统管理功能可通过 2 线 I2C/SMBus/PMBus 串行接口访问
- SPX-14767,基于 LPS25HB 的 Qwiic 压力传感器开发套件
- SC431L 低压可调并联稳压器的典型应用
- 【涂鸦智能】水浸传感器Plus_Zigbee
- 带有FPC排线座和复位按钮的CH340E串口模块
- Waymo打造最大弱势道路使用者交通事故数据集 可帮助指导自动驾驶系统研发
- 车载显示,大步向前
- 新专利:未来福特汽车或将配备亮度管理系统
- 科学家研发基于AI的身份验证工具 可保护车辆免受网络攻击威胁
- Microchip推出广泛的IGBT 7 功率器件组合,专为可持续发展、电动出行和数据中心应用而设计
- 面向未来驾驶体验 博世推出新型微电子技术
- 英飞凌与马瑞利合作 利用AURIX™ TC4x MCU系列推动区域控制单元创新
- 5C超充,该怎么卷?
- 《2025年度中国汽车十大技术趋势》正式揭晓!你最看好哪个?
- Microchip推出新型VelocityDRIVE™软件平台和车规级多千兆位以太网交换芯片,支持软件定义汽车