本文例子參考《STM32單片機開發實例——基於Proteus虛擬模擬與HAL/LL庫》 源代碼:https://github.com/LanLinnet/STM33F103R6 項目要求 理解H橋電路的工作原理,結合前面幾個項目學習過的PWM、EXTI、串口通訊等,要求通過5個按鈕控制直流電動機的運 ...
本文例子參考《STM32單片機開發實例——基於Proteus虛擬模擬與HAL/LL庫》
源代碼:https://github.com/LanLinnet/STM33F103R6
項目要求
理解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占空比的設定值。