藍(lan)牙(ya)H4傳輸層協議(yi)
藍牙幾種不同接口的傳輸協議(yi):H2/H4/H5/BCSP/SDIO及(ji)區別
H2:基于USB的傳輸
H4:基于五線UART(RX/TX/CTS/RTS/GND帶硬件流控)的傳輸,最簡單的傳輸方式,只在HCI raw data前面加上一個type;
H5: 基于三線UART(RX/TX/GND)的傳輸,需要軟件協議層加一個數據完整性校驗機制;
BCSP: 基于UART的傳輸
SDIO :基于SDIO的傳輸
TRANSPORT層:在硬件接口(UART/USB/SDIO)實現HOST跟CONTROLLER的(de)交互
H2: USB的transport
H4:UART的transport(是UART傳輸種最簡的一個Transport,只是在HCI raw data的前面加一個type就行,如下HCI一共有五種HCI data)
* HCI COMMAND:由藍牙協議棧發送給芯片的命令
* HCI EVENT:由藍牙芯片上報給藍牙協議棧的事件
* HCI ACL:藍牙協議棧跟(gen)藍牙芯片雙向交互的普通數據* HCI SCO:藍牙芯片跟藍牙協議棧雙向交互的通話/語音識別等音頻數據
* HCI ISO(這(zhe)部分(fen)是在core5.2才添加):LE audio用的數據包格式(shi)
藍牙傳輸介質Transport UART H4(RS232)介紹
//www.52bluetooth.com/portal.php?mod=view&aid=179&mobile=no
Transport H4介紹(shao)
1. 概念(nian)介紹
整(zheng)個(ge)Transport在藍牙架構(gou)中的(de)位置如下圖紅框(kuang)位置:
藍牙Transport就(jiu)是(shi)(shi)藍牙的(de)硬(ying)件發送協(xie)(xie)(xie)議(yi)(yi),硬(ying)件的(de)傳輸介質有(you):UART/USB/SDIO,那么(me)(me)Transport就(jiu)是(shi)(shi)在(zai)特定的(de)硬(ying)件傳輸介質上增加了一(yi)些(xie)協(xie)(xie)(xie)議(yi)(yi),比(bi)如我們(men)本節將的(de)H4就(jiu)是(shi)(shi)在(zai)UART上增加了一(yi)個(ge)小協(xie)(xie)(xie)議(yi)(yi),H4算是(shi)(shi)最(zui)簡(jian)單的(de)一(yi)個(ge)協(xie)(xie)(xie)議(yi)(yi),只是(shi)(shi)在(zai)數(shu)據(ju)前(qian)面(mian)加一(yi)個(ge)Type,了解(jie)過藍牙HCI的(de)一(yi)般(ban)都會知道藍牙協(xie)(xie)(xie)議(yi)(yi)棧(Host)跟(gen)芯片(Controller)一(yi)般(ban)是(shi)(shi)通(tong)(tong)過HCI數(shu)據(ju)來溝通(tong)(tong),那么(me)(me)H4就(jiu)是(shi)(shi)在(zai)HCI數(shu)據(ju)前(qian)面(mian)加上一(yi)個(ge)TYPE。一(yi)共有(you)5中type,如下(xia):
1)HCI COMMAND:由藍牙(ya)協議棧(zhan)發送(song)給(gei)芯片的命(ming)令(ling)
2)HCI EVENT:由藍(lan)牙芯片上報(bao)給(gei)藍(lan)牙協議棧的事件
3)HCI ACL:藍牙(ya)協議棧跟藍牙(ya)芯片雙向交(jiao)互的普通數(shu)據
4)HCI SCO:藍牙(ya)芯片跟藍牙(ya)協(xie)議棧雙向交互的通話/語音識別等音頻數據
5)HCI ISO(這部(bu)分是在core5.2才(cai)添加(jia)):用于發(fa)送LE audio
在Core文檔(dang)截圖如下:
交互(hu)數據格(ge)式(shi)為:
所(suo)以(yi)我們看(kan)下代碼在(zai)這部分的實現:
1)通過(guo)宏配置協議(yi)棧(zhan)的TRANSPORT type,可(ke)以看到以下代碼(ma)是配置的H4
/** BT_PBUF_TRANSPORT_H2 = 0x01,BT_PBUF_TRANSPORT_H4 = 0x02,BT_PBUF_TRANSPORT_H5 = 0x03,BT_PBUF_TRANSPORT_BCSP = 0x04,*/ #define BT_TRANSPORT_TYPE 0x02
2)舉例說(shuo)明HCI reset發(fa)送(HCI raw data為0x03 0x0c 0x00)
err_t hci_reset(void) { struct bt_pbuf_t *p; /* 申(shen)請(qing)Transport的buffer,比(bi)HCI數據多了一個byte */ if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_RESET_PLEN, BT_PBUF_RAM)) == NULL) { BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__); return BT_ERR_MEM; } /* Assembling command packet */ p = hci_cmd_ass(p, HCI_RESET, HCI_HOST_C_N_BB, HCI_RESET_PLEN); pcb->timer = utimer_create(HCI_RESET_TIMEOUT, hci_reset_timeout, 0); /* Assembling cmd prameters */ /* 發送HCI raw data在底層(ceng)處理增(zeng)加了1個byte */ phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD); bt_pbuf_free(p); return BT_ERR_OK; }3)到了Transport的處理void phybusif_output(struct bt_pbuf_t *p, uint16_t len,uint8_t packet_type) { /* 后退1個byte */ bt_pbuf_header(p, 1); /* 填寫上type */ ((uint8_t *)p->payload)[0] = packet_type; uint8_t *tx_buffer = bt_get_tx_buffer(); bt_pbuf_copy_partial(p, tx_buffer, p->tot_len, 0); BT_TRANSPORT_TRACE_DEBUG("BT TX LEN:%d\n",p->tot_len); bt_hex_dump(tx_buffer,p->tot_len); /* 通過UART發(fa)送(song)出去 */ uart_bt_send(tx_buffer,p->tot_len); }2. 硬件要求
UART硬件配置要求總(zong)結:
1)數據位8bit
2)無奇偶校驗
3)停止位1bit
4)需要有硬件流控
所以(yi)MCU跟藍牙芯(xin)片的接線需要:
我們來看下代碼的實現:
1)在STM32的UART初始化(hua)(只貼(tie)出關鍵位置)
/****************************************************************************** * func name : hw_uart_bt_init * para : baud_rate(IN) --> Baud rate of uart1 * return : hw_uart_bt_init result * description : Initialization of USART2.PA0->CTS PA1->RTS PA2->TX PA3->RX ******************************************************************************/ uint8_t hw_uart_bt_init(uint32_t baud_rate,uint8_t reconfig) { ............. /* Data format :1:8:1, no parity check, hardware flow control */ USART_InitStructure.USART_BaudRate = baud_rate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; ......... return BT_ERR_OK; }
2)在Linux的UART初始化(hua)(只貼(tie)出(chu)關鍵(jian)位置)
uint8_t hw_uart_bt_init(uint32_t baud_rate,uint8_t reconfig) { ...... // 8N1 toptions.c_cflag &= ~CSTOPB; toptions.c_cflag |= CS8; toptions.c_cflag |= CREAD | CLOCAL | CRTSCTS; toptions.c_iflag &= ~(IXON | IXOFF | IXANY); toptions.c_cflag &= ~PARENB; toptions.c_cc[VMIN] = 1; toptions.c_cc[VTIME] = 0; ....... return BT_ERR_OK; }
3. 糾錯
如果主(zhu)機(ji)(ji)(ji)(ji)(ji)或(huo)主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器在 RS232 通(tong)信上失(shi)(shi)去同(tong)步,則需要復位(wei)。失(shi)(shi)去同(tong)步意味著已(yi)檢測(ce)到錯誤(wu)的 HCI 分組指示器,或(huo) HCI 分組的長度(du)域(yu)超出范圍(wei)。如果在主(zhu)機(ji)(ji)(ji)(ji)(ji)到主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器的通(tong)信中丟失(shi)(shi) UART 同(tong)步,那(nei)么主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器將發(fa)送(song)硬件故障(HCI hardware error)事件,以(yi)將同(tong)步錯誤(wu)告訴主(zhu)機(ji)(ji)(ji)(ji)(ji)。主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器將需要從主(zhu)機(ji)(ji)(ji)(ji)(ji)接收一個HCI_RESET 指令(ling)以(yi)執行復位(wei)。主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器也將在從主(zhu)機(ji)(ji)(ji)(ji)(ji)到主(zhu)機(ji)(ji)(ji)(ji)(ji)控(kong)(kong)(kong)制(zhi)器的字節流(liu)中使用 HCI-RESET 指令(ling),以(yi)實(shi)現重新同(tong)步。
如果(guo)在從主機(ji)(ji)控制(zhi)器(qi)(qi)到主機(ji)(ji)的(de)通信中(zhong)失去 UART 同步,主機(ji)(ji)將發送 HCL_RESET指(zhi)令(ling)(ling)以復位(wei)主機(ji)(ji)控制(zhi)器(qi)(qi)。主機(ji)(ji)也將通過在從主機(ji)(ji)控制(zhi)器(qi)(qi)到主機(ji)(ji)的(de)字節流中(zhong)查(cha)找HCI_Reset 指(zhi)令(ling)(ling)的(de) HCL 指(zhi)令(ling)(ling)完(wan)成(cheng)事件,進行重新同步






