【ST NUCLEO-WB09KE测评】-8-从零创建BLE GATT空白工程
本帖最后由 慕容雪花 于 2024-9-16 23:18 编辑<p>官方指导文档: LAT1309 一步一步创建STM32WBA BLE_Custom工程</p>
<p> </p>
<p>第一步:在CUBEIDE里面,根据芯片型号选择WB09KEV6</p>
<div style="text-align: center;"> </div>
<div style="text-align: center;"> </div>
<div>接着配置串口</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>接着配置调试接口</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>使能RADIO TIMER</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>接着使能RADIO</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>接着配置时钟:</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>最后使能STM32 BLE:</div>
<div>
<div style="text-align: center;"></div>
<p> </p>
</div>
<div>创建一个GATT SERVER应用:</div>
<div style="text-align: center;"> </div>
<div> </div>
<div style="text-align: center;"> </div>
<div> </div>
<div> </div>
<div style="text-align: center;"> </div>
<p> </p>
<p>点击保存,自动生成代码。在</p>
<p>调试运行发现,一直在RADIO TIMER初始化程序卡住,后来参考官方例程,对RADIO时钟源进行了如下修改。</p>
<p> </p>
<p> </p>
<p>整个创建BLE空白工程的过程十分方便,只需要根据智能提示依次配置BLE所需的模块,最后创建Service,增加Characteristic,即可生成几乎所有的代码。</p>
<p>最后在APP_BLE_Init()函数里面增加下面的函数来开启广播,一切搞定!</p>
<pre>
<code>/* USER CODE BEGIN APP_BLE_Init_2 */
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_START_FAST);
/* USER CODE END APP_BLE_Init_2 */</code></pre>
<p>打开BLE DONGE,可以扫描到WB09-KE开发板发出的广播信号:</p>
<p> </p>
<p style="text-align: center;"></p>
<p style="text-align: center;"></p>
<p style="text-align: center;"> </p>
<p>目前Characteristic没有使能读,写,通知等特性,下面增加一个读的特性。在Cubeide里面增加即可,然后自动生成代码。</p>
<p style="text-align: center;"> </p>
<p>进入到Event handler里面,增加应用代码:</p>
<pre>
<code>static BLEEVT_EvtAckStatus_t TEMPSENSOR_EventHandler(aci_blecore_event *p_evt)
{
BLEEVT_EvtAckStatus_t return_value = BLEEVT_NoAck;
aci_gatt_srv_read_event_rp0 *p_read;
/* USER CODE BEGIN Service1_EventHandler_1 */
uint8_t mgc_val_len;
static uint8_t mgc_val_buff={0};;
uint8_t attr_error_code = BLE_ATT_ERR_NONE;
/* USER CODE END Service1_EventHandler_1 */
switch(p_evt->ecode)
{
case ACI_GATT_SRV_ATTRIBUTE_MODIFIED_VSEVT_CODE:
{
/* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */
/* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */
/* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
/* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
break;/* ACI_GATT_SRV_ATTRIBUTE_MODIFIED_VSEVT_CODE */
}
case ACI_GATT_SRV_READ_VSEVT_CODE :
{
/* USER CODE BEGIN EVT_BLUE_GATT_SRV_READ_BEGIN */
/* USER CODE END EVT_BLUE_GATT_SRV_READ_BEGIN */
p_read = (aci_gatt_srv_read_event_rp0*)p_evt->data;
if(p_read->Attribute_Handle == (TEMPSENSOR_Context.SenvalCharHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))
{
return_value = BLEEVT_Ack;
/*USER CODE BEGIN Service1_Char_1_ACI_GATT_SRV_READ_VSEVT_CODE_1 */
#warning user shall call aci_gatt_srv_read_resp() function if allowed
/*USER CODE END Service1_Char_1_ACI_GATT_SRV_READ_VSEVT_CODE_1 */
/*USER CODE BEGIN Service1_Char_1_ACI_GATT_SRV_READ_VSEVT_CODE_2 */
mgc_val_len = 2;
mgc_val_buff = mgc_val_buff + 1;
mgc_val_buff = mgc_val_buff + 2;
aci_gatt_srv_resp(p_read->Connection_Handle,BLE_GATT_UNENHANCED_ATT_L2CAP_CID,p_read->Attribute_Handle,attr_error_code,mgc_val_len,mgc_val_buff);
/*USER CODE END Service1_Char_1_ACI_GATT_SRV_READ_VSEVT_CODE_2 */
} /* if(p_read->Attribute_Handle == (TEMPSENSOR_Context.SenvalCharHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))*/
/* USER CODE BEGIN EVT_BLUE_GATT_SRV_READ_END */
/* USER CODE END EVT_EVT_BLUE_GATT_SRV_READ_END */
break;/* ACI_GATT_SRV_READ_VSEVT_CODE */
}
case ACI_GATT_SRV_WRITE_VSEVT_CODE:
{
/* USER CODE BEGIN EVT_BLUE_SRV_GATT_BEGIN */
/* USER CODE END EVT_BLUE_SRV_GATT_BEGIN */
/* USER CODE BEGIN EVT_BLUE_GATT_SRV_WRITE_END */
/* USER CODE END EVT_BLUE_GATT_SRV_WRITE_END */
break;/* ACI_GATT_SRV_WRITE_VSEVT_CODE */
}
case ACI_GATT_TX_POOL_AVAILABLE_VSEVT_CODE:
{
aci_gatt_tx_pool_available_event_rp0 *p_tx_pool_available_event;
p_tx_pool_available_event = (aci_gatt_tx_pool_available_event_rp0 *) p_evt->data;
UNUSED(p_tx_pool_available_event);
/* USER CODE BEGIN ACI_GATT_TX_POOL_AVAILABLE_VSEVT_CODE */
/* USER CODE END ACI_GATT_TX_POOL_AVAILABLE_VSEVT_CODE */
break;/* ACI_GATT_TX_POOL_AVAILABLE_VSEVT_CODE*/
}
case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE:
{
aci_att_exchange_mtu_resp_event_rp0 *p_exchange_mtu;
p_exchange_mtu = (aci_att_exchange_mtu_resp_event_rp0 *)p_evt->data;
UNUSED(p_exchange_mtu);
/* USER CODE BEGIN ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE */
/* USER CODE END ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE */
break;/* ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE */
}
/* USER CODE BEGIN BLECORE_EVT */
/* USER CODE END BLECORE_EVT */
default:
/* USER CODE BEGIN EVT_DEFAULT */
/* USER CODE END EVT_DEFAULT */
break;
}
/* USER CODE BEGIN Service1_EventHandler_2 */
/* USER CODE END Service1_EventHandler_2 */
return(return_value);
}/* end TEMPSENSOR_EventHandler */
</code></pre>
<p>实验:</p>
<p style="text-align: center;"> </p>
<p style="text-align: center;"> </p>
<p>打开串口发现竟然没有数据,一顿操作:</p>
<p>1. 配置开关</p>
<p style="text-align: center;"> </p>
<p>2. printf重定向</p>
<pre>
<code>/* USER CODE BEGIN 4 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END 4 */</code></pre>
<p>测试:</p>
<p> </p>
<p>这个是不是得最新版本的STM32CubeMX? </p>
秦天qintian0303 发表于 2024-9-17 19:19
这个是不是得最新版本的STM32CubeMX?
<p>是的,最新版本的CUBEMX才支持最新的WB09KE芯片。CUBEIDE更省事,全家桶</p>
慕容雪花 发表于 2024-9-18 08:43
是的,最新版本的CUBEMX才支持最新的WB09KE芯片。CUBEIDE更省事,全家桶
<p>cubeIDE有兼容新问题,通过MX进行程序更新后,代码框若隐若现没法对应上,就是上面那块的打开的C和H文件名那块</p>
页:
[1]