/* * @Author: mbw * @Date: 2024-12-03 10:31:45 * @LastEditors: mbw && 1600520629@qq.com * @LastEditTime: 2024-12-16 19:00:53 * @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_bt.c * @Description: * * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. */ #include "bsp_bt.h" #include "bsp_ml307.h" #include "bsp_flash.h" #include "rtdef.h" #include "lwrb.h" #include "finsh.h" #include "user_sys.h" #define LOG_TAG "bsp_bt" #define LOG_LVL LOG_LVL_DBG #include #define BT_UART "uart5" static rt_device_t rt_bt_device; static struct rt_semaphore bt_rx_sem; // struct rt_semaphore bt_ctr_sem; // 控制阀门信号量 struct rt_semaphore bt_reg_sem; // 注册阀门信号量 struct rt_semaphore bt_rem_sem; // 移除阀门信号量 struct rt_semaphore bt_rep_sem; // 更换阀门信号量 #define BT_THREAD_TIMESLICE (5) #define BT_THREAD_PRIORITY (10) #define BT_THREAD_STACK_SIZE (2048) ALIGN(RT_ALIGN_SIZE) static rt_uint8_t bt_thread_stack[BT_THREAD_STACK_SIZE] = {0}; static struct rt_thread bt_thread = {0}; lwrb_t bt_lwrb_rx; static char bt_rx_buffer[256] = {0}; BTFrameData bt_frame = {0}; valve_data valve[MAX_VALVE_NUM]; rt_size_t BSP_Bt_Send_Data(uint8_t *data, size_t size) { return rt_device_write(rt_bt_device, 0, data, size); } rt_size_t BSP_Bt_Recv_Data(uint8_t *data, size_t size) { return lwrb_read(&bt_lwrb_rx, data, size); } int BSP_BT_Init(void) { rt_uint8_t num = Flash_Get_Valve_Num(); rt_uint8_t mac_buf[FLASH_VALVE_MAC_ADDR_LEN] = {0}; if (num != 0) { for (size_t i = 0; i < MAX_VALVE_NUM; i++) { valve[i].valve_id = (i + 1); // 1-8 if (Flash_Get_Mac_Addr(valve[i].valve_mac, i) == RT_EOK) { rt_memcpy(valve[i].valve_mac, mac_buf, 6); } } } else { for (size_t i = 0; i < MAX_VALVE_NUM; i++) { rt_memset(&valve[i], 0, sizeof(struct valve_t)); } } return RT_EOK; } INIT_PREV_EXPORT(BSP_BT_Init); static rt_err_t bt_getchar(char *ch, rt_int32_t timeout) { rt_err_t result = RT_EOK; while (rt_device_read(rt_bt_device, 0, ch, 1) == 0) { result = rt_sem_take(&bt_rx_sem, rt_tick_from_millisecond(timeout)); if (result != RT_EOK) { return result; } } return RT_EOK; } static int bt_recv_readline(void) { rt_size_t read_len = 0; char ch = 0, last_ch = 0; rt_bool_t is_full = RT_FALSE; while (1) { bt_getchar(&ch, RT_WAITING_FOREVER); if (read_len < lwrb_get_free(&bt_lwrb_rx)) { lwrb_write(&bt_lwrb_rx, &ch, 1); } else { is_full = RT_TRUE; } if (ch == '\n' && last_ch == '\r') { if (is_full) { LOG_E("read line failed. The line data length is out of buffer size(%d)!", lwrb_get_free(&bt_lwrb_rx)); return -RT_EFULL; } break; } last_ch = ch; } return lwrb_get_full(&bt_lwrb_rx); } /*发送数据帧处理*/ rt_uint8_t BT_GenerateRawFrame(BTFrameData *pRawData, const rt_uint8_t *p_src, rt_uint8_t src_len) { pRawData->len = src_len + 4; rt_memset(pRawData->buf, 0, sizeof(pRawData->buf)); pRawData->buf[0] = BT_FRAME_HEAD_DATA; pRawData->buf[1] = src_len; rt_memmove(&pRawData->buf[2], p_src, src_len); // 从帧起始符开始到校验码之前所有字节的和的模256 // ,即各字节不计超过255的溢出值的二进制算术和。 pRawData->buf[pRawData->len - 2] = XOR_CheckSum(&pRawData->buf[0], pRawData->len - 2); pRawData->buf[pRawData->len - 1] = BT_FRAME_TAIL_DATA; LOG_HEX("BTFrameData", 16, &pRawData->buf[0], pRawData->len); return RT_EOK; } /*用于控制阀门的状态 * id: 1-8 * mac_addr: 6字节 * status: 0-关闭 1-打开 */ int BSP_Bt_Valve_Ctr(rt_uint8_t id, rt_uint8_t *mac_addr, WireLessState status) { rt_uint8_t ret = 0; BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 8); ptr->cmd = kValveCmdCtr; ptr->buf[0] = id; rt_memcpy(&ptr->buf[1], mac_addr, 6); ptr->buf[7] = status; BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 9); rt_free(ptr); ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len); if (ret == bt_frame.len) { return RT_EOK; } return RT_ERROR; } /*注册阀门信息*/ int BSP_Bt_Register_Valve(rt_uint8_t id, rt_uint8_t *mac_addr) { rt_uint8_t ret = 0; BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 7); ptr->cmd = kValveCmdReg; ptr->buf[0] = id; rt_memcpy(&ptr->buf[1], mac_addr, 6); BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 8); rt_free(ptr); ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len); if (ret == bt_frame.len) { return RT_EOK; } return RT_ERROR; } /*移除阀门信息*/ int BSP_Bt_Remove_Valve(rt_uint8_t id, rt_uint8_t *mac_addr) { rt_uint8_t ret = 0; BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 7); ptr->cmd = kValveCmdRem; ptr->buf[0] = id; rt_memcpy(&ptr->buf[1], mac_addr, 6); BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, 8); rt_free(ptr); ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len); if (ret == bt_frame.len) { return RT_EOK; } return RT_ERROR; } /*更换阀门信息*/ int BSP_Bt_Replace_Valve(rt_uint8_t id, rt_uint8_t *mac_addr, rt_uint8_t *new_mac_addr) { rt_uint8_t ret = 0; BtData_t *ptr = (BtData_t *)rt_malloc(sizeof(BtData_t) + 14); ptr->cmd = kValveCmdRep; ptr->buf[0] = id; rt_memcpy(&ptr->buf[1], mac_addr, 6); rt_memcpy(&ptr->buf[7], new_mac_addr, 6); BT_GenerateRawFrame(&bt_frame, (rt_uint8_t *)ptr, (sizeof(BtData_t) + 14)); rt_free(ptr); ret = BSP_Bt_Send_Data((rt_uint8_t *)&bt_frame.buf[0], bt_frame.len); if (ret == bt_frame.len) { return RT_EOK; } return RT_ERROR; } // 这个ID是真实id减一,例:第一个阀门,则为 1 - 1 = 0 /*data 数据用作阀门更换时的新MAC参数6字节*/ int Bt_Valve_Handler(ValveCmdType type, rt_uint8_t id, rt_uint8_t *data) { int ret = RT_EOK; switch (type) { case kValveCmdCtr: // 阀门控制 ret = BSP_Bt_Valve_Ctr(valve[id].valve_id, valve[id].valve_mac, WirelessValveClose); // 关阀门 break; case kValveCmdReg: // 阀门注册 ret = BSP_Bt_Register_Valve(valve[id].valve_id, valve[id].valve_mac); break; case kValveCmdRem: // 阀门移除 ret = BSP_Bt_Remove_Valve(valve[id].valve_id, valve[id].valve_mac); break; case kValveCmdRep: // 阀门更换 ret = BSP_Bt_Replace_Valve(valve[id].valve_id, valve[id].valve_mac, data); if (ret == RT_EOK) { rt_memcpy(valve[id].valve_mac, data, 6); Flash_Set_Mac_Addr(valve[id].valve_mac, valve[id].valve_id - 1); } break; default: ret = -RT_ERROR; LOG_E("unknown valve command type"); break; } return ret; } int BSP_Bt_Process(uint8_t *data, uint16_t len) { int ret = 0; uint16_t index = 0; uint8_t data_buf[256] = {0}; // 解析接收到的数据帧,先寻找AA开头,然后再找AA下一个字节,其代表了数据长度,然后找到代表长度的值的长度的下一位,其为校验码,校验码后为结束码0x55, // 如果数据正确,则提取数据,不正确,则不处理 // LOG_HEX("BT_RX_DATA", 16, data, len); LOG_D("len = %d", len); if (len < 4) { // 至少需要 4 个字节:起始码、长度、校验码、结束码 LOG_E("长度不对 [1]"); ; return 1; } while (index < len && data[index] != 0xAA) // 寻找起始码 0xAA { index++; } LOG_D("index = %d", index); uint16_t datalength = data[index + 1]; // 读取数据长度 LOG_D("datalength = %d", datalength); uint8_t rx_sum = data[index + 2 + datalength]; // 读取校验码 uint8_t calculated_sum = XOR_CheckSum(&data[index], datalength + 2); // 计算校验码 if (rx_sum != calculated_sum) { LOG_E("校验和不对 rx_sum[%02X] != calculated_sum[%02X]", rx_sum, calculated_sum); LOG_HEX("bt_rx_data:", 16, data, len); return 4; } if (data[index + 2 + datalength + 1] != 0x55) // 检查结束码 { LOG_E("结束码错误"); return 5; } rt_uint8_t fram_len = datalength + 4; // 当程序走到这里时,就说明接收到了正确的数据帧,开始解析响应 rt_memcpy(data_buf, &data[index], fram_len); switch (data[index + 2]) { case kValveEventCtr: LOG_D("valve control event"); if (data_buf[fram_len - 3] == WirelessValveClose) // 关闭成功 { rt_sem_release(&bt_ctr_sem); } break; case kValveEventReg: if (data_buf[fram_len - 3] == RT_TRUE) // 注册成功) { LOG_I("接收到阀门注册响应:"); LOG_HEX("bt_rx_data:", 16, data_buf, fram_len); Flash_Set_Mac_Addr(&data_buf[4], data[index + 3] - 1); rt_uint8_t num = Flash_Get_Valve_Num(); Flash_Set_Valve_Num(num + 1); rt_sem_release(&bt_reg_sem); } break; case kValveEventRem: if (data_buf[fram_len - 3] == RT_TRUE) // 移除成功 { LOG_D("移除阀门响应成功"); rt_sem_release(&bt_rem_sem); } break; case kValveEventRep: if (data_buf[index + datalength - 3] == RT_TRUE) // 更换成功 { LOG_D("阀门更换响应成功"); rt_sem_release(&bt_rep_sem); } break; case kValveEventStatus: LOG_I("接收到阀门心跳数据:"); LOG_HEX("bt_rx_data:", 16, data_buf, fram_len); // TODO:添加阀门数据处理函数 rt_memcpy(&valve[data_buf[3] - 1], &data_buf[3], sizeof(struct valve_t)); LOG_HEX("valve_data:", 16, (rt_uint8_t *)&valve[data_buf[3] - 1], sizeof(struct valve_t)); break; default: LOG_W("unknow cmd: %02X", data[index + 2]); break; } return ret; } static void BSP_Bt_Parse_Data(void) { rt_size_t len = lwrb_get_full(&bt_lwrb_rx); char *rx_ptr = rt_calloc(1, len + 1); BSP_Bt_Recv_Data(rx_ptr, len); // 发送过来的数据格式为:帧头 + 数据长度 + 事件类型 + 数据 + 校验码 + 帧尾 BSP_Bt_Process(rx_ptr, len); rt_free(rx_ptr); } static void Bt_Thread_Entry(void *parameter) { // 初始化阀门信息 valve[0].valve_id = 1; valve[0].valve_mac[0] = 0XA2; valve[0].valve_mac[1] = 0xB4; valve[0].valve_mac[2] = 0x8F; valve[0].valve_mac[3] = 0x10; valve[0].valve_mac[4] = 0x53; valve[0].valve_mac[5] = 0x5C; Flash_Set_Mac_Addr(valve[0].valve_mac, 0); Flash_Set_Valve_Num(1); LOG_D("Bt_Thread_Entry"); while (1) { if (bt_recv_readline()) { BSP_Bt_Parse_Data(); } } } /* 接收数据回调函数 */ static rt_err_t Bt_Rcv_Cb(rt_device_t dev, rt_size_t size) { rt_sem_release(&bt_rx_sem); return RT_EOK; } int BSP_Bt_Init(void) { rt_err_t ret = RT_EOK; lwrb_init(&bt_lwrb_rx, bt_rx_buffer, sizeof(bt_rx_buffer)); lwrb_reset(&bt_lwrb_rx); /* 查找系统中的串口设备 */ rt_bt_device = rt_device_find(BT_UART); if (!rt_bt_device) { LOG_E("find %s failed!\n", BT_UART); return RT_ERROR; } /* 以中断接收模式打开串口设备 */ if (rt_device_open(rt_bt_device, RT_DEVICE_FLAG_INT_RX) != RT_EOK) { LOG_E("rt_device_open failed!\n"); return RT_ERROR; } rt_sem_init(&bt_rx_sem, "bt_rx_sem", 0, RT_IPC_FLAG_PRIO); /* 接收来自蓝牙主机的信号量 */ rt_sem_init(&bt_ctr_sem, "bt_ctr_sem", 0, RT_IPC_FLAG_PRIO); rt_sem_init(&bt_reg_sem, "bt_reg_sem", 0, RT_IPC_FLAG_PRIO); rt_sem_init(&bt_rem_sem, "bt_rem_sem", 0, RT_IPC_FLAG_PRIO); rt_sem_init(&bt_rep_sem, "bt_rep_sem", 0, RT_IPC_FLAG_PRIO); /* 设置接收回调函数 */ if (rt_device_set_rx_indicate(rt_bt_device, Bt_Rcv_Cb) != RT_EOK) { LOG_E("rt_device_set_rx_indicate failed!\n"); return RT_ERROR; } /* 静态初始化线程 1*/ ret = rt_thread_init(&bt_thread, // 该线程用于数据解析 "bt_thread", Bt_Thread_Entry, RT_NULL, &bt_thread_stack[0], sizeof(bt_thread_stack), BT_THREAD_PRIORITY, BT_THREAD_TIMESLICE); /* 创建成功则启动线程 */ rt_thread_startup(&bt_thread); return ret; } INIT_DEVICE_EXPORT(BSP_Bt_Init); #ifdef TEST_ENABLE static void TEST_BT_Send_Data(int argc, char **argv) { if (argc == 3) { int mode = atoi(argv[1]); int id = atoi(argv[2]) - 1; LOG_D("send data mode: %d id :%d", mode, id); switch (mode) { case 1: Bt_Valve_Handler(kValveCmdCtr, id, RT_NULL); break; case 2: Flash_Set_Valve_Num(1); Bt_Valve_Handler(kValveCmdReg, id, RT_NULL); break; case 3: Bt_Valve_Handler(kValveCmdRem, id, RT_NULL); rt_memset(valve[0].valve_mac, 0, sizeof(struct valve_t)); Flash_Set_Mac_Addr(valve[0].valve_mac, 0); Flash_Set_Valve_Num(0); break; case 4: Bt_Valve_Handler(kValveCmdRep, id, RT_NULL); break; default: break; } } } MSH_CMD_EXPORT(TEST_BT_Send_Data, "TEST_BT_Send_Data"); #endif