該
智能小車(chē)能夠使用
超聲波測(cè)距并在OLED屏上顯示信息,如果前方物體距離小于10cm蜂鳴器會(huì)發(fā)出警報(bào),可以通過(guò)藍(lán)牙模塊來(lái)控制小車(chē)前進(jìn)、后退、左旋轉(zhuǎn)、右旋轉(zhuǎn),小車(chē)前方的led燈會(huì)根據(jù)是哪個(gè)方向的旋轉(zhuǎn)亮燈,小車(chē)還能進(jìn)行對(duì)電池adc電壓檢測(cè),并在屏幕顯示,藍(lán)牙控制是手機(jī)上到HC的官網(wǎng)下載HC藍(lán)牙助手然后自定義按鈕發(fā)送數(shù)據(jù)到HC_05藍(lán)牙模塊上,利用開(kāi)發(fā)板的串口接收完成對(duì)發(fā)送數(shù)據(jù)的接收,然后做出相應(yīng)動(dòng)作(目前只能完成基本的操作后續(xù)會(huì)對(duì)代碼進(jìn)行改進(jìn))。
第一次的設(shè)計(jì)存在一些錯(cuò)誤,錯(cuò)誤的地方現(xiàn)在已經(jīng)修改,修改如下:一、的蜂鳴器的地接錯(cuò)位置,經(jīng)過(guò)修改后,在原來(lái)的板子上進(jìn)行了飛線處理,經(jīng)過(guò)驗(yàn)證可正常使用。二、原來(lái)板子利用了PA10來(lái)控制電機(jī)芯片,因?yàn)镻A10是下載引腳,會(huì)導(dǎo)致一上電電機(jī)就會(huì)轉(zhuǎn)動(dòng),還會(huì)導(dǎo)致有時(shí)候程序下載不進(jìn)去,則將PA10改成PB6.
# 一、項(xiàng)目簡(jiǎn)介
基于梁山派開(kāi)發(fā)板的藍(lán)牙遙控小車(chē)
# 二、功能介紹
功能:
1.利用藍(lán)牙控制小車(chē),使用的是hc_05模塊,手機(jī)下載hc的官方的控制軟件。
2.OLED屏幕顯示小車(chē)前方物體的距離、前進(jìn)的速度擋位、電池電壓的adc。
3.超聲波避障。
4.蜂鳴器報(bào)警。
5.車(chē)燈在左轉(zhuǎn)和右轉(zhuǎn)分別顯示不同的狀態(tài),并且開(kāi)發(fā)板上的LED會(huì)根據(jù)方向來(lái)進(jìn)行流水燈顯示。
6.按鍵控制小車(chē)前進(jìn)時(shí)的擋位。
# 電路分析
## 1.電源模塊
![QQ截圖20221220103913.png]

利用兩節(jié)18650電池串聯(lián),先經(jīng)過(guò)一個(gè)
穩(wěn)壓二極管進(jìn)行穩(wěn)壓,然后經(jīng)過(guò)開(kāi)關(guān),可輸出為驅(qū)動(dòng)電機(jī)的電壓,然后經(jīng)過(guò)降壓芯片輸出5V的電壓,其中還分別并聯(lián)兩個(gè)鉭電容進(jìn)行濾波。
## 2.蜂鳴器模塊
![QQ截圖20221220105047.png]

當(dāng)BUZZER引腳輸出高電平,蜂鳴器即開(kāi),其中引腳選擇了PB4,可以配置為定時(shí)器輸出,該代碼已配置為定時(shí)器輸出,可通過(guò)改變輸入值來(lái)控制發(fā)出的聲音的頻率。
```
#include "bsp_buzzer.h"
void buzzer_config(void)
{
/* 使能時(shí)鐘 */
rcu_periph_clock_enable(RCU_BUZZER);
/* 配置為輸出模式 復(fù)用模式 */
gpio_mode_set(PORT_BUZZER,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_BUZZER);
/* 配置為推挽輸出 50MHZ */
gpio_output_options_set(PORT_BUZZER,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_BUZZER);
gpio_af_set(PORT_BUZZER,GPIO_AF_2,PIN_BUZZER);//配置GPIO的復(fù)用
}
void buzzer_on(uint16_t speed)
{
gpio_mode_set(PORT_BUZZER,GPIO_MODE_AF,GPIO_PUPD_NONE,PIN_BUZZER); //復(fù)用推挽輸出
timer_channel_output_pulse_value_config(BSP_PWM2_TIMER,BSP_PWM0_CHANNEL_0,speed); // 配置定時(shí)器通道輸出脈沖值
}
```
## 3.按鍵電路
![QQ截圖20221220105838.png]

把key引腳設(shè)置為上拉模式,如果按鍵按下則將引腳電平拉低,該代碼且將開(kāi)發(fā)板上的key引腳一起初始化了,并且能夠在OLED屏上顯示速度的擋位。
```
#include "bsp_key.h"
#include "sys.h"
#include "bsp_led.h"
#include "stdio.h"
void key_gpio_config(void)
{
/*開(kāi)啟GPIO時(shí)鐘*/
rcu_periph_clock_enable(BSP_KEY_RCU);
rcu_periph_clock_enable(RCU_SYSCFG);
rcu_periph_clock_enable(BSP_KEY1_RCU);
/*配置GPIO時(shí)鐘模式*/
gpio_mode_set( BSP_KEY_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, BSP_KEY_PIN);
gpio_mode_set(BSP_KEY1_PORT,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,BSP_KEY1_PIN); // 按鍵默認(rèn)狀態(tài)是高電平,配置為上拉
nvic_irq_enable(BSP_KEY_EXTI_IRQN,3U, 3U);
syscfg_exti_line_config(BSP_KEY_EXTI_PORT_SOURCE,BSP_KEY_EXTI_PIN_SOURCE );
exti_init(BSP_KEY_EXTI_LINE, EXTI_INTERRUPT, EXTI_TRIG_BOTH);
exti_interrupt_enable(BSP_KEY_EXTI_LINE);
exti_interrupt_flag_get(BSP_KEY_EXTI_LINE);
}
void BSP_KEY_EXTI_IRQHANDLER(void) //函數(shù)不需要被調(diào)用, 不占用CPU時(shí)間
{
if(exti_interrupt_flag_get(BSP_KEY_EXTI_LINE)==SET)
{
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
printf("key press!
");
}
else
{
printf("key release!
");
}
exti_interrupt_flag_clear(BSP_KEY_EXTI_LINE);
}
}
void key_scan(void)
{
/*獲取按鍵引腳對(duì)應(yīng)狀態(tài)*/
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
delay_1ms(20);
if(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET)
{
gpio_bit_toggle(PORT_LED0,PIN_LED0);
printf("key press!/r/n");
while(gpio_input_bit_get(BSP_KEY_PORT, BSP_KEY_PIN)==SET);
printf("key release!/r/n");
}
}
}
uint8_t gearshift=1;
uint8_t KEY_Read(void)
{
/* 先讀取按鍵引腳的電平 如果低電平,按鍵按下 */
if(gpio_input_bit_get(BSP_KEY1_PORT,BSP_KEY1_PIN) == RESET) // 按鍵按下
{
delay_1ms(20); // 延遲消抖
if(gpio_input_bit_get(BSP_KEY1_PORT,BSP_KEY1_PIN) == RESET) // 再次檢測(cè)按鍵是否按下
{
gearshift++;
if(gearshift>3)
{
gearshift=1;
}
}
}
return gearshift;
}
void gearshift_show(void)
{
uint16_t a;
a=KEY_Read();
OLED_ShowString(1,3,"speed:",2);
OLED_ShowNum(60,3,a,1,2);
}
```
```
#ifndef _BSP_KEY_H
#define _BSP_KEY_H
#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_oled.h"
#define BSP_KEY_RCU RCU_GPIOA
#define BSP_KEY_PORT GPIOA
#define BSP_KEY_PIN GPIO_PIN_0
#define BSP_KEY1_RCU RCU_GPIOB // 按鍵端口時(shí)鐘
#define BSP_KEY1_PORT GPIOB // 按鍵端口
#define BSP_KEY1_PIN GPIO_PIN_3 // 按鍵引腳
#define BSP_KEY_EXTI_IRQN EXTI0_IRQn
#define BSP_KEY_EXTI_PORT_SOURCE EXTI_SOURCE_GPIOA
#define BSP_KEY_EXTI_PIN_SOURCE EXTI_SOURCE_PIN0
#define BSP_KEY_EXTI_LINE EXTI_0
#define BSP_KEY_EXTI_IRQHANDLER EXTI0_IRQHandler
void key_gpio_config(void);
void key_scan(void);
uint8_t KEY_Read(void);
void gearshift_show(void);
#endif
```
## 4.超聲波測(cè)距
![QQ截圖20221220110715.png]

使用了hc_04模塊,測(cè)出小車(chē)前方物體距離并在OLED屏上顯示。
```
#include "bsp_ultrasonsic.h"
#include "stdio.h"
uint8_t Count_update;
static void ultrasonsic_gpio_config(void) //static只有文件下方可以調(diào)用,其他地方不能使用
{
/*開(kāi)啟GPIOB時(shí)鐘*/
rcu_periph_clock_enable(BSP_ULTRASONSIC_RCU);
/*配置GPIOB時(shí)鐘模式*/
gpio_mode_set( BSP_ULTRASONSIC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BSP_ULTRASONSIC_TRIG_PIN); //浮空輸出
/*配置GPIOB時(shí)鐘輸出*/
gpio_output_options_set(BSP_ULTRASONSIC_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_ULTRASONSIC_TRIG_PIN);//ULTRASONSIC_TRAG推挽輸出
gpio_mode_set( BSP_ULTRASONSIC_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, BSP_ULTRASONSIC_ECHO_PIN); //下拉輸入
gpio_bit_write(BSP_ULTRASONSIC_PORT,BSP_ULTRASONSIC_TRIG_PIN,RESET);//TRAG初始狀態(tài)為低電平
}
static void Ultras_TIM2_Init(uint16_t pre,uint16_t per)
{
timer_parameter_struct timere_initpara;
rcu_periph_clock_enable(BSP_ULTRASONSIC_TIMER_RCU);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_deinit(BSP_ULTRASONSIC);
timere_initpara.prescaler =pre-1; /*!< prescaler value */
timere_initpara.alignedmode =TIMER_COUNTER_EDGE; /*!< aligned mode */
timere_initpara.counterdirection=TIMER_COUNTER_UP; /*!< counter direction */
timere_initpara.clockdivision =TIMER_CKDIV_DIV1; /*!< clock division value */
timere_initpara.period =per-1; /*!< period value */
timere_initpara.repetitioncounter=0;
timer_init(BSP_ULTRASONSIC, &timere_initpara);
nvic_irq_enable(BSP_ULTRASONSIC_IRQ,3U, 2U);
timer_interrupt_enable(BSP_ULTRASONSIC,TIMER_INT_UP);
//timer_enable(BSP_ULTRASONSIC);
timer_interrupt_flag_clear(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP); //清除更新中斷,免得一打開(kāi)中斷立即產(chǎn)生中斷
timer_break_enable(BSP_ULTRASONSIC); //打開(kāi)定時(shí)器更新中斷
timer_disable(BSP_ULTRASONSIC);
}
void Ultrasonic_Init(void)
{
ultrasonsic_gpio_config();
Ultras_TIM2_Init(200,1000); //1ms
}
void BSP_ULTRASONSIC_IRAHANDLER(void) //
定時(shí)器中斷,每1ms count+1
{
if(timer_interrupt_flag_get(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP)==SET)
{
timer_interrupt_flag_clear(BSP_ULTRASONSIC,TIMER_INT_FLAG_UP);
Count_update++;
}
}
static void timer_open(void) //打開(kāi)定時(shí)器
{
Count_update = 0;
timer_counter_value_config(BSP_ULTRASONSIC, 0);
timer_enable(BSP_ULTRASONSIC);//使能定時(shí)器
}
static void timer_close(void) //關(guān)閉定時(shí)器
{
timer_disable(BSP_ULTRASONSIC);
}
uint32_t GetEchoTimer(void)
{
uint32_t time= 0;
/*//當(dāng)回響信號(hào)很長(zhǎng)是,計(jì)數(shù)值溢出后重復(fù)計(jì)數(shù),overCount用中斷來(lái)保存溢出次數(shù)*/
time = Count_update*1000;//overCount每++一次,代表overCount毫秒,time微妙
time+=timer_counter_read(BSP_ULTRASONSIC);//獲取計(jì)TIM2數(shù)寄存器中的計(jì)數(shù)值,一邊計(jì)算回響信號(hào)時(shí)間
timer_counter_value_config(BSP_ULTRASONSIC,0); //將TIM2計(jì)數(shù)寄存器的計(jì)數(shù)值清零
delay_1ms(50);
return time;
}
float Hcsr04GetLength(void )
{
/*測(cè)5次數(shù)據(jù)計(jì)算一次平均值*/
float length = 0;
float t = 0;
float sum = 0;
uint16_t i = 0;
while(i != 5){
TRIG=1;
delay_1us(20);//持續(xù)時(shí)間超過(guò)10us
TRIG=0;
/*Echo發(fā)出信號(hào) 等待回響信號(hào)*/
/*輸入方波后,模塊會(huì)自動(dòng)發(fā)射8個(gè)40KHz的聲波,與此同時(shí)回波引腳(echo)端的電平會(huì)由0變?yōu)?;
(此時(shí)應(yīng)該啟動(dòng)定時(shí)器計(jì)時(shí));當(dāng)超聲波返回被模塊接收到時(shí),回波引 腳端的電平會(huì)由1變?yōu)?;
(此時(shí)應(yīng)該停止定時(shí)器計(jì)數(shù)),定時(shí)器記下的這個(gè)時(shí)間即為
超聲波由發(fā)射到返回的總時(shí)長(zhǎng);*/
while(ECHO == 0);//echo等待回響
/*開(kāi)啟定時(shí)器*/
timer_open();
i = i+1; //每收到一次回響信號(hào)+1,收到5次就計(jì)算均值
while(ECHO == 1);
/*關(guān)閉定時(shí)器*/
timer_close();
/*獲取Echo高電平時(shí)間時(shí)間*/
t = GetEchoTimer();
length = (float)t/58;//單位時(shí)cm
sum += length;
}
length = sum/5;//五次平均值
return length;
}
int a,b,c,d,e,f,g,h=0;
void bsp_distance_oled(void)
{
d=Hcsr04GetLength();
a=d/100;
b=(d%100)/10;
c=(d%10);
OLED_Clear();
OLED_ShowString(1,2,"distance:",3);
OLED_ShowNum(80,2,a,1,3);
OLED_ShowNum(86,2,b,1,3);
OLED_ShowNum(92,2,c,1,3);
}
```
```
#include "bsp_oled.h"
#define BSP_ULTRASONSIC_RCU RCU_GPIOD
#define BSP_ULTRASONSIC_PORT GPIOD
#define BSP_ULTRASONSIC_TRIG_PIN GPIO_PIN_1
#define BSP_ULTRASONSIC_ECHO_PIN GPIO_PIN_5
#define BSP_ULTRASONSIC_TIMER_RCU RCU_TIMER4
#define BSP_ULTRASONSIC TIMER4
#define BSP_ULTRASONSIC_IRQ TIMER4_IRQn
#define BSP_ULTRASONSIC_IRAHANDLER TIMER4_IRQHandler
#define TRIG PDout(1)
#define ECHO PDin(5)
void Ultrasonic_Init(void);
void BSP_ULTRASONSIC_IRAHANDLER(void);
void Ultrasonic_Init(void);
uint32_t GetEchoTimer(void);
float HCSR04_Get_Distance(void);
float Hcsr04GetLength(void );
void bsp_distance_oled(void);
#endif
```
## 5.藍(lán)牙模塊
使用了hc_05模塊。
![QQ截圖20221220112426.png]

```
#include "bsp_hc.h"
#include "stdio.h"
uint8_t g_recv_buff_hc[USART_RECEIVE_LENGTH]; // 接收緩沖區(qū)
uint16_t g_recv_length_hc = 0; // 接收數(shù)據(jù)長(zhǎng)度
uint8_t g_recv_complete_flag_hc = 0; // 接收數(shù)據(jù)完成標(biāo)志位
void uart6_gpio_config(uint32_t band_rate)
{
/* 開(kāi)啟時(shí)鐘 */
rcu_periph_clock_enable(BSP_UART6_TX_RCU); // 開(kāi)啟串口時(shí)鐘
rcu_periph_clock_enable(BSP_UART6_RX_RCU); // 開(kāi)啟端口時(shí)鐘
rcu_periph_clock_enable(BSP_UART6_RCU); // 開(kāi)啟端口時(shí)鐘
/* 配置GPIO復(fù)用功能 */
gpio_af_set(BSP_UART6_TX_PORT,BSP_UART6_AF,BSP_UART6_TX_PIN);
gpio_af_set(BSP_UART6_RX_PORT,BSP_UART6_AF,BSP_UART6_RX_PIN);
/* 配置GPIO的模式 */
/* 配置TX為復(fù)用模式 上拉模式 */
gpio_mode_set(BSP_UART6_TX_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_UART6_TX_PIN);
/* 配置RX為復(fù)用模式 上拉模式 */
gpio_mode_set(BSP_UART6_RX_PORT, GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_UART6_RX_PIN);
/* 配置TX為推挽輸出 50MHZ */
gpio_output_options_set(BSP_UART6_TX_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_UART6_TX_PIN);
/* 配置RX為推挽輸出 50MHZ */
gpio_output_options_set(BSP_UART6_RX_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_UART6_RX_PIN);
/* 配置串口的參數(shù) */
usart_deinit(BSP_UART6); // 復(fù)位串口
usart_baudrate_set(BSP_UART6,band_rate); // 設(shè)置波特率
usart_parity_config(BSP_UART6,USART_PM_NONE); // 沒(méi)有校驗(yàn)位
usart_word_length_set(BSP_UART6,USART_WL_8BIT); // 8位數(shù)據(jù)位
usart_stop_bit_set(BSP_UART6,USART_STB_1BIT); // 1位停止位
/* 使能串口 */
usart_enable(BSP_UART6); // 使能串口
usart_transmit_config(BSP_UART6,USART_TRANSMIT_ENABLE); // 使能串口發(fā)送
usart_receive_config(BSP_UART6,USART_RECEIVE_ENABLE); // 使能串口接收
/* 中斷配置 */
nvic_irq_enable(BSP_UART6_IRQ, 2, 2); // 配置中斷優(yōu)先級(jí)
usart_interrupt_enable(BSP_UART6,USART_INT_RBNE); // 讀數(shù)據(jù)緩沖區(qū)非空中斷和溢出錯(cuò)誤中斷
usart_interrupt_enable(BSP_UART6,USART_INT_IDLE); // 空閑檢測(cè)中斷
}
void BSP_UART6_IRQHandler(void)
{
if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_RBNE) == SET) // 接收緩沖區(qū)不為空
{
g_recv_buff_hc[g_recv_length_hc++] = usart_data_receive(BSP_UART6); // 把接收到的數(shù)據(jù)放到緩沖區(qū)中
}
if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_IDLE) == SET) // 檢測(cè)到幀中斷
{
usart_data_receive(BSP_UART6); // 必須要讀,讀出來(lái)的值不能要
g_recv_buff_hc[g_recv_length_hc] = '
主站蜘蛛池模板:
乐清市|
思茅市|
砀山县|
琼中|
镇坪县|
宣化县|
井陉县|
景德镇市|
陕西省|
永昌县|
武安市|
托克逊县|
玉屏|
凤凰县|
福贡县|
凤凰县|
兴城市|
太原市|
龙泉市|
华容县|
安远县|
宝应县|
扶风县|
九龙县|
德兴市|
北辰区|
双桥区|
荆州市|
慈利县|
寻甸|
视频|
黄陵县|
昌平区|
益阳市|
金秀|
永德县|
伊通|
武宁县|
板桥市|
横峰县|
河津市|