#include #include #include "usb.h" #include "sys.h" #include "systick.h" #include "usart.h" #include "led.h" #include "beep.h" #include "FreeRTOS.h" #include "timer.h" #include "queue.h" #include "semphr.h" #include "task.h" #include "sysport.h" #include "mac.h" #include "stm32Temp.h" #include "watchdog.h" #include "rtc.h" #include "user_tcp.h" #include "key.h" #include "logflash.h" #include "user_http.h" #include "ec20module.h" #include "ec20tcp.h" #include "ec20http.h" #include "userapp.h" #include "user_flash.h" #include "usercmd.h" #include "user_oled.h" #include "user_key.h" /********************************************************************************** *内部函数声明 **********************************************************************************/ /*FreeRTOS任务函数声明*/ void StartTask(void *pvParameters); //开始任务函数 :初始化、创建其他任务 void NetTask(void *pvParameters); //网络任务函数 :初始化网络、维护网络 void Rs232Task(void *pvParameters); //Rs232处理函数 :处理RS232串口接收的数据 void Rs485Task(void *pvParameters); //Rs485处理函数 :处理RS485串口接收的数据 void LedTask(void *pvParameters); //LED任务函数 :DATA作为500ms呼吸灯 void TcpUrcTask(void *pvParameters); //TCP URC任务函数 :处理TCP协议中EC20返回的URC void TcpDownTask(void *pvParameters); //LTE任务函数 :处理分发4G模块串口帧数据 void TcpHeartTask(void *pvParameters); //TCP心跳任务函数 :TCP心跳 void TcpUpTask(void *pvParameters); //TCP上行任务函数 :TCP心跳,上行sTcp0Queue队列里的数据 void MenuTask(void *pvParameters); //车牌处理任务函数:处理摄像头任务发来的车牌 void ListTask(void *pvParameters); //LIST任务函数 :打印各个任务信息 void UcmdTask(void *pvParameters); //用户命令任务函数:处理用户命令(用户命令可能来自USB口或者EC20的TCP下行数据) void UsbTask(void *pvParameters); //USB任务函数 :处理USB串口数据 /********************************************************************************** *内部常变量 **********************************************************************************/ /*FreeRTOS任务优先级*/ #define START_TASK_PRIO 32 //开始任务 #define NET_TASK_PRIO 2 //网络任务 #define RS232_TASK_PRIO 9 //任务优先级 #define RS485_TASK_PRIO 5 //任务优先级 #define LED_TASK_PRIO 31 //任务优先级 #define TCPURC_TASK_PRIO 3 //任务优先级 #define TCPDOWN_TASK_PRIO 1 //任务优先级 #define MENU_TASK_PRIO 3 //任务优先级 #define LIST_TASK_PRIO 32 //任务优先级 #define TCPUP_TASK_PRIO 7 //任务优先级 #define TCPHEART_TASK_PRIO 6 //任务优先级 #define UCMD_TASK_PRIO 29 //任务优先级 #define DEBUG_TASK_PRIO 1 //任务优先级 /*FreeRTOS任务堆栈大小*/ #define START_STK_SIZE 256 //任务堆栈大小 //256个入栈空间(256*4 bytes) #define NET_STK_SIZE 256 //任务堆栈大小 //256个入栈空间(256*4 bytes) #define RS232_STK_SIZE 256 //任务堆栈大小 //256个入栈空间(256*4 bytes) #define RS485_STK_SIZE 256 //任务堆栈大小 //256个入栈空间(256*4 bytes) #define LED_STK_SIZE 128 //任务堆栈大小 #define TCPURC_STK_SIZE 256 //任务堆栈大小 #define TCPDOWN_STK_SIZE 512 //任务堆栈大小 #define MENU_STK_SIZE 256 //任务堆栈大小 #define LIST_STK_SIZE 256 //任务堆栈大小 #define TCPUP_STK_SIZE 256 //任务堆栈大小 #define TCPHEART_STK_SIZE 128 //任务堆栈大小 #define UCMD_STK_SIZE 256 //任务堆栈大小 #define DEBUG_STK_SIZE 256 //任务堆栈大小 /*FreeRTOS任务句柄*/ TaskHandle_t StartTaskHandler; //任务句柄 TaskHandle_t NetTaskHandler; //任务句柄 TaskHandle_t rs232TaskHandler; //任务句柄 TaskHandle_t rs485TaskHandler; //任务句柄 TaskHandle_t LedTaskHandler; //任务句柄 TaskHandle_t TcpUrcTaskHandler; //任务句柄 TaskHandle_t tcpDownTaskHandler; //任务句柄 TaskHandle_t menuTaskHandler; //任务句柄 TaskHandle_t ListTaskHandler; //任务句柄 TaskHandle_t TcpUpTaskHandler; //任务句柄 TaskHandle_t TcpHeartTaskHandler; //任务句柄 TaskHandle_t UcmdTaskHandler; //任务句柄 TaskHandle_t DebugTaskHandler; //任务句柄 /*FreeRTOS软件定时器句柄*/ TimerHandle_t timeRefresh_h ; //显示屏时间刷新 int main(void) { NVIC_SetVectorTable(FLASH_BASE, FLASH_OFFSET) ; //设置中断向量表的位置和偏移量 SCB->VTOR = FLASH_BASE | FLASH_OFFSET ; Watchdog_Feed() ; //独立看门狗喂狗 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4) ; //设置系统中断优先级分组4 无子优先级、0~15共计16个抢占优先级 InitIapFlashConfig(&uIapFlash) ; //读出FLASH中的Iap配置,初始化共用体变量uIapFlash,最后重新写入FLASH中 InitAppFlashConfig(&uAppFlash) ; //读出FLASH中的App配置,初始化共用体变量uAppFlash,最后重新写入FLASH中 InitApplictationState(&gateApp); //初始化结构体变量gateApp UsbInit(222500) ; //调试串口、串口转USB口初始化 Watchdog_Feed() ; /*创建开始任务。*/ xTaskCreate((TaskFunction_t )StartTask, //任务函数 (const char* )"start_task", //任务名称 (uint16_t )START_STK_SIZE, //任务堆栈大小 (void* )NULL, //传递给任务函数的参数 (UBaseType_t )START_TASK_PRIO, //任务优先级 (TaskHandle_t* )&StartTaskHandler //任务句柄 ) ; vTaskStartScheduler() ; //开启任务调度 以上代码段系统还未启动,所有可屏蔽中断都出去屏蔽状态。 } //开始任务任务函数 void StartTask(void *pvParameters) { Watchdog_Feed() ; //看门狗喂狗 taskENTER_CRITICAL(); //进入临界区 Board_Init() ; //硬件驱动初始化和功能块初始化 HomeMenu() ; //OLED显示主界面 /*创建OS任务运行状态事件标志位*/ osSafeEventHandler = xEventGroupCreate() ; //OS任务运行状态事件标志组用于监测各个任务的运行状态,如果有任务长时间没有轮询执行,则说明该任务异常挂起 /*创建网络状态事件标志位*/ netEventHandler = xEventGroupCreate() ; //网络状态事件标志位,相当于一个状态机,标志网络状态的各个环节 /*创建EC20资源互斥信号量*/ ec20MutexSemaphore = xSemaphoreCreateMutex(); //创建EC20资源互斥信号量,EC20模块需要有严格的命令时序,所以无论哪个任务需要操作EC20都需要等待EC20资源空闲。 /*创建软件定时器*/ timeRefresh_h = xTimerCreate((const char*)"Refresh Time", (TickType_t)1*configTICK_RATE_HZ, (UBaseType_t)pdTRUE, (void*)1, (TimerCallbackFunction_t)RefreshOledTime ) ; //显示屏第4行刷新定时器 xTimerStart(timeRefresh_h, 0) ; //OLED更新时间OS软件定时器打开 Watchdog_Feed() ; /*创建任务*/ xTaskCreate((TaskFunction_t)NetTask, (const char*)"NetTask", (uint16_t)NET_STK_SIZE, (void*)NULL, (UBaseType_t)NET_TASK_PRIO, (TaskHandle_t*)&NetTaskHandler); xTaskCreate((TaskFunction_t)Rs232Task, (const char*)"Rs232Task", (uint16_t)RS232_STK_SIZE, (void*)NULL, (UBaseType_t)RS232_TASK_PRIO, (TaskHandle_t*)&rs232TaskHandler); xTaskCreate((TaskFunction_t)Rs485Task, (const char*)"Rs485Task", (uint16_t)RS485_STK_SIZE, (void*)NULL, (UBaseType_t)RS485_TASK_PRIO, (TaskHandle_t*)&rs485TaskHandler); xTaskCreate((TaskFunction_t)LedTask, (const char*)"LedTask", (uint16_t)LED_STK_SIZE, (void*)NULL, (UBaseType_t)LED_TASK_PRIO, (TaskHandle_t*)&LedTaskHandler); xTaskCreate((TaskFunction_t)MenuTask, (const char*)"MenuTask", (uint16_t)MENU_STK_SIZE, (void*)NULL, (UBaseType_t)MENU_TASK_PRIO, (TaskHandle_t*)&menuTaskHandler); xTaskCreate((TaskFunction_t)TcpHeartTask,(const char*)"TcpHeartTask",(uint16_t)TCPHEART_STK_SIZE,(void*)NULL, (UBaseType_t)TCPHEART_TASK_PRIO, (TaskHandle_t*)&TcpHeartTaskHandler); xTaskCreate((TaskFunction_t)TcpUpTask, (const char*)"TcpUpTask", (uint16_t)TCPUP_STK_SIZE, (void*)NULL, (UBaseType_t)TCPUP_TASK_PRIO, (TaskHandle_t*)&TcpUpTaskHandler); xTaskCreate((TaskFunction_t)UcmdTask, (const char*)"UcmdTask", (uint16_t)UCMD_STK_SIZE, (void*)NULL, (UBaseType_t)UCMD_TASK_PRIO, (TaskHandle_t*)&UcmdTaskHandler); xTaskCreate((TaskFunction_t)TcpUrcTask, (const char*)"TcpUrcTask", (uint16_t)TCPURC_STK_SIZE, (void*)NULL, (UBaseType_t)TCPURC_TASK_PRIO, (TaskHandle_t*)&TcpUrcTaskHandler); xTaskCreate((TaskFunction_t)TcpDownTask, (const char*)"TcpDownTask", (uint16_t)TCPDOWN_STK_SIZE, (void*)NULL, (UBaseType_t)TCPDOWN_TASK_PRIO, (TaskHandle_t*)&tcpDownTaskHandler); xTaskCreate((TaskFunction_t)UsbTask, (const char*)"Debug_task", (uint16_t)DEBUG_STK_SIZE, (void*)NULL, (UBaseType_t)DEBUG_TASK_PRIO, (TaskHandle_t*)&DebugTaskHandler); xTaskCreate((TaskFunction_t)ListTask, (const char*)"ListTask", (uint16_t)LIST_STK_SIZE, (void*)NULL, (UBaseType_t)LIST_TASK_PRIO, (TaskHandle_t*)&ListTaskHandler); vTaskDelete(StartTaskHandler) ; //删除开始任务 taskEXIT_CRITICAL() ; //退出临界区 } /********************************************************************************************************************* * 网络任务函数 *********************************************************************************************************************/ void NetTask(void *pvParameters) { while(1) //EC20初始化过程对时序要求很高,所以在此期间需要完全占用EC20资源 { SETNETTASKOK ; //网络任务已运行标志 static uint8_t failedTimes = 0 ; if( GETUSERNETSTATE ) //MODULEBIT_0\NETREGBIT_1\TCPBIT_2\HTTPBIT_3 标志位全部置1,说明网络全部正常 { failedTimes = 0 ; //网络维护失败计次清零 } else //MODULEBIT_0\NETREGBIT_1\TCPBIT_2\HTTPBIT_3 标志位全部置1,说明网络全部正常 { failedTimes++ ; //网络维护失败计次累加 if( failedTimes>2 ) //网络维护失败计次达到2次 直接重启系统 { WriteLogToFlash("系统网络崩溃,重启系统!") ; SystemSoftReset() ; } OccpyEc20(60*configTICK_RATE_HZ, __FILE__, __LINE__) ; //抢占EC20资源,超时时间位60S,如果超时则重启系统 RunResult runResult = TIMEOUT ; if( GETMODULESTATE == STATE_ERR ) /*EC20没有module初始化成功则执行*/ { StatusBarPrintf("握手中:") ; //显示屏状态栏显示“握手中:” runResult = EC20_Module_Init() ; //需要保证串口通信正常且关闭模块串口ECHO成功 if( RUNOK == runResult) /*模块UART \gpio\POW\ECHO\RELESE皆无异常*/ { SETMODULEOK ; //设置“标志位0:EC20 moudle初始化状态 STATE_OK" AppLogPrintf("握手成功") ; } else /*EC20_Module_Init初始化失败不做异常处理,该任务会一直运行EC20_Module_Init()*/ { WriteLogToFlash("模块安装异常!") ; AppLogPrintf("握手失败") ; } } if( GETMODULESTATE == STATE_OK && GETNETREGSTATE == STATE_ERR ) //EC20module初始化完成,且CSPS初始化未完成,则进行CS、PS初始化 { StatusBarPrintf("入网中:") ; //显示屏状态栏显示“入网中” char *errInfo = portMalloc(30) ; runResult = EC20_Net_Reg(errInfo, 30) ; //连接运营商核心网,即CS SERVER、PS SERVER if( RUNOK == runResult) // EC20_Net_Reg(SIM/CS/PS)皆无异常则往下执行 { SETNETREGOK ; //设置”标志位1:EC20 EC20_Net_Reg初始化状态 STATE_OK“ } else //1、EC20_Net_Reg异常,需要重新进行EC20_Module_Init; 2、模块关机 { WriteLogToFlash(errInfo) ; SETMODULEERR ; //设置“标志位0:EC20 moudle初始化状态 STATE_ERR" EC20_CLOSE() ; //EC20关机 } AppLogPrintf(errInfo) ; //提示错误:请插入SIM卡、SIM欠费、CSQ portFree(errInfo) ; } if( (GETMODULESTATE == STATE_OK) && (GETNETREGSTATE == STATE_OK) && (GETTCPSTATE == STATE_ERR) ) //EC20module、EC20_Net_Reg初始化都完成,则进行AppTcpInit初始化 { StatusBarPrintf("连接TCP服务器:") ; //显示屏状态栏显示“连接TCP服务器:” runResult = AppTcpInit() ; //TCP PDP初始化 SOCKET连接 if( RUNOK == runResult) //TCP连接成功 { SETTCPOK ; //设置”标志位2:EC20 TCP状态 STATE_OK““ TcpWritedata( TCPLOGFRAME, "Device tcp connetced!") ; //上传TCP数据,更新服务器硬件客户端列表 AppLogPrintf("TCP连接成功") ; } else //TCP连接失败不影响主业务逻辑,所以TCP异常只做重新初始化,不做异常处理 { SETTCPERR ; //设置”标志位2:EC20 TCP状态 STATE_ERR AppLogPrintf("TCP连接失败") ; WriteLogToFlash("TCP连接失败!") ; } } if( (GETMODULESTATE == STATE_OK) && (GETNETREGSTATE == STATE_OK) && (GETHTTPSTATE == STATE_ERR) ) //EC20module、EC20_Net_Reg初始化都 完成,则进行Http_Init { runResult = Http_Init() ; //Http PDP /HTTP Config if( RUNOK == runResult) //Http 初始化正常 { SETHTTPOK ; //设置”标志位3:EC20 HTTP请求状态 STATE_OK“““ StatusBarPrintf("注册中:") ; //显示屏显示“注册中:” runResult = Reg_Post() ; //通过苏宁提供的对时接口对时注册 TcpWritedata( TCPLOGFRAME, "Device Register!") ; //TCP上报注册结果 if( RUNOK != runResult) //Http 请求数据失败,严重错误,直接重启系统 { WriteLogToFlash("Http初始化OK,注册请求失败,重启系统!") ; SystemSoftReset() ; //系统重启 } AppLogPrintf("硬件注册成功!") ; RefreshOledTime() ; //OLED更新时间 } else //Http 初始化异常 直接重启EC20重新初始化 { SETHTTPERR ; AppLogPrintf("HTTP初始化失败") ; WriteLogToFlash("HTTP初始化失败!") ; } } if( GETUSERNETSTATE ) //MODULEBIT_0\NETREGBIT_1\TCPBIT_2\HTTPBIT_3 标志位全部置1,说明网络全部正常 { EC20_Query_CSQ(sEc20Param.csq) ; //获取CSQ的值 EC20_Query_Voltage(sEc20Param.ec20Voltage) ; //获取EC20电压值 DisplayStatusBar() ; //状态栏显示信号质量和电压 failedTimes = 0 ; //网络维护失败计次清零 } RELESE_EC20(); //释放EC20资源 AppLogPrintf("释放EC20资源!") ; } vTaskDelay(5*configTICK_RATE_HZ) ; //最高网络维护频率:5S/次 } } /********************************************************************************************************************* * RS232数据处理任务函数 *********************************************************************************************************************/ void Rs232Task(void *pvParameters) { while(1) { char *buf = portMalloc(1024) ; u16 len = 0 ; if( RW_OK == GetQueueMemData(&sRS232Queue, buf, &len)) //从sRS232Queue帧缓冲区中获取一帧数据准备处理 { AppLogPrintf("Rs232 recdata:%s .", buf) ; //将RS232接收的帧数据通过USB输出,用户可以在此对帧数据做其他处理 } portFree(buf) ; vTaskDelay(1*configTICK_RATE_HZ) ; //处理RS232数据:1S/次 } } /********************************************************************************************************************* * 同步VIP车牌任务函数 *********************************************************************************************************************/ void Rs485Task(void *pvParameters) { while(1) { char *buf = portMalloc(1024) ; u16 len = 0 ; if( RW_OK == GetQueueMemData(&sRS485Queue, buf, &len)) //从sRS485Queue帧缓冲区中获取一帧数据准备处理 { AppLogPrintf("Rs485 recdata:%s .", buf) ; //将RS485接收的帧数据通过USB输出,用户可以在此对帧数据做其他处理 } portFree(buf) ; vTaskDelay(1*configTICK_RATE_HZ) ; //处理RS485数据:1S/次 } } /********************************************************************************************************************* * 车牌接收及处理任务函数 *********************************************************************************************************************/ void MenuTask(void *pvParameters) { while(1) { GetKeylnput() ; //执行菜单处理函数 vTaskDelay(20) ; //20/configTICK_RATE_HZ=0.2S运行一次 } } /********************************************************************************************************************* * 用户命令处理任务函数 *********************************************************************************************************************/ void UcmdTask(void *pvParameters) { while(1) { SETUCMDTASKOK ; char *buf = portMalloc(512) ; uint16_t len = 0 ; if(RW_OK == GetQueueMemData(&sUsercmdQueue, buf, &len)) //从sUsercmdQueue帧缓冲区中获取一帧数据准备处理 { Cmd_Process(buf, len) ; //处理用户帧命令 } portFree(buf) ; vTaskDelay(0.5*configTICK_RATE_HZ); } } /********************************************************************************************************************* * DATA灯闪烁任务函数 *********************************************************************************************************************/ void LedTask(void *pvParameters) { while(1) { Watchdog_Feed() ; Data_Led_Reverse() ; //DATA LED灯翻转 Beep_Reverse() ; //蜂鸣器翻转 /* OledPrintf(LINE_LEFT, HIGH_12, LINE4, (char*)uCalendar.bytes) ; // if( times >= 0xFFFE) //times累加器溢出则清零 // { // times = 0 ; // } // if( (times % CHECKTASKINTERVAL) == 0) //到达检测网络运行状态的时间 // { // if(GETTASKOSSAFE == STATE_OK) //有任务在CHECKTASKINTERVAL时间内没有被运行 直接记录日志然后重启系统 // { // AppLogPrintf("各任务运行正常!Task事件组:0x%x !", READOSSAFEEVENT) ; // RESETOSSAFEEVENT ; //清除各任务运行正常标志位 // } // else // { // char *buf = portMalloc(128) ; // snprintf( buf, 128, "存在任务运行异常,Task事件组:0x%x ,设备重启 !", READOSSAFEEVENT) ; // WriteLogToFlash(buf) ; // AppLogPrintf(buf) ; // portFree(buf) ; // SystemSoftReset() ; // } // } */ vTaskDelay(1*configTICK_RATE_HZ) ; //1S钟运行一次 } } /********************************************************************************************************************* * 任务信息列出任务函数 *********************************************************************************************************************/ void ListTask(void *pvParameters) { while(1) { /*char *freeRTOS_Info = portMalloc(512) ; vTaskList(freeRTOS_Info) ; size_t freeHeapSize = xPortGetFreeHeapSize() ; printf("\r\n*****************************************************\ \r\n系统信息:\r\n*****************************************************\r\nName\t State Prio Stack Num\r\n\ %s\r\nOS动态内存剩余:freeHeapSize:%dBytes\r\n!\ \r\n******************************************************\r\n ", freeRTOS_Info, freeHeapSize) ; //打印FreeRTOS系统信息 portFree(freeRTOS_Info) ;*/ vTaskDelay(1000*configTICK_RATE_HZ); } } /********************************************************************************************************************* * TCP心跳任务函数 *********************************************************************************************************************/ void TcpUpTask(void *pvParameters) { while(1) { SETTCPUPTASKOK ; //TCPUP任务已正常运行 if( GETTCPSTATE == STATE_OK ) //TCP网络正常 { char *buf = portMalloc(1024) ; uint16_t len = 0 ; if( RW_OK == GetQueueMemData(&sTcp0Queue, buf, &len)) //从sTcp0Queue帧缓冲区中获取一帧数据准备处理 { OccpyEc20(60*configTICK_RATE_HZ, __FILE__, __LINE__) ; //等待获取EC20资源 RunResult status = Tcp_SendData(&sChannal0, (uint8_t*)buf, len) ; if( RUNOK != status) //TCP第一次发送数据失败 { status = Tcp_SendData(&sChannal0, (uint8_t*)buf, len) ; if( RUNOK != status) //TCP第二次发送数据失败 { SETTCPERR ; //TCP网络状态异常 ErrorLogPrintf("Tcp SendData Err!") ; WriteLogToFlash("Tcp SendData Err!") ; //本地FLASH记录 } } RELESE_EC20() ; //释放EC20资源 } portFree(buf) ; } vTaskDelay(50); //50/configTICK_RATE_HZ=0.5S运行一次 } } void TcpHeartTask(void *pvParameters) { while(1) { SETTCPHEARTTASKOK ; //TCP 心跳任务已正常运行 if( GETTCPSTATE == STATE_OK ) //TCP网络正常 { OccpyEc20(60*configTICK_RATE_HZ, __FILE__, __LINE__) ; //等待获取EC20资源 EC20_Query_CSQ( sEc20Param.csq ) ; //获取EC20的信号质量CSQ EC20_Query_Voltage( sEc20Param.ec20Voltage ) ; //获取EC20的供电电压 TcpWritedata( TCPHEARTFRAME, "CSQ:%s, EC20 Voltage:%smV", sEc20Param.csq, sEc20Param.ec20Voltage) ; RELESE_EC20() ; //释放EC20资源 char *oledBuf = (char*)portMalloc(16) ; snprintf(oledBuf, 16, "%smV", sEc20Param.ec20Voltage) ; //显示屏显示EC20电压 DisplayBattery(oledBuf) ; memset(oledBuf, 0, 16) ; snprintf(oledBuf, 16, "CSQ%s", sEc20Param.csq) ; //显示屏显示csq DisplayCsq(oledBuf) ; portFree(oledBuf) ; } vTaskDelay(40*configTICK_RATE_HZ); //30s执行一次TCP上行心跳 } } /********************************************************************************************************************* *TcpUrcTask任务函数 *********************************************************************************************************************/ void TcpUrcTask(void *pvParameters) { while(1) { SETCAMERATASKOK ; //任务已正常运行标志位 char *buf = portMalloc(256) ; uint16_t len = 0 ; if(RW_OK == GetQueueMemData(&sUrcQueue, buf, &len)) //从sUrcQueue帧缓冲区中获取一帧数据准备处理 { TcpUrcType urcType = TcpUrcHandle(buf, len) ; //URC分类解析 switch( urcType ) { case CLOSED: SETTCPERR ; //设置TCP状态为 STATE_ERR ErrorLogPrintf("Tcp server closed .") ; WriteLogToFlash("Tcp server closed .") ; break ; case PDPDEACT: SETMODULEERR ; //设置MODULE状态为 STATE_ERR ErrorLogPrintf("Tcp PDP deact .") ; WriteLogToFlash("Tcp PDP deact .") ; break ; case INCOMING_FULL: ErrorLogPrintf("Tcp incoming full .") ; WriteLogToFlash("Tcp incoming full .") ; break ; case INCOMING_CONT: ErrorLogPrintf("Tcp incoming .") ; WriteLogToFlash("Tcp incoming .") ; break ; default: ErrorLogPrintf("Tcp unknown urc .") ; WriteLogToFlash("Tcp unknown urc .") ; break ; } } portFree(buf) ; vTaskDelay(0.5*configTICK_RATE_HZ); // (0.5*configTICK_RATE_HZ)/configTICK_RATE_HZ = 0.5S 运行一次 } } void TcpDownTask(void *pvParameters) { while(1) { SETLTETASKOK ; //该任务已正常运行标志位 char *buf = portMalloc(1024) ; uint16_t len = 0 ; if(RW_OK == GetQueueMemData(&sTcpQueue, buf, &len)) //从sTcpQueue帧缓冲区中获取一帧数据准备处理 { int pos = 0; pos = kmp(buf, "+QIURC: \"recv\"") ; if( pos>=0) /*判断是否位接收到TCP下行数据*/ { /*(L0142MAC:31FFD405524E353728902251;00&I am heart 5 .$X)*/ char *tcpData = portMalloc(512) ; CopyStr(tcpData, buf+pos, 0x0A, 0x00, 256) ; TcpFrame_S *psRcmd = (TcpFrame_S*)tcpData ; int dataLen = strlen(tcpData) ; //接收数据的长度 if( (psRcmd->head == '(')&& (psRcmd->loadHead == '&')&& (*(tcpData+dataLen-5) == '$')&& (*(tcpData+dataLen-3) == ')') //用户数据帧合法性校验 ) { switch( psRcmd->frameType ) //按照帧类型分类处理 { case TCPCMDFRAME: { if( RW_OK != InsertQueueMemData(&sUsercmdQueue, tcpData, dataLen) ) { ErrorLogPrintf("sUsercmdQueue溢出!") ; } break ; } case TCPSERVERACK: //Tcp server对硬件上行的数据ACK确认回复包 { AppLogPrintf("Tcp server确认收到数据帧:%s ", tcpData) ; break ; } default: { AppLogPrintf("TCP收到下行未知类型数据帧:%s ", tcpData) ; TcpWritedata( TCPCMDBACKFRAME, "TCP收到下行未知类型数据帧") ; break ; } } } else /*tcp下行数据,但是非下行命令帧*/ { AppLogPrintf("TCP收到下行'非'法数据帧:%s ", tcpData) ; } portFree(tcpData) ; } else /*TCP下行数据解析失败*/ { ErrorLogPrintf("TCP 下行数据解析失败:%s ", buf) ; } } portFree(buf) ; vTaskDelay(3); //3/configTICK_RATE_HZ=0.03s运行一次 30ms } } void UsbTask(void *pvParameters) { while(1) { //任务已经正常运行标志位 char *buf = portMalloc(512) ; uint16_t len = 0 ; if( RW_OK == GetQueueMemData(&sUsbQueue, buf, &len)) //从sUsbQueue帧缓冲区中获取一帧数据准备处理 { TcpFrame_S *psRcmd = (TcpFrame_S*)buf ; int bufLen = strlen(buf) ; if( (psRcmd->head == '(')&& (psRcmd->loadHead == '&')&& (*(buf+bufLen-5) == '$')&& (*(buf+bufLen-3) == ')') //用户数据帧合法性校验 合法命令帧最后5个字节为“$X)\r\n” ) { switch( psRcmd->frameType ) //按照帧类型分类处理 { case COMCMDFRAME: //下行的控制命令帧 { if( RW_OK != InsertQueueMemData(&sUsercmdQueue, buf, bufLen) ) { ErrorLogPrintf("sUsercmdQueue溢出!") ; } break ; } case TCPSERVERACK: //USB 上位机软件对硬件上行的数据ACK确认回复包 { AppLogPrintf("USB上位机确认收到数据帧:%s .", buf) ; break ; } default: { AppLogPrintf("USB收到下行未知类型数据帧:%s .", buf) ; TcpWritedata( TCPCMDBACKFRAME, "USB收到下行未知类型数据帧") ; break ; } } } else /*收到USB数据,但是非下行命令帧*/ { AppLogPrintf("USB收到下行'非'法数据帧:%s .", buf) ; } } portFree(buf) ; vTaskDelay(0.5*configTICK_RATE_HZ); } }