? ?畢設(shè)做的是掌控小車,因此采用藍(lán)牙通信作為小車和手部通信,前段時(shí)間做出實(shí)物,對其遇到的問題以及解決的方法做一些總結(jié)。一個(gè)主控芯片采用STM32F103ZET6,另一個(gè)主控芯片采用STM32F103C8T6,原因是本來準(zhǔn)備了兩個(gè)主控C8T6,不小心燒了一個(gè)。
1.兩個(gè)藍(lán)牙的配對
?需要準(zhǔn)備的硬件:
2個(gè)HC-05主從一體,2個(gè)USB轉(zhuǎn)TTL,杜邦線若干,USB拓展口(電腦USB口較少的)
AT指令集(在藍(lán)牙模塊進(jìn)入AT指令模式后,需要在串口助手上發(fā)送AT指令):
對于HC-05這款藍(lán)牙模塊,其上有一個(gè)黑色的小按鈕,在通電之前長按,插入電腦USB口后,原本快閃紅燈變?yōu)槁W后,即進(jìn)入AT模式,此時(shí)可以在串口助手上發(fā)送AT指令。每發(fā)送一條AT指令后,串口助手會回饋一個(gè)OK或者其他,證明可以正常使用,若不能回復(fù)OK,大概有以下問題:
(1)檢查連線,是否RXD連接的TXD,是否杜邦線連接正確。
(2)檢查波特率是否正確,默認(rèn)的波特率是38400
以下為兩個(gè)藍(lán)牙模塊配對的過程:
?1.初始化藍(lán)牙模塊(需要開啟兩個(gè)串口助手對主從機(jī)進(jìn)行配置,此處A為主機(jī),B為從機(jī))
藍(lán)牙模塊A的配置
AT+ORGL ? ? ? ?
初始化藍(lán)牙模塊(當(dāng)使用了此條AT指令后,自動退出AT模式,需重新進(jìn)入AT模式)
AT+PSWD="xxxx" ?
設(shè)置藍(lán)牙配對密碼(其中xxxx代表任意數(shù)字,主機(jī)從機(jī)的密碼要一致)
AT+ROLE=1 ? ? ?
設(shè)置藍(lán)牙模塊A為主機(jī) (1代表主機(jī),0代表從機(jī))
藍(lán)牙模塊B的配置
AT+ORGL ? ? ? ?
初始化藍(lán)牙模塊(當(dāng)使用了此條AT指令后,自動退出AT模式,需重新進(jìn)入AT模式)
AT+PSWD="xxxx" ?
設(shè)置藍(lán)牙配對密碼(其中xxxx代表任意數(shù)字,主機(jī)從機(jī)的密碼要一致)
AT+ROLE=0 ? ? ?
設(shè)置藍(lán)牙模塊A為主機(jī) (1代表主機(jī),0代表從機(jī))
2.查詢從機(jī)地址并綁定
AT+ADDR? ? ? ?
對從機(jī)進(jìn)行地址查詢,獲得查詢地址,我使用從機(jī)獲得的的地址0022:12:0205FC
將獲得的地址其中的冒號換成逗號即0022,12,0205FC
注意:在AT指令中所有的標(biāo)點(diǎn)均為英文輸入法下的
AT+BIND=0022,12,0205FC
?
在主機(jī)的串口助手窗口發(fā)送,使主機(jī)綁定從機(jī)地址
AT+BIND? ? ? ? ?
查看主機(jī)是否成功綁定從機(jī)地址
3.設(shè)置主機(jī)從機(jī)的波特率
AT+UART=115200,0,0 ? ?
設(shè)置主機(jī)的波特率為115200
AT+UART??? ??? ? ? ?
查詢主機(jī)波特率是否為115200
AT+UART=115200,0,0 ? ?
設(shè)置從機(jī)的波特率為115200
AT+UART??? ??? ? ? ?
查詢從機(jī)波特率是否為115200
配置完成后,拔出再重新通電,此時(shí)不用按住黑色小按鈕,待兩個(gè)藍(lán)牙模塊的紅燈均變?yōu)槁W時(shí),即配對成功,此時(shí)在主機(jī)的串口助手上發(fā)送數(shù)字,在從機(jī)的串口助手上可以接收到,即實(shí)現(xiàn)了兩個(gè)藍(lán)牙模塊的通信。
2.單片機(jī)的配置(僅為部分配置代碼)
? 根據(jù)上述兩個(gè)藍(lán)牙之間的通信,不難推斷藍(lán)牙通信就是無線的串口通信,STM32單片機(jī)配置時(shí)應(yīng)注意配置兩個(gè)單片機(jī)的串口,要有和藍(lán)牙相同的波特率,同時(shí)將藍(lán)牙連接至配置好的單片機(jī)所用的串口(RXD,TXD)上
我在小車上的串口配置,使用串口3
#include "usart3.h"
#include "sys.h"
#include "usart.h"
#include "tb6612.h"
#include "timer.h"
uint8_t Serial_RxFlag;
extern int USART3_Flag;
uint16_t R_Data;
void usart3_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructurea;
USART_InitTypeDef USART_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //
USART_DeInit(USART3);//
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure); //PB10
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_Init(GPIOB,&GPIO_InitStructure); //PB11
NVIC_InitStructurea.NVIC_IRQChannel=USART3_IRQn;
NVIC_InitStructurea.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructurea.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructurea.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructurea); //
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//
USART_InitStruct.USART_BaudRate=bound;//
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//
USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//
USART_InitStruct.USART_Parity=USART_Parity_No;//
USART_InitStruct.USART_StopBits=USART_StopBits_1;//
USART_InitStruct.USART_WordLength=USART_WordLength_8b;//
USART_Init(USART3,&USART_InitStruct); //
USART_Cmd(USART3,ENABLE);//
}
void USART3_IRQHandler(void)
{
if (USART_GetITStatus(USART3, USART_IT_RXNE) == 1)
{
R_Data = USART_ReceiveData(USART3);//?aDD±íê?ê?μ?μ?êy?Y
if(R_Data=='A') USART3_Flag=1;
if(R_Data=='B') USART3_Flag=2;
if(R_Data=='C') USART3_Flag=3;
if(R_Data=='D') USART3_Flag=4;
if(R_Data=='E') USART3_Flag=5;
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
}
可以參考一個(gè)老哥的https://blog.csdn.net/hbzdsXCV/article/details/129278918?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168240123616800186542106%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=168240123616800186542106&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-129278918-null-null.142^v86^wechat,239^v2^insert_chatgpt&utm_term=%E4%B8%A4%E4%B8%AA%E5%8D%95%E7%89%87%E6%9C%BA%E7%9A%84%E8%93%9D%E7%89%99%E9%80%9A%E4%BF%A1&spm=1018.2226.3001.4187
手部采集部分,使用串口2
#include "usart2.h"
u8 USART2_RX_BUF[USART2_REC_LEN]; //?óê??o3?,×?′óUSART_REC_LEN??×??ú.??×??ú?a??DD·?
u16 USART2_RX_STA; //?óê?×′ì?±ê??
void uart2_Init(u32 baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //ê1?üUSART2£?GPIOAê±?ó
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //?′ó?í?íìê?3?
GPIO_Init(GPIOA, &GPIO_InitStructure);//3?ê??ˉGPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//????ê?è?
GPIO_Init(GPIOA, &GPIO_InitStructure);//3?ê??ˉGPIOA.3
//Usart1 NVIC ????
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//?à??ó??è??3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //×óó??è??3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQí¨μàê1?ü
NVIC_Init(&NVIC_InitStructure); //?ù?Y???¨μ?2?êy3?ê??ˉVIC??′??÷
//USART 3?ê??ˉéè??
USART_InitStructure.USART_BaudRate = baudrate;//′??ú2¨ì??ê
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×?3¤?a8??êy?Y??ê?
USART_InitStructure.USART_StopBits = USART_StopBits_1;//ò???í£?1??
USART_InitStructure.USART_Parity = USART_Parity_No;//?T????D£?é??
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//?Tó2?têy?Yá÷????
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //ê?·¢?£ê?
USART_Init(USART2, &USART_InitStructure); //3?ê??ˉ′??ú2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//?a??′??ú?óêü?D??
USART_Cmd(USART2, ENABLE); //ê1?ü′??ú2
}
void USART2_IRQHandler(void) //′??ú2?D??·t??3ìDò
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //?óê??D??(?óê?μ?μ?êy?Y±?D?ê?0x0d 0x0a?á?2)
{
Res =USART_ReceiveData(USART2); //?áè??óê?μ?μ?êy?Y
if((USART2_RX_STA&0x8000)==0)//?óê??′íê3é
{
if(USART2_RX_STA&0x4000)//?óê?μ?á?0x0d
{
if(Res!=0x0a)USART2_RX_STA=0;//?óê?′í?ó,??D??aê?
else USART2_RX_STA|=0x8000; //?óê?íê3éá?
}
else //?1??ê?μ?0X0D
{
if(Res==0x0d)USART2_RX_STA|=0x4000;
else
{
USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
USART2_RX_STA++;
if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//?óê?êy?Y′í?ó,??D??aê??óê?
}
}
}
}
}
static u8 USART2_TX_BUF[200];
void u2_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART2_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART2_TX_BUF); //′?′?·¢?íêy?Yμ?3¤?è
for(j=0;j<i;j++) //?-?··¢?íêy?Y
{
while((USART2->SR&0X40)==0); //?-?··¢?í,?±μ?·¢?ííê±?
USART2->DR=USART2_TX_BUF[j];
}
}
3.實(shí)現(xiàn)兩個(gè)藍(lán)牙的通信
在配置好兩個(gè)單片機(jī)的串口之后,其實(shí)關(guān)于藍(lán)牙通信就已經(jīng)解決的差不多了,最后剩下的關(guān)鍵只有串口發(fā)送函數(shù)和串口接收函數(shù)的使用,在主機(jī)使用串口發(fā)送函數(shù),在從機(jī)使用串口接收函數(shù),注意串口發(fā)送和接收的串口。
4.遇到的問題及解決方案
開始由于好久沒搗鼓過32了,而且我這個(gè)電腦ST-LINK一直沒有調(diào)過來,因此后來改成用串口燒錄,對于c8t6的串口燒錄(使用TTL轉(zhuǎn)USB燒錄),燒錄時(shí)應(yīng)用跳線帽將BOOT0置1,待燒錄完成后將BOOT0置0,才可正常工作,而期間BOOT1一直置0。
5.完整版代碼
鏈接:https://pan.baidu.com/s/1Nar8uLibDYbWvmrfeW7pBg?pwd=rx1l?
提取碼:rx1l文章來源:http://www.zghlxwxcb.cn/news/detail-546510.html
這是本人第一次在CSDN上發(fā)表文章,本人才學(xué)疏淺,寫下此文也是希望能幫到別人,謝謝。文章來源地址http://www.zghlxwxcb.cn/news/detail-546510.html
到了這里,關(guān)于關(guān)于兩個(gè)STM32F103系列單片機(jī)的藍(lán)牙通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!