一、简介
本文主要介绍了运用STM32实现可视化风扇的过程。由于使用HAL库编程,其中需要用到的软件有STM32CubeMX和Keil5。本项目的实现需要中断系统和定时器的相关知识基础,并应用外部中断及PWM输出功能。同时本文也涉及到字模软件Pctolcd2002的简单使用,可借此进一步了解OLED屏作为显示模块的实际工作原理。
二、项目要求描述
设计一款可视风扇,要求如下:
- 按下按键1,风扇转速为低速,同时,LED灯出现流水效果1,OLED屏幕显示“风速:低速(及对应占空比)”;
- 按下按键2,风扇转速为中速,同时,LED灯出现流水效果2,OLED屏幕显示“风速:中速(及对应占空比)”;
- 按下按键3,风扇转速为低速,同时,LED灯出现流水效果3,OLED屏幕显示“风速:高速(及对应占空比)”。
三、 外设设置
1、引脚分配
本项目所包含的电子元件:STM32F103ZET6,L9110S(直流电机),板载LED灯,OLED屏。
开关 | K1 | PE2 |
K2 | PE3 | |
K3 | PE4 | |
K4 | PA0 | |
电机 | VCC | 5V |
GND | GND | |
A | PA15 | |
B | PC13 | |
LED灯 | LD1 | PC0 |
LD2 | PC1 | |
LD3 | PC2 | |
LD4 | PC3 | |
OLED屏 | VCC | 3.3V |
GND | GND | |
SCL | PB10 | |
SDA | PB11 |
2、按键开关
1)GPIO:将四个按键K1——K4引脚模式设置为外部中断EXTI,均为上升沿触发。K4初始引脚拉低,其余中断引脚拉高,在CubeMX中相应引脚的配置如图所示。
2)NVIC:将四个按键的中断使能全部勾选。不设置中断优先级,而是使用默认的中断优先级。
3、风扇电机
1)GPIO:启用定时器2的CH1通道,可给PA0或PA15配置PWM输出功能。由于PA0用作按键K4的输出引脚,故将PA15配置位复用推挽输出引脚,输出PWM波。PC13配置为通用推挽,置低电平。
2)PWM信号周期及占空比的计算公式:
T=(PSC+1)*(ARR+1)/TIMx_CLK ···式一
Duty=CCR/(ARR+1)*100% ··········式二
定时器2的定时时钟TIM2_CLK为72MHZ,若设PWM信号的周期为10ms,根据式一可以设置预分频系数PSC为7199,自动重载值为99。同时,根据式二,将占空比Duty设为0,即写入捕获/比较寄存器CCR的初值为0,方便在程序编写中使用__HAL_TIM_SET_COMPARE()修改占空比的值,从而实现风扇档位的切换。
4、板载LED灯
GPIO:将四个LED灯LD1——LD4的引脚模式设为推挽输出,初始电平置高。
5、OLED屏
1)GPIO:将I2C2通道打开,可知PB10为对应通道SCL引脚,PB11为对应通道SDA引脚,硬件对应接线即可。
2)字模提取:在PCtoLCD2002完美版的字符模式中单击选项,打开字模选项,选择C51格式,点击确定。把项目要求中在oled屏上需要显示的汉字打在输入框中,点击生成字模。
3)MDK工程:将生成的字模复制,并粘贴替换在Keil中oledfont.h里汉字库数组里的内容。
四、程序编写
1、编写思路
1)按键开关:设置外部中断,运用三个按键实现切换风扇的不同档位,一个按键留作复位(关闭),符合日常风扇的工作运转。
2)风扇电机:初始和复位状态下,A引脚PWM占空比为0,B引脚置低电平,双LOW状态实现了风扇的停止;在实际代码编写中,通过改变占空比的值,不同程度地给A引脚置高电平,从而实现了正转调速。
3)板载LED灯:通过按键消除标志位的方法,实现了切换不同流水灯的效果。
4)OLED屏:作为显示模块,将项目要求中相应的汉字及字符串分别通过不同按键实现,达到可视化的效果。
2、程序代码
生成MDK工程后,进行应用程序的编写。由于篇幅有限,这里重点把用户添加或修改的代码列举出来。具体代码如下图程序清单所示。
/* Includes ------------------------------------------------------------------*/
#include "main.h" //引入库函数
#include "i2c.h"
#include "tim.h"
#include "gpio.h"
#include "oled.h"
/* USER CODE BEGIN PV */
volatile unsigned char ET=0; //设立标志位,初值置0
/* USER CODE END PV */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_I2C2_Init();
OLED_Init();
OLED_Clear();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); //将定时器2的通道一打开
HAL_GPIO_WritePin(GPIOC,B_Pin,GPIO_PIN_RESET); //将电机的B引脚置低电平
OLED_ShowCHinese(0,2,6); //初始状态下,oled屏上显示“Duty=0% 小朱可视风扇”
OLED_ShowCHinese(16,2,7);
OLED_ShowCHinese(32,2,8);
OLED_ShowCHinese(48,2,9);
OLED_ShowCHinese(64,2,0);
OLED_ShowCHinese(80,2,10);
OLED_ShowString(0,0,"Duty:0%",sizeof("Duty:0%"));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) //主函数
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(ET==0) //如果标志位置0,所有灯均为熄灭状态
{
HAL_GPIO_WritePin(GPIOC,LD1_Pin|LD2_Pin|LD3_Pin|LD4_Pin,GPIO_PIN_SET);
}
else if(ET==1) //如果标志位置1,前两灯为流水灯状态
{
HAL_GPIO_TogglePin(GPIOC,LD1_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD2_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD1_Pin|LD2_Pin);
HAL_Delay(500);
}
else if(ET==2) //如果标志位置2,前三灯为流水灯状态
{
HAL_GPIO_TogglePin(GPIOC,LD1_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD2_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD3_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD1_Pin|LD2_Pin|LD3_Pin);
HAL_Delay(500);
}
else if(ET==3) //如果标志位置3,前四灯为流水灯状态
{
HAL_GPIO_TogglePin(GPIOC,LD1_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD2_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD3_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD4_Pin);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC,LD1_Pin|LD2_Pin|LD3_Pin|LD4_Pin);
HAL_Delay(500);
}
}
/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //中断函数
{
switch(GPIO_Pin)
{
case K1_Pin: //按下按键1,oled屏显示“Duty:30% 风速:低速”
OLED_Clear();
OLED_ShowCHinese(0,2,0);
OLED_ShowCHinese(16,2,1);
OLED_ShowCHinese(32,2,2);
OLED_ShowCHinese(48,2,3);
OLED_ShowCHinese(64,2,1);
OLED_ShowString(0,0,"Duty:30%",sizeof("Duty:30%"));
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,30); //修改电机占空比为30%
ET=1; //标志位置1
break;
case K2_Pin: //按下按键2,oled屏显示“Duty:60% 风速:中速”
OLED_Clear();
OLED_ShowCHinese(0,2,0);
OLED_ShowCHinese(16,2,1);
OLED_ShowCHinese(32,2,2);
OLED_ShowCHinese(48,2,4);
OLED_ShowCHinese(64,2,1);
OLED_ShowString(0,0,"Duty:60%",sizeof("Duty:60%"));
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,60); //修改电机占空比为60%
ET=2; //标志位置2
break;
case K3_Pin: //按下按键3,oled屏显示“Duty:90% 风速:高速”
OLED_Clear();
OLED_ShowCHinese(0,2,0);
OLED_ShowCHinese(16,2,1);
OLED_ShowCHinese(32,2,2);
OLED_ShowCHinese(48,2,5);
OLED_ShowCHinese(64,2,1);
OLED_ShowString(0,0,"Duty:90%",sizeof("Duty:90%"));
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,90); //修改电机占空比为90%
ET=3; //标志位置3
break;
case K4_Pin: //按下按键4,oled屏显示“Duty:0% 小朱可视风扇”
OLED_Clear();
OLED_ShowCHinese(0,2,6);
OLED_ShowCHinese(16,2,7);
OLED_ShowCHinese(32,2,8);
OLED_ShowCHinese(48,2,9);
OLED_ShowCHinese(64,2,0);
OLED_ShowCHinese(80,2,10);
OLED_ShowString(0,0,"Duty:0%",sizeof("Duty:0%"));
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0); //修改电机占空比为0%
ET=0; //标志位置0
break;
}
}
/* USER CODE END 4 */
文章来源地址https://www.toymoban.com/news/detail-844770.html
文章来源:https://www.toymoban.com/news/detail-844770.html
到了这里,关于STM32 可视化风扇(按键+电机+LED灯+OLED屏)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!