/** * author wulianwei * title BC260Y模块驱动 */ #include "stm32f10x.h" #include "bc26.h" #include "sys.h" #include "module_wrapper.h" #include "at.h" //C库 #include #include extern uart_recv_t uart_recv; extern valid_data_t valid_data; uint8_t err_cout = MODULE_FAIL; //从睡眠中唤醒BC26 static void bc26_wake(void) { at_send_simple_cmd(AT); //AT触发 } //========================================================== // 函数名称: bc26_send_data // // 函数功能: 发送数据 // // 入口参数: data:数据(数组) // len:长度 // // 返回参数: 无 // // 说明: //========================================================== static int bc26_send_data(const void *data, int len) { char cmdBuf[SEND_SIZE+20]={0}; char hexData[SEND_SIZE] = {0}; bc26_wake(); //bc26_tcp_reconnect(); byteToHexStr(data,hexData,len); snprintf(cmdBuf,SEND_SIZE,"AT+QISEND=0,%d,\"%s\",%d\r\n", len,hexData,0); //发送数据,返回后不释放链接 // UsartPrintf(USART_DEBUG, "raisend:%s\r\n",cmdBuf); if(!at_send_cmd(cmdBuf, "SEND OK")) { // Usart_SendString(USART2, data, len); //发送设备连接请求数据 return 0; } return -1; } static int bc26_send_data_rai(const void *data, int len,int rai) { char cmdBuf[SEND_SIZE+20]={0}; char hexData[SEND_SIZE] = {0}; bc26_wake(); delay_ms(3); bc26_wake(); //清空接收缓存 //bc26_tcp_reconnect(); len = len<=SEND_SIZE/2 ? len:SEND_SIZE/2; byteToHexStr(data,hexData, len); snprintf(cmdBuf,sizeof(cmdBuf),"AT+QISEND=0,%d,\"%s\",%d\r\n", len,hexData,rai); //发送数据,返回后释放链接 //UsartPrintf(USART_DEBUG, "\r\nraisend:%s,%d\r\n",cmdBuf,strlen(cmdBuf)); if(!at_send_cmd(cmdBuf, "SEND OK")) { // Usart_SendString(USART2, data, len); //发送设备连接请求数据 return 0; } return -1; } //========================================================== // 函数名称: bc26_get_data // // 函数功能: 获取平台返回的数据 // // 入口参数: data:存储有效数据(数组),len:有效数据长度,timeOut:等待的时间(ms) // // 返回参数: 平台返回的原始数据 // // 说明: 不同网络设备返回的格式不同,需要去调试 //========================================================== static int bc26_get_data(void *data,int len,int timeOut) { int minLen = 0; char *recvdiff[4] = {0};//分割字符串地址 char recvbuf[RECV_SIZE] = {0}; int data_len = 0;//有效数据长度 char *recvSign = "+QIURC: \"recv\",0,"; if(!uart_recv_match_wait(recvSign,timeOut)) { uart_recv.start_addr = strstr(uart_recv.buf,recvSign); UsartPrintf(USART_DEBUG, "返回数据:%d,%s\r\n",uart_recv.len,uart_recv.start_addr); memcpy((char*)recvbuf, (char*)uart_recv.start_addr, uart_recv.len); split((char*)recvbuf,",",recvdiff,sizeof(recvdiff)); data_len = my_atoi(recvdiff[2]); minLen = data_len < len? data_len : len; memcpy(data,(char*)recvdiff[3]+1,minLen); //有效数据前后多了一个双引号 uart_recv_clear(); return data_len; } uart_recv_clear(); return -1; } static void bc26_restart(void) { UsartPrintf(USART_DEBUG, "自动重启\r\n"); BC26_RST_HIGH(); delay_ms(60); BC26_RST_LOW(); uart_recv_clear(); } static int bc26_config(void) { char recv[300] = {0}; at_send_cmd_back_wait(AT,recv,sizeof(recv),100); //AT触发 UsartPrintf(USART_DEBUG, "1.休眠\r\n"); at_send_cmd_back(LIGHTSLEEP,recv,sizeof(recv)); if(!strstr(recv,"OK")) { UsartPrintf(USART_DEBUG,"休眠失败\r\n"); return -1; } UsartPrintf(USART_DEBUG, "2.不回显命令\r\n"); at_send_cmd_back(ATE0,recv,sizeof(recv)); if(!strstr(recv,"OK")) { UsartPrintf(USART_DEBUG,"禁止回显失败\r\n"); return -1; } UsartPrintf(USART_DEBUG, "3.16进制发送数据\r\n"); at_send_cmd_back(QICFG,recv,sizeof(recv)); if(!strstr(recv,"OK")) { UsartPrintf(USART_DEBUG,"16进制发送数据失败\r\n"); return -1; } module_init_status = MODULE_OK; return 0; } //========================================================== // 函数名称: bc26_init // // 函数功能: 初始化BC26 // // 入口参数: 无 // // 返回参数: 0 成功 1失败 // // 说明: //========================================================== static int bc26_init(void) { return bc26_config(); } /** * @Title 模块ue功能关闭 * @Return 0:成功,-1:失败 */ static int bc26_ue_down(void) { bc26_wake();//唤醒 delay_ms(10); if(at_send_cmd(CFUN0,"OK")) { UsartPrintf(USART_DEBUG, "UE功能关闭\r\n"); return -1; } tcp_connect_status = TCP_CLOSED; //tcp断开 UsartPrintf(USART_DEBUG, "UE功能关闭失败\r\n"); return 0; } /** * @Title TCP连接 * @Param ip:地址, port:端口 */ static void bc26_tcp_connect(const char *ip, const char *port) { char conCmd[200]={0}; bc26_wake();//唤醒 UsartPrintf(USART_DEBUG, "连接TCP服务器\r\n"); snprintf(conCmd,sizeof(conCmd),QIOPEN,ip,port); at_send_simple_cmd(conCmd); tcp_connect_status = TCP_CONNECTING; } /** * @Title 打开UDP端口 * @Param ip:地址, port:端口 */ static void bc26_udp_open(const char *ip, const char *port) { char conCmd[200]={0}; // bc26_wake();//唤醒 snprintf(conCmd,sizeof(conCmd),QIOPENUDP,ip,port); UsartPrintf(USART_DEBUG, "连接UDP服务器\r\n"); at_send_simple_cmd(conCmd); tcp_connect_status = TCP_CONNECTING; } /** * @Title TCP通道关闭 * @Return 0:成功,-1:失败 */ static int bc26_tcp_close(void) { bc26_wake();//唤醒 delay_ms(10); //UsartPrintf(USART_DEBUG, "断开TCP操作:%s\r\n",QICLOSE); if(at_send_cmd(QICLOSE,"CLOSE OK")) { return -1; } tcp_connect_status = TCP_CLOSED; //tcp断开 UsartPrintf(USART_DEBUG, "断开TCP服务器\r\n"); return 0; } /** * @Title 判断tcp连接状态 * @Return 0 保持连接,-1 断开连接 */ static int bc26_tcp_state(void) { char *statebuf[8] ={0}; char recvbuf[200] = {0}; bc26_wake(); delay_ms(15); at_send_cmd_back(QISTATE,recvbuf,sizeof(recvbuf)); if(strstr(recvbuf,"OK")) { if(strstr((char *)recvbuf,"+QISTATE: 0")) { split((char*)recvbuf,",",statebuf,sizeof(statebuf)); if(statebuf[5]) { if(*(statebuf[5]) == '2') { tcp_connect_status = TCP_OPEN; //tcp连接 UsartPrintf(USART_DEBUG, "TCP服务器保持链接\r\n"); return 0; } } } } tcp_connect_status = TCP_CLOSED; //tcp断开 UsartPrintf(USART_DEBUG, "TCP服务器已断开\r\n"); return -1; } static void bc26_tcp_reconnect(const char *ip, const char *port) { bc26_wake();//唤醒 if(bc26_tcp_state()) { UsartPrintf(USART_DEBUG, "重连服务器\r\n"); bc26_tcp_close(); bc26_tcp_connect(ip,port); } } static void bc26_udp_reopen(const char *ip, const char *port) { bc26_wake();//唤醒 if(bc26_tcp_state()) { UsartPrintf(USART_DEBUG, "重连服务器\r\n"); bc26_tcp_close(); bc26_udp_open(ip,port); } } static void bc26_tcp_online_event(void) { UsartPrintf(USART_DEBUG, "bc26_tcp_online_event\r\n"); tcp_connect_status = TCP_OPEN;// tcp在线 } static void bc26_tcp_close_event(void) { UsartPrintf(USART_DEBUG, "bc26_tcp_close_event\r\n"); tcp_connect_status = TCP_CLOSED; //tcp断线 } static void bc26_recv_event(void) { int i; int minLen = 0; char *recvdiff[4] = {0};//分割字符串地址 char recvbuf[RECV_SIZE] = {0}; int data_len = 0;//有效数据长度 int valid_data_size = sizeof(valid_data.buf); uart_recv_wait(150);//有效数据返回有延迟 memcpy((char*)recvbuf,(char*)uart_recv.start_addr,uart_recv.len); splitCharLimit((char*)recvbuf,',',recvdiff,4); data_len = my_atoi(recvdiff[2]); minLen = data_len < valid_data_size-1? data_len : valid_data_size-1; valid_data.len = minLen; memcpy(valid_data.buf,(char*)recvdiff[3]+1,minLen); //有效数据前后多了一个双引号 UsartPrintf(USART_DEBUG, "bc26_recv_event\r\n"); } void bc26_error_event(void) { UsartPrintf(USART_DEBUG, "error_event:%s\r\n",uart_recv.buf); if(err_cout == 5) //连续出错5次UsartPrintf,重启模块 { err_cout= 0; module_start_status = MODULE_FAIL; module_init_status = MODULE_FAIL; } } void bc26_sleep_event(void) { UsartPrintf(USART_DEBUG, "ENTER DEEPSLEEP\r\n",uart_recv.buf); } static void bc26_restart_event(void) { UsartPrintf(USART_DEBUG, "bc26_restart_event:%s\r\n",uart_recv.buf); module_start_status = MODULE_OK; //bc260启动成功 module_init_status = MODULE_FAIL; //重新配置参数 tcp_connect_status = TCP_CLOSED;//TCP 需要重连 bc26_config();//配置 } at_event_t bc26_at_event[] = { { "+IP:", bc26_restart_event}, //tcp连接成功 { "+QIOPEN: 0,0", bc26_tcp_online_event}, //tcp连接成功 { "+QIURC: \"closed\",0", bc26_tcp_close_event}, //tcp断开链接 { "+QIURC: \"recv\",0", bc26_recv_event}, { "ERROR", bc26_error_event}, { "+QNBIOTEVENT: \"ENTER DEEPSLEEP\"", bc26_sleep_event} }; static void bc26_handle_event(void) { int i = 0; char *start_addr; if(uart_recv.len ==0) return; for(i=0;ievent_header); if(start_addr) { if(event->event_callback == bc26_error_event) { err_cout++; } else { err_cout=0; } uart_recv.start_addr = start_addr; event->event_callback(); uart_recv_clear(); break; } } } at_module_t at_module_bc26 = { .start = bc26_restart, .init = bc26_init, .connect = bc26_tcp_connect, .reconnect = bc26_tcp_reconnect, .udpreopen = bc26_udp_reopen, .tcpstate = bc26_tcp_state, .send = bc26_send_data, .send_rai = bc26_send_data_rai, .recv_timeout = bc26_get_data, .close = bc26_tcp_close, .handle_event = bc26_handle_event, .cmd_back = at_send_cmd_back, .cmd = at_send_simple_cmd, .low_power = bc26_ue_down, .udpopen = bc26_udp_open, }; int bc26_sal_init() { if(at_module_register(&at_module_bc26)) { module_init_status = MODULE_FAIL; return -1; } if(at_module_init()) { module_init_status = MODULE_FAIL; return -1; } module_init_status = MODULE_OK; return 0; } void bc26_sal_register() { at_module_register(&at_module_bc26); }