rt-thread nano stm32f103cbt6 蓝牙模块的通信(有整个工程的代码仓库)
本項(xiàng)目代碼倉(cāng)庫(kù)的網(wǎng)頁(yè):董昊旻/rt_nano_bluetoothhttps://gitee.com/donghaomin/rt_nano_bluetooth
目錄
一,任務(wù)來(lái)源
二,任務(wù)描述
三,代碼編寫思路
(一)數(shù)據(jù)存儲(chǔ),刪減
(二)藍(lán)牙初始化,藍(lán)牙發(fā)送過(guò)來(lái)的數(shù)據(jù)進(jìn)行解析
四,總結(jié)
一,任務(wù)來(lái)源
清明節(jié)在家呆著無(wú)聊就看了一個(gè)豬八戒發(fā)布的一個(gè)簡(jiǎn)單的任務(wù),但是不會(huì)操作那些程序外包的東西,就把這個(gè)任務(wù)作為一個(gè)練手的小項(xiàng)目,打發(fā)一下時(shí)間,代碼的思考,撰寫和調(diào)試應(yīng)該花了12個(gè)小時(shí),昨天晚上5點(diǎn)到半夜1點(diǎn)(代碼寫到興奮的睡不著覺,在地上站著玩了一個(gè)半小時(shí)手機(jī)才睡著),第二天的早上8點(diǎn)到12點(diǎn)。很大一部分時(shí)間花在了調(diào)試stm32的引腳,中斷和串口上了,大學(xué)畢業(yè)之后就沒用過(guò)stm32了,也沒用過(guò)stm32clubMx,所以學(xué)習(xí)這個(gè)工具花了一點(diǎn)時(shí)間。
藍(lán)牙模塊我手里沒有,因?yàn)殚L(zhǎng)春疫情的原因我也沒辦法買,啥時(shí)候疫情結(jié)束我也不知道,就對(duì)著大夏龍雀的藍(lán)牙文檔盲寫了。
硬件如下
二,任務(wù)描述
下邊這個(gè)圖就是他發(fā)布的任務(wù),這個(gè)東西仁者見仁智者見智,我感覺難度還行,就是比較費(fèi)時(shí)間。
三,代碼編寫思路
這個(gè)要是我大學(xué)的時(shí)候?qū)?#xff0c;也就是三個(gè)小時(shí)之內(nèi),現(xiàn)在至少需要20個(gè)小時(shí),哈哈。不是能力下降了,就是思考的問(wèn)題不一樣了。大學(xué)的時(shí)候一切以能用主義,寫上去能用就OK,現(xiàn)在開始思考代碼的可讀性,可維護(hù)性,穩(wěn)定性等等...
言歸正傳,既然思考的問(wèn)題不一樣,所以我們就先分割一下這個(gè)項(xiàng)目的功能。
1.帶id的數(shù)據(jù)存儲(chǔ),還可以刪除數(shù)據(jù)(我的理解是不用存儲(chǔ)到norflash上,暫存到sram即可)
2.一個(gè)下降沿中斷的GPIO
3.一路串口(我用的是UART2)
這個(gè)是硬件上的基礎(chǔ)需求,然后我們聊一下軟件的代碼邏輯:
(一)數(shù)據(jù)存儲(chǔ),刪減
我沒有采取鏈表的結(jié)構(gòu)來(lái)存儲(chǔ)數(shù)據(jù),第一是沒必要這么復(fù)雜,它只要幾十個(gè)數(shù)據(jù)用不了那么多,寫著也麻煩。我就用一個(gè)機(jī)構(gòu)體存儲(chǔ)了溫度數(shù)據(jù)和連接狀態(tài)。DATA_SUM是40,這么一寫的話就能存儲(chǔ)40條數(shù)據(jù)了,還能存儲(chǔ)藍(lán)牙硬件初始化的完成狀況和藍(lán)牙連接的狀態(tài)。
數(shù)據(jù)增加,你一按動(dòng)按鍵的時(shí)候就將中斷中的flag置1,在主循環(huán)的while(1)將數(shù)據(jù)加進(jìn)去一個(gè)結(jié)構(gòu)體中,將結(jié)構(gòu)體中的useDataCount加一,超出40就報(bào)錯(cuò),讓他清空。
刪除的話就更簡(jiǎn)單了,直接讓這個(gè)大結(jié)構(gòu)體memset為0,就OK了。
typedef enum UsrState {DATA_UN_USED_Sta = 0x00, // 溫度值不正確(不存在)DATA_USED_Sta = 0x01, // 溫度值正確(存在)DATA_SUM_Sta }usrsta;typedef struct D_USR_DATA{unsigned char id; // 計(jì)數(shù)標(biāo)簽float value; // 溫度值usrsta state; // 狀態(tài)值,溫度值是否正確 }d_data;typedef struct Dong_BLUE_TEMP{unsigned int blueTooth_state; // 藍(lán)牙啟動(dòng)的狀態(tài)位unsigned int blueTooth_connect_state; // 藍(lán)牙連接的狀態(tài)位,是否斷了連接unsigned char usedDataCount; // 當(dāng)前存儲(chǔ)了多少個(gè)溫度數(shù)據(jù)d_data data[DATA_SUM]; // 溫度數(shù)據(jù) }d_bule_temp;(二)藍(lán)牙初始化,藍(lán)牙發(fā)送過(guò)來(lái)的數(shù)據(jù)進(jìn)行解析
藍(lán)牙模塊初始化:藍(lán)牙模塊是通過(guò)"AT"指令進(jìn)行配置的,為了避免有人用沒配置過(guò)的藍(lán)牙模塊進(jìn)行連接,所以我們就需要每次初始化的時(shí)候初始化,避免出現(xiàn)藍(lán)牙模塊配置的問(wèn)題出現(xiàn)的BUG。
藍(lán)牙數(shù)據(jù)解析:藍(lán)牙發(fā)過(guò)來(lái)的數(shù)據(jù)是串口發(fā)送與接收的,我設(shè)置串口的緩沖BUFFER為10Byte,對(duì)這10Byte進(jìn)行解析我們就能知道要做的事情。我用一個(gè)結(jié)構(gòu)體來(lái)存儲(chǔ)這10個(gè)Byte。代碼里有注釋,我就不詳細(xì)描述了。
有了這個(gè)結(jié)構(gòu)體,我們就可以做一個(gè)類似于"診斷"的接口,因此代碼運(yùn)行的邏輯就是,接收到串口的數(shù)據(jù),在主函數(shù)中判斷結(jié)構(gòu)體的第一個(gè)數(shù)據(jù)really是不是0x01,是0x01的話就判斷function id,在進(jìn)入到不同得一級(jí)分支,在根據(jù)sub function id進(jìn)入到二級(jí)分支,再根據(jù)datalenght來(lái)判斷data的6Byte用了幾個(gè)。具體這個(gè)6個(gè)Byte表達(dá)了那些內(nèi)容就由,二級(jí)分支自己決定了。
/*** 一級(jí)主功能ID* */ typedef enum FUNCTION_ID {BLUE_TOOTH_IMG = 0x00, // 藍(lán)牙信息獲取TEMP_DATA_OPT = 0x01, // 溫度信息獲取,刪除DIAG_CODE_OPT = 0x02, // 診斷IDFUNCTION_ID_SUM // ID總數(shù) }d_function_id;typedef struct Dong_BLUETOOTH_RECIVE_CMD{unsigned char really; // 判斷是否當(dāng)前有數(shù)據(jù)(你也可以理解為器件ID),有數(shù)據(jù)的話就是0x01,沒有就是0x00,也就是說(shuō)藍(lán)牙發(fā)送數(shù)據(jù)的時(shí)候第一位必須是0x01d_function_id function_id; // 藍(lán)牙接收數(shù)據(jù)的主功能idunsigned char sub_function_id; // 藍(lán)牙接收數(shù)據(jù)的二級(jí)功能idunsigned char datalenght; // 藍(lán)牙發(fā)送過(guò)來(lái)的數(shù)據(jù)長(zhǎng)度unsigned char data[6]; // 藍(lán)牙發(fā)送過(guò)來(lái)的數(shù)據(jù)6個(gè)byte }d_bule_revcmd;藍(lán)牙模塊AT指令的判斷我寫了一個(gè)代碼覺得很有趣下邊貼出來(lái),加了一個(gè)超時(shí)的處理。
// 藍(lán)牙狀態(tài)運(yùn)行檢測(cè) errornum bluetooth_AT_OK(void) {errornum ret = DIAG_OK;unsigned int overtime = 0;while(d_revbuffer.really == 0x00) {HAL_UART_Transmit_IT(&huart2,(uint8_t *)AT_OK_ACK,strlen(AT_OK_ACK));rt_thread_mdelay(500);overtime++;if(overtime > OVERTIME_TIMES) {ret = DIAG_OVERTIM_ERR;rt_kprintf("AT_OK time out\n");return ret;}}memcpy(locat_data,&d_revbuffer,sizeof(locat_data));int dong = memcmp(locat_data,AT_OK_ANS,strlen(AT_OK_ANS));if(dong!=0){rt_kprintf("AT False\n");ret = DIAG_BLUE_ERR;}else {rt_kprintf("AT OK\n");ret = DIAG_OK;}return ret; }運(yùn)行的LOG,用串口模擬藍(lán)牙,主機(jī)主動(dòng)發(fā)AT,從機(jī)在10次請(qǐng)求內(nèi)發(fā)OK,主機(jī)就認(rèn)為藍(lán)牙沒問(wèn)題。
我的代碼結(jié)構(gòu)如下圖:
diag負(fù)責(zé)分析和處理藍(lán)牙接收的串口數(shù)據(jù)。
bluetooth負(fù)責(zé)藍(lán)牙模塊的初始化,檢測(cè)藍(lán)牙信號(hào)強(qiáng)度,連接狀態(tài)等的函數(shù)(連接狀態(tài)函數(shù)我會(huì)放到一個(gè)一秒周期的task中,連接上了blueTooth_connect_state就置0x01,掉了就0x00),藍(lán)牙模塊正不正常的話我就用AT指令測(cè)試,能回OK就將blueTooth_connect_state置0x02,不能就0x03,類似于這個(gè)意思推之后的邏輯。
hardware就是硬件初始化相關(guān)的函數(shù),我初始化了UART2,PC13(LED),PA11(KEY)。
urs_data就是存儲(chǔ)溫度和其他基礎(chǔ)結(jié)構(gòu)體的頭文件,初始化函數(shù)。
四,總結(jié)
代碼目前還沒寫完,目前處于一個(gè)初版本demo的狀況,但是能用!你可以直接把代碼下載下來(lái),用RT Thread Studio編譯下載到你的開發(fā)板,你也不用擔(dān)心,開發(fā)板不兼容,因?yàn)槲矣玫氖呛诵陌濉?/p>
總結(jié)
以上是生活随笔為你收集整理的rt-thread nano stm32f103cbt6 蓝牙模块的通信(有整个工程的代码仓库)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为java程序添加字库
- 下一篇: 西门子200smart与台达MS300变