👨?💻個人主頁:@開發者-削好皮的Pineapple!
👨?💻 hello 歡迎 點贊👍 收藏? 留言📝 加關注?!
👨?💻 本文由 削好皮的Pineapple! 原創
👨?💻 收錄于專欄:C語言到基于STM32 的智能礦探小車
文章目錄
- ?前言?
- 🎶一、模塊化編程思維
- 🎶二、直流電機
- 2.1 電機驅動模塊
- 🎶三、小車運動控制代碼實現
- 3.1 小車控制函數(`car.c`/`car.h`)
- 3.2 程序下載與運行設置
- 3.3 速度控制
- 結束語🥇
?前言?
今天是實習培訓的新一天,學習聚焦于模塊化編程思維以及直流電機控制相關知識,包括電機驅動模塊的使用、小車運動控制代碼的實現以及PWM技術在速度調節中的應用,為后續智能礦探小車的開發進一步夯實基礎。
🎶一、模塊化編程思維
模塊化編程是按照不同功能將程序拆分為對應的源文件(.c)和頭文件(.h),以提高代碼的可維護性和復用性。
- 源文件(.c):用于保存函數接口的具體實現。
例如led.c
:void led_init(void) {// 初始化LED的具體代碼 } void led_ctrl(...) {// 控制LED的具體代碼 }
#include "led.h"
#include "stm32f4xx.h"void LED_Init(void)
{// 使能GPIOF和GPIOE外設時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOE, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;// 配置GPIOF的LED引腳(D1、D2)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_Init(GPIOF, &GPIO_InitStruct);// 配置GPIOE的LED引腳(D3、D4)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;GPIO_Init(GPIOE, &GPIO_InitStruct);// 默認關閉所有LEDGPIO_SetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10);GPIO_SetBits(GPIOE, GPIO_Pin_13 | GPIO_Pin_14);
}void LED_Control(LEDNUM led_num, LEDSTA state)
{switch(led_num){case LED_D1:if(state == LED_ON)GPIO_ResetBits(GPIOF, GPIO_Pin_9);elseGPIO_SetBits(GPIOF, GPIO_Pin_9);break;case LED_D2:if(state == LED_ON)GPIO_ResetBits(GPIOF, GPIO_Pin_10);elseGPIO_SetBits(GPIOF, GPIO_Pin_10);break;case LED_D3:if(state == LED_ON)GPIO_ResetBits(GPIOE, GPIO_Pin_13);elseGPIO_SetBits(GPIOE, GPIO_Pin_13);break;case LED_D4:if(state == LED_ON)GPIO_ResetBits(GPIOE, GPIO_Pin_14);elseGPIO_SetBits(GPIOE, GPIO_Pin_14);break;}
}
- 頭文件(.h):用于保存函數聲明、構造類型定義、全局變量聲明等,且需添加防止重復包含的預處理指令。
例如led.h
:#ifndef _LED_H // 如果未定義_LED_H #define _LED_H // 定義_LED_H,防止頭文件重復包含// 函數聲明 void led_init(void); void led_ctrl(...);// 全局變量聲明 // 構造類型定義#endif
#ifndef _LED_H
#define _LED_H#include <stdint.h> // 添加此頭文件以使用uint8_ttypedef enum {LED_D1,LED_D2,LED_D3,LED_D4
} LEDNUM;typedef enum {LED_OFF,LED_ON
} LEDSTA;void LED_Init(void);
void LED_Control(LEDNUM led_num, LEDSTA state);#endif
- 常見模塊示例:
delay.c
/delay.h
:實現延時功能,如void delay_ms(uint16_t nms);
(毫秒級延時)、void delay_us(uint16_t us);
(微秒級延時)。
🎶二、直流電機
2.1 電機驅動模塊
-
接線說明:
-
兩個綠色端子:直接連接直流電機。
-
6個排針:
VCC
:接5V或3.3V(5V驅動時小車力度大,狀態改變較難;3.3V驅動時力度小,狀態改變相對容易)。GND
:接GND(注意正負極不可接反)。- 控制引腳:
B-1A
、B-1B
用于控制一個電機,A-1A
、A-1B
用于控制另一個電機,具體對應哪個電機需看實物綠色端子的連接。以下是本次實訓所用驅動電路板。
引腳依次是:B-1A、B-1B、GND、VCC、A-1A、A-1B
-
-
電機轉動原理:直流電機由兩個引腳驅動,當兩個引腳電平狀態不同時電機轉動。
- 假設
B-1A
為高電平、B-1B
為低電平時,電機向前轉動;則B-1A
為低電平、B-1B
為高電平時,電機向后轉動。 - 當
B-1A
和B-1B
均為低電平或均為高電平時,電機停止轉動。
- 假設
-
可用GPIO引腳:在CAMERA處有部分GPIO引腳可用于連接控制,如2腳(GND)、4腳(PD6)、6腳、8腳、10腳…1腳(3V3)、3腳(PB7)、5腳、7腳、9腳…根據原理圖(GEC-M4原理圖2016-07-29.pdf)可得:
🎶三、小車運動控制代碼實現
3.1 小車控制函數(car.c
/car.h
)
- 小車初始化函數:
void car_Init(void)
{//1.時鐘使能RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD , ENABLE);//2.初始化GPIO ---> 推挽輸出模式 GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_Init(GPIOD, &GPIO_InitStruct);// 配置GPIOE的LED引腳GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7| GPIO_Pin_6;GPIO_Init(GPIOB, &GPIO_InitStruct);//3.默認狀態:小車停止GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);//左GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//右
}
- 基本運動控制函數:
- 前進:
int speed = 100;
void car_up(void)
{//左輪電機前轉GPIO_ResetBits(GPIOD, GPIO_Pin_6 );//A-1BGPIO_SetBits(GPIOD, GPIO_Pin_7 );// A-1A//右輪電機前轉GPIO_ResetBits(GPIOB, GPIO_Pin_6 );//B-1AGPIO_SetBits(GPIOB, GPIO_Pin_7 );//B-1Bdelay_ms(speed);GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//右delay_ms(100-speed);
}
- 后退:
void car_back(void)
{//左輪電機后轉GPIO_ResetBits(GPIOD, GPIO_Pin_7 );GPIO_SetBits(GPIOD, GPIO_Pin_6 ); //右輪電機后轉GPIO_ResetBits(GPIOB, GPIO_Pin_7 );GPIO_SetBits(GPIOB, GPIO_Pin_6 );
}
- 左轉:
void car_left(void)
{//左輪不轉 (后轉)GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);//右輪前進GPIO_ResetBits(GPIOB, GPIO_Pin_6 );GPIO_SetBits(GPIOB, GPIO_Pin_7 );
}
- 右轉:
void car_right(void)
{//右輪不轉 (后轉)GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//左輪前進GPIO_ResetBits(GPIOD, GPIO_Pin_6 );GPIO_SetBits(GPIOD, GPIO_Pin_7 );
}
- 停止:
void car_stop(void)
{//右輪和左輪子都不轉GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);
}
3.2 程序下載與運行設置
- 下載程序時:
BOOT0
接3V3,BOOT1
接GND,按下復位鍵,CPU執行引導程序,程序可下載到開發板。 - 下載完成后:
BOOT0
接GND,BOOT1
接GND,重新上電或按復位鍵,程序重新運行。
3.3 速度控制
-
簡單速度調節(上面已經實現):通過控制電機轉動與停止的時間比例來調節速度。
int speed = 100; void car_up(void) {// 左輪電機前轉// 右輪電機前轉(右輪速度調節)B-1A = 1;B-1B = 0; // 右輪轉動delay_ms(speed);B-1B = 1; // 右輪停止轉動delay_ms(100 - speed); }
-
PWM(脈沖寬度調制):通過調節有效電平時間與整個周期的比例(占空比)來精確控制電機轉速、蜂鳴器鳴叫等。
- 占空比 = 有效電平時間 / 整個周期。
- 例如:有效電平時間50ms,周期100ms,占空比為50%。
- 注意:使用PWM調節的周期不能太長。
-
主函數示例:
int main() {while(1){car_up(); // 小車前進} }
-
練習目標:調節小車輪子速度,使小車前進1m左右。
結束語🥇
🔥 訂閱專欄持續學習:C語言到基于STM32的智能礦探小車
💬 歡迎點贊、收藏、留言討論,一起攻克嵌入式開發!