开发环境
MCU:STM8L151K4T6
蓝牙模块:WH-BLE103(文末附官方资料链接)
编译:IAR_STM8
烧录:STVP
开发平台:vscode
主要扩展:Embedded IDE、C\C++
测试过程
前言
最近想鼓捣鼓捣蓝牙,之前没有接触过蓝牙协议栈,感觉从现成的模块入手会更快一点。
选用的是WH-BLE103,支持透传以及AT指令组网。这里简单科普一下,透传是啥呢?其实就是把蓝牙模块当串口来用,你发过来的数据是什么,我接收到的就是什么。而AT指令,可以快速的设置蓝牙模块的各项参数。
对于WH-BLE103来说,只需要设定配对密码和改变模式就能自行组网。
目标
- 实现十台设备的组网和信息通讯
- 实现手机通过中继控制/查询网内节点设备信息(实验中使用LED亮暗表示信息)
工程与代码
- 工程配置
因为我希望组网是一个动态的过程(可以任意添加或删除设备),因此需要申请动态数组,看了下memory map,我在工程中申请了一个256字节的heap。
"linker": {
"linker-config": "lnkstm8l151k4.icf",
"auto-search-runtime-lib": true,
"use-C_SPY-debug-lib": true,
"config-defines": [
"_CSTACK_SIZE=0x0400",
"_HEAP_SIZE=0x0100"
]
}
- MCU串口初始化
AT指令可以设置蓝牙的串口通讯参数,本实验沿用了WH-BLE103的出厂参数,具体可看注释。
void bsp_uart_init(void)
{
USART_DeInit(USART1);
CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);
//remappin
//SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortC, ENABLE);
/**
* @param USART1 ,
* @param BR: 57600,
* @param WL: 8bit,
* @param SB: 1 bit,
* @param PR: no parity,
* @param MODE: RX/TX mode
*/
USART_Init(USART1, (uint32_t)57600, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Tx | USART_Mode_Rx));
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
ITC_SetSoftwarePriority(USART1_RX_IRQn, ITC_PriorityLevel_2);//priority 2
USART_Cmd(USART1, ENABLE);
USART1_RX_STA = 0;
bsp_tim3_init(1250);//Enter interrupt after 10ms
}
- MCU串口数据处理程序
用于处理蓝牙回传数据流和外部(如手机)数据流
USART1_RX_STA的声明入下:
Bit [15] | Bit [14:0] |
---|---|
0: waiting for receive, 1: received a set of data | record the length of data |
采用了10ms规则,即两次数据流的接收间隔必须大于10ms
void USART1_IRQHandler(void)
{
uint8_t receive_data;
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET) //Check whether the specified UART1 interrupt occurs.
{
receive_data = USART_ReceiveData8(USART1);
if((USART1_RX_STA & (uint16_t)(1<<15)) == 0)
{
if(USART1_RX_STA < USART1_RX_MAX_LEN) //Determine whether the byte overflows
{
TIM3_SetCounter(0);//recount
if(0 == USART1_RX_STA)
TIM3_Cmd(ENABLE);
USART1_RX_buf[USART1_RX_STA++] = receive_data;
// if(RELAY_DEV == DEVICE_ID)
// USART1_RELAY_buf[USART1_RX_STA++] = receive_data;
}
else
USART1_RX_STA |= (uint16_t) 1<<15;//enforce finish receive
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //Clear UART1 pending flag
}
}
- AT指令发送
基于蓝牙模块手册编写,根据蓝牙回传规则,AT指令发送成功时的返回数据尾为 “OK\r\n”,进入AT模式时返回的数据尾为 “ok\r\n”。
uint8_t AT_Send(uint8_t *atcmd)
{
uint16_t tag = 1;
uint8_t t;
// uint16_t k;
USART1_RX_STA = 0;
memset(USART1_RX_buf, 0, sizeof(USART1_RX_buf));
uint8_t retry = 10;//number of AT command sending attempts
while (retry--)