19-CubeMx+Keil+Proteus仿真STM32 - 直流电动机
本文例子参考《STM32单片机开发实例——基于Proteus虚拟仿真与HAL/LL库》
源代码:https://github.com/LanLinnet/STM32F103R6
项目要求
理解H桥电路的工作原理,结合前面几个项目学习过的PWM、EXTI、串口通讯等,要求通过5个按钮控制直流电动机的运行状态,包括:电动机正转、电动机反转、电动机停止、电动机加速和电动机减速,其中电动机加速/减速以10%的PWM信号宽度占空比为递增/递减量。
硬件设计
-
在第一节的基础上,在Proteus中添加电路如下图所示。其中我们添加了一个直流电动机H桥芯片
L298
,一个直流电动机MOTOR-DC
。
此外,我们还添加了一个虚拟仪表:虚拟终端VIRTUAL TERMINAL
,将其波特率设置为19200bits/s。 -
直流电动机和H桥电路:直流电动机是一种常见的动力源,很多情况下需要用直流电动机带动执行机构做各种复杂动作。直流电动机与H桥电路如下图所示。
- 当开关A、D闭合时,电动机左侧接通驱动电源正极,右侧接通驱动电源负极,直流电动机正转;
- 当开关B、C闭合时,电动机左侧接通驱动电源负极,右侧接通驱动电源正极,直流电动机反转;
- 当只有开关A、C闭合或只有开关B、D闭合时,电动机左、右侧短路,直流电动机能耗制动,对于某些大功率直流电动机,还需要在短路回路中串联制动电阻,防止能耗制动过程中电流过大。
-
双H桥芯片L298:
1)简介:L298是意法半导体公司出品的双H桥芯片,片内集成2个独立的H桥,可同时驱动2个最大电压为46V、最大电流为2A的直流电动机。
2)引脚:L298控制信号为5VTTL电平,驱动电压为5-46V,故在使用STM32控制时应当选用具备“FT”特性的GPIO引脚,并将引脚设为开漏输出模式,同时外接上拉电阻到5V电源正极。控制电路由VSS供电,驱动电路由VS供电,芯片引脚和常用电路如下图所示。
- ENx:H桥A/B的使能引脚,高电平有效,往往与PWM信号相连,用于调节H桥A/B控制的直流电动机转速。
- ISENx:H桥A/B的驱动检测引脚,用于进行过流检测,并将检测结果反馈给控制器以形成闭环控制,一般不用,可直接接地。
- IN1-IN4:方向控制信号输入端,其中IN1、IN2控制H桥A,其中IN3、IN4控制H桥B,具体如下表所示。
- OUT1-OUT4:2个H桥的输出端,用来连接2个直流电动机,其中OUT1、OUT2用来连接Motor1,OUT3、OUT4用来连接Motor2。
- D1-D8:8个整流二极管,由于直流电动机为感性负载,为了避免L298在电动机转换方向时受到反向电流的冲击,加入整流二极管进行泄流。
-
打开CubeMX,建立工程。这一项目有很多设置都与前面涉及的项目相似,若不熟悉可以进行回顾。
-
点击“Generator Code”生成Keil工程。
软件编写
点击“Open Project”在Keil中打开工程,打开“main.c”,添加代码如下。
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h" //引入标准输入输出库头文件
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
uint16_t cmpv = 80; //捕获比较值,即CRR2的设定值
uint8_t rf = 0; //中断标志位
/* USER CODE END PV */
/* USER CODE BEGIN 1 */
char str[4]; //用于存放CRR2值转换的字符串
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); //定时器3运行并在通道2输出PWM函数
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, cmpv); //给定时器3设定通道2的捕获比较寄存器值(CRR2)
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
if(rf == 1)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&"PWM:", 4, 4); //串口发送字符串(PWM比较寄存器值,值越大转速越快)
sprintf(str, "%d", cmpv);
HAL_UART_Transmit(&huart1, (uint8_t *)str, 3, 3);
HAL_UART_Transmit(&huart1, (uint8_t *)&"\n\r", 2, 2);
rf = 0; //标志位清零
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
//外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0) //正转按钮
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
rf = 1;
}
else if(GPIO_Pin == GPIO_PIN_1) //反转按钮
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);
rf = 1;
}
else if(GPIO_Pin == GPIO_PIN_2) //停止按钮
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET);
}
else if(GPIO_Pin == GPIO_PIN_3) //加速按钮(增加PWM信号波形占空比)
{
if(cmpv<100) cmpv+=10;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, cmpv); //给定时器3设定通道2的捕获比较寄存器值(CRR2)
rf = 1;
}
else if(GPIO_Pin == GPIO_PIN_4) //减速按钮(减小PWM信号波形占空比)
{
if(cmpv>0) cmpv-=10;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, cmpv); //给定时器3设定通道2的捕获比较寄存器值(CRR2)
rf = 1;
}
}
/* USER CODE END 4 */
联合调试
- 点击运行,生成HEX文件。
- 在Proteus中加载相应HEX文件,点击运行。按下不同的按键,可以看到电动机转速的变化,并且在虚拟终端中可以看到PWM占空比的设定值。