/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : uart_Ethernet.h * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include // ETHERNET串口接收的循环缓冲 #define ETHERNET_DATA_COUNT 200 loopbuff_t Ethernet_Buff; uint8_t Ethernet_Buff_Data[sizeof(uint8_t) * (ETHERNET_DATA_COUNT + 1)] = {0}; // ETHERNET串口接收的消息通知 SemaphoreHandle_t Ethernet_semQ = NULL; // ETHERNET串口AT命令接收的循环缓冲 #define ETHERNET_ATDATA_COUNT 50 loopbuff_t Ethernet_ATBuff; uint8_t Ethernet_ATBuff_Data[sizeof(uint8_t) * (ETHERNET_ATDATA_COUNT + 1)] = {0}; // 网口初始化状态 uint8_t Ethernet_initStatus = 0, Ethernet_connected = 0; static void Ethernet_IRQHandler(USART_Handle *huart) { BaseType_t xHigherPriorityTaskWoken; uint8_t c = (uint8_t) huart->Instance->DR; // 加入缓冲 LoopBuff_PutItem(&Ethernet_Buff, &c); // 发消息给任务 xSemaphoreGiveFromISR(Ethernet_semQ, &xHigherPriorityTaskWoken); } static void Ethernet_ATHandler(USART_Handle *huart) { uint8_t c = (uint8_t) huart->Instance->DR; // 加入缓冲 LoopBuff_PutItem(&Ethernet_ATBuff, &c); } void Ethernet_Send(char *buf) { UART_Transmit(&huart3, (uint8_t *) buf, strlen(buf)); } // 非中断方式,直接从串口接收数据 uint16_t Ethernet_Recv(char *buf, uint16_t wait_cnt) { uint16_t recv_cnt = 0; uint32_t stop_seconds; char c; stop_seconds = rf_get_seconds() + 2; while(rf_get_seconds() < stop_seconds) { if(LoopBuff_GetCount(&Ethernet_ATBuff) > 0) { c = *(uint8_t *) LoopBuff_GetDataPtr(&Ethernet_ATBuff, Ethernet_ATBuff.info.rdPtr); LoopBuff_RemoveItems(&Ethernet_ATBuff, 1); printf("%c", c); if(c != '\r' && c != '\n') { buf[recv_cnt++] = c; if(recv_cnt == wait_cnt) break; } } } return recv_cnt; } // 进入AT命令模式 uint8_t Ethernet_ATMode() { uint8_t try_cnt; char buf[3] = {0}; // 进入AT命令模式 for(try_cnt = 0; try_cnt < 3; try_cnt++) { // 先进入AT命令模式 delay_ms(100); Ethernet_Send("+++"); if(Ethernet_Recv(buf, 1) < 1 || buf[0] != 'a') continue; Ethernet_Send("a"); if(Ethernet_Recv(buf, 3) < 3 || strncmp(buf, "+ok", 3) != 0) continue; // 成功进入AT命令模式 delay_ms(100); return 1; } return 0; } uint8_t Ethernet_ATCmd(char *cmd, char *ok_str, char *err_str) { char buf[21], c; uint8_t try_cnt; uint16_t recv_cnt = 0; uint32_t stop_seconds; memset(buf, 0, sizeof(buf)); for(try_cnt = 0; try_cnt < 3; try_cnt++) { // 清空串口缓冲区 LoopBuff_Clear(&Ethernet_ATBuff); // 发送命令 Ethernet_Send(cmd); Ethernet_Send("\r"); // 等待返回数据 stop_seconds = rf_get_seconds() + 2; while(rf_get_seconds() < stop_seconds) { if(LoopBuff_GetCount(&Ethernet_ATBuff) > 0) { c = *(uint8_t *) LoopBuff_GetDataPtr(&Ethernet_ATBuff, Ethernet_ATBuff.info.rdPtr); LoopBuff_RemoveItems(&Ethernet_ATBuff, 1); printf("%c", c); if(c != '\r' && c != '\n') { buf[recv_cnt++] = c; if(strstr(buf, ok_str) != NULL) return 1; if(strstr(buf, err_str) != NULL) return 0; } } } } return 0; } void Ethernet_Open() { // 创建消息队列 LoopBuff_Create(&Ethernet_Buff, sizeof(uint8_t), ETHERNET_DATA_COUNT, 0, (uint32_t) Ethernet_Buff_Data); LoopBuff_Create(&Ethernet_ATBuff, sizeof(uint8_t), ETHERNET_ATDATA_COUNT, 0, (uint32_t) Ethernet_ATBuff_Data); // 创建信号量 Ethernet_semQ = xSemaphoreCreateBinary(); SET_BIT(USART3->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); LL_USART_Enable(USART3); } // 本函数要用到中断,只能在任务启动以后执行 void Ethernet_Config() { huart3.RxISR = Ethernet_ATHandler; delay_ms(100); VCC_ETHERNET_ON(); delay_ms(1000); // 设置状态 Ethernet_initStatus = 0; Ethernet_connected = 0; // 设置Usr_K3工作方式 #if 1 // 进入AT命令模式 if(!Ethernet_ATMode()) return; // 设置命令不回显 if(!Ethernet_ATCmd("AT+E=OFF", "+OK", "+ERR")) return; // 设置DHCP if(!Ethernet_ATCmd("AT+WANN=DHCP", "+OK", "+ERR")) // if(!Ethernet_ATCmd("AT+WANN=STATIC,192.168.0.3,255.255.255.0,192.168.0.1", "+OK", "+ERR")) return; // 设置DNS(如DHCP配置可不设DNS) // if(!Ethernet_ATCmd("AT+DNS=202.106.0.20", "+OK", "+ERR")) // return; // 设置TCP模式、服务器、端口 if(RF_APP == RF_APP_AJH) { // if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,171.88.5.52,8061", "+OK", "+ERR")) // 公司路由器 if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,extra.cd-ls.cn,8061", "+OK", "+ERR")) // if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,data.ajhiot.com,8088", "+OK", "+ERR")) // if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,114.55.209.85,8088", "+OK", "+ERR")) // data.ajhiot.com // if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,192.168.0.2,8061", "+OK", "+ERR")) // 直连电脑 return; } else if(RF_APP == RF_APP_PRAX) { if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,tts.praxair.com.cn,7005", "+OK", "+ERR")) return; } else { if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,data.cd-ls.cn,8088", "+OK", "+ERR")) return; } // 关闭串口心跳包 if(!Ethernet_ATCmd("AT+HEARTEN1=OFF", "+OK", "+ERR")) return; // 关闭串口注册包 if(!Ethernet_ATCmd("AT+REGEN1=OFF", "+OK", "+ERR")) return; // 关闭短连接功能 if(!Ethernet_ATCmd("AT+SOCKSL1=OFF", "+OK", "+ERR")) return; // 设置超时重启时间:60秒 if(!Ethernet_ATCmd("AT+RSTIM=60", "+OK", "+ERR")) return; // 连接前是否清理串口缓存? if(!Ethernet_ATCmd("AT+UARTCLBUF=ON", "+OK", "+ERR")) return; // 设为默认参数 if(!Ethernet_ATCmd("AT+CFGTF", "saved", "+ERR")) return; // 重启模块 if(!Ethernet_ATCmd("AT+Z", "OK", "+ERR")) return; #endif /* Enable UART3 interrupt */ huart3.RxISR = Ethernet_IRQHandler; // 设置状态 Ethernet_initStatus = 1; } // 检查服务器连接情况 uint8_t Ethernet_IsConnected() { u8 try_count; u8 atMode = 0, connected = 0, tranMode = 0; huart3.RxISR = Ethernet_ATHandler; // 清除串口缓冲数据 LoopBuff_Clear(&Ethernet_ATBuff); // 进入AT命令模式,3次不成功则复位 for(try_count = 0; try_count < 3; try_count++) { if(Ethernet_ATMode()) { atMode = 1; break; } osDelay(500); } if(atMode) { // 检查是否连上网络 connected = Ethernet_ATCmd("AT+SOCKLKA1", "+OK=CONNECTED", "+OK=CONNECTING"); // 进入透传模式,3次不成功则复位 for(try_count = 0; try_count < 3; try_count++) { if(Ethernet_ATCmd("AT+ENTM", "+OK", "+ERR")) { tranMode = 1; break; } osDelay(500); } } huart3.RxISR = Ethernet_IRQHandler; return (atMode && connected && tranMode); }