赞
踩
EC20是一款集成度非常高的4G无线通信模块,支持多种常见通信频段,能满足几乎所有的M2M(MachinetoMachine)应用需求。模块支持TCP/UDP/FTP等一众网络协议,内置多星座高精度定位GNSS接收机,快速提供准确的经纬度信息,UART接口提供AT命令控制和数据传输。
物联网很多的网关设备因需要会安装在有线网络不易布到线的地方,而有些网关则需要跟着运输工具一起移动,那么就需要产品实现与上位机服务器进行无线通信,而4G的无线通信模块就提供了一种非常便利的实现。本例使用了FreeRTOS作为实时操作系统,嵌入式代码运行在FreeRTOS之上,使用提供系统调用完成了多任务编程。
目录
嵌入式程序运行在STM32芯片之上,通过UART与4G模块进行通信,控制协议为AT指令格式。STM32与4G模块之间还有两个引脚:
下图为实现原理的示意图:
本例基于STM32平台,完整工程代码已上传。工程一共涉及三个串口,功能分别如下:
代码的顶层结构由任务和消息队列与中断构成。程序开始初始化消息队列与串口控制器和相关GPIO之后,注册串口接收函数。接收函数在串口接收中断处调用,将信息发送到消息队列中。最后启动三个任务,来处理三个串口接收队列中的信息。完整的数据流图如下:
下面是除了串口的初始化工作,已增加了中文注释帮助理解,主要包括任务的初始化和启动:
- #define START_TASK_PRIO 1 //任务优先级
- #define START_STK_SIZE 64 //任务堆栈大小
- TaskHandle_t StartTask_Handler; //任务句柄
- void start_task(void *pvParameters); //开始任务声明
-
- #define EC20_TASK_PRIO 10
- #define EC20_STK_SIZE 128
- TaskHandle_t ec20_task_handler;
- void ec20_task(void *pvParameters);
-
- #define STM32_TASK_PRIO 11
- #define STM32_STK_SIZE 128
- TaskHandle_t stm32_task_handler;
- void stm32_task(void *pvParameters);
-
- #define IDLE_TASK_PRIO 8
- #define IDLE_STK_SIZE 128
- TaskHandle_t idle_task_handler;
- void idle_task(void *pvParameters);
-
- #define SET_TASK_PRIO 9
- #define SET_STK_SIZE 128
- TaskHandle_t set_task_handler;
- void set_task(void *pvParameters);
- int main(void)
- {
- Flash_EnableReadProtection();//开Flash读保护
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
- //创建开始任务
- xTaskCreate((TaskFunction_t )start_task,
- (const char* )"start_task",
- (uint16_t )START_STK_SIZE,
- (void* )NULL,
- (UBaseType_t )START_TASK_PRIO,
- (TaskHandle_t* )&StartTask_Handler);
- vTaskStartScheduler();
- }
-
- /**********************
- @GPIO初始化
- **********************/
- void gpio_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_ResetBits(GPIOB, GPIO_InitStructure.GPIO_Pin);
- }
- /**********************
- @启动任务函数
- **********************/
- void start_task(void *pvParameters)
- {
- taskENTER_CRITICAL(); //进入临界区
- gpio_init(); //GPIO初始化
- delay_init(); //延时函数初始化
- global_init(); //全局变量初始化
- msg_init(); //消息队列初始化
- uart3_init(global.baud);//串口3初始化
- uart1_init(115200);//串口1初始化
- uart2_init(global.baud);//串口2初始化
- //创建ec20任务
- xTaskCreate((TaskFunction_t )ec20_task,
- (const char* )"ec20_task",
- (uint16_t )EC20_STK_SIZE,
- (void* )NULL,
- (UBaseType_t )EC20_TASK_PRIO,
- (TaskHandle_t* )&ec20_task_handler);
-
- //创建传感器任务
- xTaskCreate((TaskFunction_t )stm32_task,
- (const char* )"stm32_task",
- (uint16_t )STM32_STK_SIZE,
- (void* )NULL,
- (UBaseType_t )STM32_TASK_PRIO,
- (TaskHandle_t* )&stm32_task_handler);
-
- // //创建空闲任务
- // xTaskCreate((TaskFunction_t )idle_task,
- // (const char* )"idle_task",
- // (uint16_t )IDLE_STK_SIZE,
- // (void* )NULL,
- // (UBaseType_t )IDLE_TASK_PRIO,
- // (TaskHandle_t* )&idle_task_handler);
- //创建参数设置任务
- xTaskCreate((TaskFunction_t )set_task,
- (const char* )"set_task",
- (uint16_t )SET_STK_SIZE,
- (void* )NULL,
- (UBaseType_t )SET_TASK_PRIO,
- (TaskHandle_t* )&set_task_handler);
-
-
- vTaskDelete(StartTask_Handler); //删除开始启动任务
- taskEXIT_CRITICAL(); //退出临界区
- }
-
下面以串口1为例提供相关初始化以及发送和接收中断代码:
- #include "global.h"
- #include "usart1.h"
- #include "msg.h"
- #include "global.h"
-
- extern uint8_t callback_ec20_deault(MSG *rx);
- static volatile MSG *tx;
-
- static COMMUCATION_RECV_CALLBACK callBack_recv = 0;
- //串口接收中断数据处理函数
- static COMMUCATION_RECV_CALLBACK default_callback = callback_ec20_deault;
- //串口配置
- static void uart1_config(u32 baud)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
- //PA9 -> UART1_TX
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- //PA10 -> UART1_RX
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- //USART1 参数配置
- USART_DeInit(USART1);
- USART_InitStructure.USART_BaudRate = baud;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(USART1, &USART_InitStructure);
-
-
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE ); //¿ª¿ÕÏÐÖжÏ
- USART_ITConfig(USART1, USART_IT_ERR, ENABLE); //¿ª´íÎóÖжÏ
-
- USART_ClearFlag(USART1, USART_FLAG_TC);
- USART_ClearFlag(USART1, USART_FLAG_RXNE);
- USART_ClearFlag(USART1, USART_FLAG_IDLE);
- USART_ClearFlag(USART1, USART_FLAG_ORE);
-
- USART_Cmd(USART1, ENABLE);
-
- //NVIC ÅäÖÃ
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
-
-
- //dma接收配置 未用
- static void dma_recv_config(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
-
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
-
- DMA_DeInit(DMA1_Channel5);
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)msg_recv_ec20[0].buf;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_InitStructure.DMA_BufferSize = global.bufferSize;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel5, &DMA_InitStructure);
-
- DMA_ClearFlag(DMA1_FLAG_GL4); //Çå³ýDMA1ËùÓбêÖ¾
-
-
- USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
- DMA_Cmd(DMA1_Channel5, ENABLE);
-
- }
-
- //dma发送配置 未用
- static void dma_send_config(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
-
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //DMA1 ʱÖÓ
-
- DMA_DeInit(DMA1_Channel4);
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)tx->buf;
- DMA_InitStructure.DMA_BufferSize = 0;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel4, &DMA_InitStructure);
-
- DMA_ClearFlag(DMA1_FLAG_GL4);
-
-
- USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
- DMA_Cmd(DMA1_Channel4, DISABLE);
-
- DMA_ClearFlag(DMA1_FLAG_GL4);
- DMA_ClearFlag(DMA1_FLAG_HT4);
- DMA_ClearFlag(DMA1_FLAG_TC4);
- DMA_ClearFlag(DMA1_FLAG_TE4);
-
- }
- //串口1中断处理函数
- void USART1_IRQHandler(void)
- {
- uint32_t sr;
- sr = sr;
-
- if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)//·¢ËÍ¿Õ
- {
- USART_ClearITPendingBit(USART1, USART_IT_TXE);
- }
-
- if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)//·¢ËÍÍê³É
- {
- USART_ClearITPendingBit(USART1, USART_IT_TC);
- USART_ITConfig(USART1, USART_IT_TC, DISABLE);
- }
-
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//ÊÕµ½
- {
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);//Çå½ÓÊÕÖжϱêÖ¾
- }
-
- if(USART_GetITStatus(USART1, USART_IT_ORE) != RESET)
- {
- sr = USART_ReceiveData(USART1);
- USART_ClearITPendingBit(USART1, USART_IT_ORE);
- }
-
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//¿ÕÏÐ
- {
- sr = USART_ReceiveData(USART1);
- DMA_Cmd(DMA1_Channel5, DISABLE);
- USART_ClearITPendingBit(USART1, USART_IT_IDLE );
-
- msg_recv_ec20[global.cur_ec20_msg].state = 1;
- msg_recv_ec20[global.cur_ec20_msg].len = global.bufferSize - DMA_GetCurrDataCounter(DMA1_Channel5);
-
- callBack_recv((MSG*)&msg_recv_ec20[global.cur_ec20_msg]);//启动回调函数函数处理中断内容
- callBack_recv = default_callback;
-
- DMA1_Channel5->CMAR = (u32)(ec20_rx()->buf);
- DMA1_Channel5->CNDTR = global.bufferSize;
- DMA_Cmd(DMA1_Channel5, ENABLE);
- }
-
- if(USART_GetITStatus(USART1 ,USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//´íÎó
- {
- sr = USART_ReceiveData(USART1);
- USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE);
- }
- }
- //串口接收DMA中断
- void DMA1_Channel5_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA1_IT_TC5) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_TC5);
- }
- if(DMA_GetITStatus(DMA1_IT_TE5) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_TE5);
- }
- DMA_ClearITPendingBit(DMA1_IT_TC5);
- DMA_ClearITPendingBit(DMA1_IT_TE5);
- DMA_Cmd(DMA1_Channel5, DISABLE);
- DMA1_Channel5->CNDTR = 100;
- DMA_Cmd(DMA1_Channel5, ENABLE);
- }
- //串口发送DMA中断
- void DMA1_Channel4_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA1_IT_TC4) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_TC4);
- }
- if(DMA_GetITStatus(DMA1_IT_TE4) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_TE4);
- }
- if(DMA_GetITStatus(DMA1_IT_GL4) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_GL4);
- }
- if(DMA_GetITStatus(DMA1_IT_HT4) == SET)
- {
- DMA_ClearITPendingBit(DMA1_IT_HT4);
- }
- DMA_Cmd(DMA1_Channel4, DISABLE);
- }
-
- //串口1初始化
- void uart1_init(u32 baud)
- {
- uart1_config(baud);
- dma_recv_config();
- dma_send_config();
- callBack_recv = default_callback;//配置串口中断回调函数
- }
-
-
- //串口1发送函数
- uint8_t uart1_send(uint8_t *pt_txbuf , uint32_t tx_len, COMMUCATION_RECV_CALLBACK callback)
- {
- if(pt_txbuf == 0)
- return FALSE;
-
- if(callback != 0)
- callBack_recv = callback;
-
-
- DMA_ClearFlag(DMA1_FLAG_TC4);
- DMA_ClearFlag(DMA1_FLAG_TE4);
-
- DMA_Cmd(DMA1_Channel4, DISABLE);
- DMA1_Channel4->CMAR = (u32)(pt_txbuf);
- DMA1_Channel4->CNDTR = tx_len;
- DMA_Cmd(DMA1_Channel4, ENABLE);
- return TRUE;
- }
下面只介绍 EC20任务和传感器任务的实现,剩下一个任务的实现有兴趣的读者可以到我的资源里把工程代码下载下来进行研究,欢迎评论区留言讨论。
下面是EC20模块初始化,建立TCP连接以及接收数据处理整个状态机在一切结果正常的情况下的流程图:
下面是任务状态机的实现,包括一些模块返回错误的流程跳转,代码中以增加中文注释帮忙理解:
- //AT指令
- const char chk_baud[] = {"AT+IPR?\r\n"}; //查询波特率
- const char set_baud[] = {"AT+IPR=115200\r\n"}; //设置波特率
- const char chk_signal[] = {"AT+CSQ\r\n"}; //查询信号强度
- const char close_cmd_echo[] = {"ATE0\r\n"}; //关闭数据回显
- const char save_param[] = {"AT&W\r\n"}; //保存设置参数,应答超时300ms
- const char chk_iccid[] = {"AT+QCCID\r\n"}; //查询ccid
-
- const char chk_pin[] = {"AT+CPIN?\r\n"}; //查询sim卡密码,5s超时
- const char chk_pin_back1[] = {"+CME ERROR: 10"}; //sim卡未插好
- const char chk_pin_back2[] = {"+CPIN: READY"}; //sim卡准备好
-
- const char chk_sim_reg[] = {"AT+CREG?\r\n"}; //查询sim卡是否注册
- const char chk_net_reg[] = {"AT+CGREG?\r\n"}; //查询net注册
-
- //运营商APN
- const char set_link_ChinaMobile[] = {"AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1\r\n"};//设置接入点(移动)APN,USERNAME,PASSWORD
- const char set_link_UNICOM[] = {"AT+QICSGP=1,1,\"UNINET\",\"\",\"\",1\r\n"};//设置接入点(联通) APN,USERNAME,PASSWORD
- const char set_link_p[] = {"AT+QICSGP=1,1,\"CTLTE\",\"\",\"\",1\r\n"};//设置接入点(电信) APN,USERNAME,PASSWORD
-
- const char chk_link_point[] = {"AT+QICSGP=1\r\n"}; //查询接入点
- const char active_pdp_context[] = {"AT+QIACT=1\r\n"};//激活接入点150s超时
- const char chk_pdp_context[] = {"AT+QIACT?\r\n"}; //查询context,返回当前接入点信息(150s超时)
- const char deactive_pdp_context[] = {"AT+QIDEACT=1\r\n"};//关闭接入点40s超时
- //const char creat_tcp[] = {"AT+QIOPEN=1,0,\"TCP\",\"120.55.115.113\",5008,0,2\r\n"};//创建TCP连接(150s超时)
- //const char creat_tcp[] = {"AT+QIOPEN=1,0,\"TCP\",\"120.26.204.86\",8001,0,2\r\n"};//创建TCP连接(150s超时)
-
- const char creat_tcp_top[] = {"AT+QIOPEN=1,0,\"TCP\",\""};
- const char creat_tcp_tail[] = {"\","};//创建TCP连接150s
- const char creat_tcp_port[] = {",0,1\r\n"};//服务端口号+传输模式【推送,非透传】
- const char creat_tcp_back1[] = {"CONNECT"};//创建TCP成功,透传模式的回应
-
- const char close_tcp[] = {"AT+QICLOSE=0\r\n"}; //关闭TCP连接(自己设置超时时间)
- const char chk_tcp[] = {"AT+QISTATE=1,0\r\n"}; //查询TCP连接(指定connetcID)
- const char chk_data_echo[] = {"AT+QISDE?\r\n"}; //查询数据回显
- //const char close_data_echo[] = {"AT+QISDE=0\r\n"}; //关闭数据回显(透传模式不需要)
- const char chk_err_code[] = {"AT+QIGETERROR\r\n"}; //查询最近的错误码
-
- const char exit_transpartent[] = {"+++"}; //退出透传模式
- const char exit_transpartent2[] = {"++++++++\r\n"}; //命令模式下+++操作
-
- const char change_transparent_mode[] = {"AT+QISWTMD=1,2\r\n"}; //改为透传模式
- const char enter_transparent_mode[] = {"ATO\r\n"}; //进入透传模式
-
- const char common_ack[] = {"OK"}; //通用回复"OK"
-
- const char chk_Operator[] = {"AT+COPS?\r\n"};//查是什么卡,移动联通电信
- const char Operater1_ack[] = {"CHINA MOBILE"};//中国移动
- const char Operater2_ack[] = {"CHN-UNICOM"};//中国联通
- const char Operater3_ack[] = {"CHN-CT"};//中国电信
- // const char Operater1_ack[] = {"china mobile"};//中国移动
- // const char Operater2_ack[] = {"chn-unicom"};//中国联通
- // const char Operater3_ack[] = {"chn-ct"};//中国电信
-
- const char chk_signal_quality[] = {"AT+CSQ\r\n"};//查询信号强度
- const char chk_signal_ack[] = {"+CQS"};//查询信号强度返回值
-
-
- const char remote_recv[] = {"+QIURC"};//服务器数据返回
-
- const char tcp_direct_ack[] = {"+QIOPEN:"};//tcp连接 direct push 模式返回值
-
-
- const char send_head[] = {"AT+QISEND=0,"};//通知ec20即将发送数据
- const char send_head_ack[] = {">"};
- const char sended_data_ack[] = {"SEND OK"};
- const char query_sended[] = {"AT+QISEND=0,0\r\n"};//查询发送数据
- const char query_sended_ack[] = {"+QISEND:"};
- /
- //EC20主任务
- void ec20_task(void)
- {
- u8 rs;
-
- ec20.fsm = ST_PWR_ON;//初始化状态机
- UPDATE_REBOOT_TIME; //初始化重启计时
- CLEAR_REBOOT_COUNT; //初始化重启计数
-
- while(1)
- {
- switch(ec20.fsm)
- {
- case ST_PWR_ON: //上电
- // c4g_power_off();
- c4g_power_on();
- ec20.fsm = ST_CLOSE_CMD_ECHO;//跳转关闭回显
- break;
-
- case ST_REBOOT: //重启
- c4g_power_reset();
- ec20.fsm = ST_CLOSE_CMD_ECHO;//跳转关闭回显
- UPDATE_REBOOT_TIME;
- CLEAR_REBOOT_COUNT;
- global.reboot_time_count = xTaskGetTickCount();//更新全局数据发送时间间隔
- break;
-
- case ST_CLOSE_CMD_ECHO://关闭数据回显
- if(c4g_close_cmd_echo())
- {
- UPDATE_REBOOT_TIME;
- ec20.fsm = ST_CHK_SIM;
- }
- if(JUDGE_REBOOT_TIME(30))//超时则重启
- {
- ec20.fsm = ST_REBOOT;
- printf("EC20 reboot\r\n\r\n");
- }
- break;
-
- case ST_CHK_SIM: //查看sim卡,物理卡
- rs = c4g_chk_sim();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CHK_SIGNAL;//跳转信号强度
- UPDATE_REBOOT_TIME;
- }else
- if(rs == 2)//未插卡
- {
- printf("no sim\r\n");
- UPDATE_REBOOT_TIME;
- }
- else//重启
- {
- if(JUDGE_REBOOT_TIME(20))//查询时间超过20s
- {
- printf("check sim timeout\r\n\r\n");
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_CHK_SIGNAL: //查询信号强度
- rs = c4g_chk_signal();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CHK_SIM_REG;//跳转sim卡注册
- UPDATE_REBOOT_TIME;
- }
- else
- {
- if(JUDGE_REBOOT_TIME(20))//查询时间超过20s
- {
- printf("check signal timeout\r\n\r\n");
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_CHK_SIM_REG: //查询sim卡注册
- rs = c4g_sim_reg();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CHK_NET_REG;
- UPDATE_REBOOT_TIME;
- }
- else
- if(rs == 2)
- {
- if(JUDGE_REBOOT_TIME(90))//查询时间超过90s
- {
- printf("check sim reg timeout\r\n\r\n");
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_CHK_NET_REG: //查询网络注册
- rs = c4g_net_reg();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CHK_OPERATER;//跳转查询运营商
- UPDATE_REBOOT_TIME;
- }
- else
- if(rs == 2)
- {
- if(JUDGE_REBOOT_TIME(60))//查询时间超过60s
- {
- printf("check net reg timeout\r\n\r\n");
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_CHK_OPERATER: //查询运营商
- rs = c4g_check_Operater();
- if(rs == TRUE)
- {
- ec20.fsm = ST_SET_POINT;//跳转设置接入点
- UPDATE_REBOOT_TIME;
- }
- else
- {
- if(JUDGE_REBOOT_TIME(60))//查询时间超过60s
- {
- printf("Operater check err\r\n\r\n");//没查到运营商
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_SET_POINT: //设置接入点,APN
- rs = c4g_set_point();
- if(rs == TRUE)
- {
- ec20.fsm = ST_ACTIVE_POINT;//Ìøת->"¼¤»î½ÓÈëµã"
- UPDATE_REBOOT_TIME;
- }
- else
- {
- if(JUDGE_REBOOT_TIME(60))//²éѯʱ¼ä³¬¹ý60s
- {
- printf("set apn err\r\n\r\n");
- ec20.fsm = ST_REBOOT;
- }
- }
- break;
-
- case ST_CHK_POINT: //查询接入点
-
- break;
-
- case ST_ACTIVE_POINT: //激活接入点
- rs = c4g_active_context();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CREAT_TCP;//跳转创建TCP
- UPDATE_REBOOT_TIME;
- CLEAR_REBOOT_COUNT;
- }
- else
- if(rs == 2)//收到数据,但是数据错误
- {
- printf("active PDP Context err 1\r\n\r\n");
- ec20.fsm = ST_DEACTIVE_POINT;//跳转关闭接入点
- UPDATE_REBOOT_TIME;
- }
- else//超过150秒未收到回复
- {
- printf("active PDP Context err 2\r\n\r\n");
- ec20.fsm = ST_REBOOT;//跳转到重启设备
- }
- break;
-
- case ST_DEACTIVE_POINT: //关闭接入点
- rs = c4g_deactive_context();
- if(rs == TRUE)
- {
- ec20.fsm = ST_CHK_SIM;//跳转查询sim卡
- CLEAR_REBOOT_COUNT;//清除重启计数
- UPDATE_REBOOT_TIME;
- }
- else
- if(rs == 2)//有返回,但是返回数据错误
- {
- if(JUDGE_REBOOT_COUNT(3))//最多查4次,如果还是失败则重启设置
- {
- printf("link point err 1\r\n\r\n");//接入点设置失败
- ec20.fsm = ST_REBOOT;//跳转重启设备
- }
- }
- else//40秒超时无回答
- {
- printf("link point err 2\r\n\r\n");//接入点设置失败
- ec20.fsm = ST_REBOOT;//跳转重启设备
- }
- break;
-
- case ST_CHK_CONTEXT: //查询接入点文本
- rs = c4g_chk_context();
- if(rs == TRUE){//查询成功,但是未激活
- ec20.fsm = ST_ACTIVE_POINT;
- UPDATE_REBOOT_TIME;
- }else
- if(rs == 3){//已经激活
- ec20.fsm = ST_CHK_TCP;//先查询是否建立了TCP连接,如没有则建立
- }else
- if(rs == 2){//错误信息
- printf("context err 1\r\n\r\n");//查询接入点文本错误
- }
- break;
-
- case ST_CREAT_TCP: //创建TCP连接
- rs = c4g_creat_tcp();
- if(rs == TRUE)
- {
- ec20.fsm = ST_COMMUCATION;//跳转通信
- global.socket_state = 1;//tcp连接成功
- CLEAR_REBOOT_COUNT;//清除重启计数
- UPDATE_REBOOT_TIME;
- }
- else
- if(rs !=0 && rs != TRUE)//有返回,则返回数据错误
- {
- if(JUDGE_REBOOT_COUNT(5))//五次失败重启
- {
- char tmp[2];
- sprintf(tmp, "%u", rs);
- printf("creat tcp err:");
- printf((const char*)tmp);
- printf("\r\n\r\n");
- ec20.fsm = ST_REBOOT;//跳转重启
- }
- }
- else//创建TCP超时,150s
- {
- printf("creat tcp timout\r\n\r\n");
- ec20.fsm = ST_REBOOT;//跳转重启
- }
- break;
-
- case ST_CHK_TCP: //查询TCP
- rs = c4g_chk_tcp();
- if(rs == TRUE)//没有建立tcp,需要重新建立
- {
- ec20.fsm = ST_CREAT_TCP;//跳转创建tcp
- UPDATE_REBOOT_TIME;
- CLEAR_REBOOT_COUNT;
- }
- else//********************
- if(rs == 3)//TCP连接已存在
- {
- if( xTaskGetTickCount() - global.reboot_time_count > global.reboot_time_set )//超过系统超时时间
- {
- global.reboot_time_count = xTaskGetTickCount();//更新时间
- ec20.fsm = ST_CLOSE_TCP;//跳转"关闭CTP"
- UPDATE_REBOOT_TIME;
- }
- else
- {
- ec20.fsm = ST_COMMUCATION;//跳转等待接收数据
- UPDATE_REBOOT_TIME;
- }
- }
- else
- if(rs == 4)//正在关闭TCP
- {
- ec20.fsm = ST_CLOSE_TCP;//跳转关闭TCP
- UPDATE_REBOOT_TIME;
- }
- else//超时无人应答
- {
- printf("chk tcp timeout\r\n\r\n");//查询TCP失败
- ec20.fsm = ST_REBOOT;//跳转重启
- }
- break;
-
- case ST_CLOSE_TCP: //关闭TCP
- rs = c4g_close_tcp();
- if(rs == TRUE)//关闭TCP成功
- {
- ec20.fsm = ST_CREAT_TCP;//跳转创建TCP
- UPDATE_REBOOT_TIME;
- CLEAR_REBOOT_COUNT;
- }
- else
- if(rs == 2)//错误信息
- {
- if( JUDGE_REBOOT_COUNT(5) )//最多查5次
- {
- printf("close tcp err\r\n\r\n");
- ec20.fsm = ST_REBOOT;//跳转重启
- }
- }
- else
- {
- printf("close tcp timeout\r\n\r\n");//关闭TCP超时
- ec20.fsm = ST_REBOOT;//Ì跳转重启
- }
- break;
-
- case ST_COMMUCATION://数据通信
- {
- MSG*cmsg;
- u8 err;
-
- err = getting_queue_ec20_remote((void*)&cmsg, 10*OS_TICKS_PER_SEC);//每10s查询一次
- if(err == pdTRUE)//收到远端数据
- {
- send_to_stm32(cmsg);//发送给传感器串口
- printf("send to user\r\n\r\n");
- }
- else
- {
- if(global.socket_state == 2)
- {
- printf("direct reboot\r\n\r\n");
- ec20.fsm = ST_REBOOT;//跳转重启
- }
- else
- if(global.socket_state == 0)
- {
- printf("transfer to close tcp\r\n\r\n");
- ec20.fsm = ST_CLOSE_TCP;//跳转关闭TCP
- UPDATE_REBOOT_TIME;
- }
- }
- }
- break;
-
- case ST_CHK_DATA_ECHO: //查询数据回显
- printf("idle \r\n\r\n");
- break;
- case ST_CLOSE_DATA_ECHO://关闭数据回显
-
- break;
- case ST_CHK_ERRCODE: //查询最近的错误码
-
- break;
-
- }
- }
- }
下面是传感器任务的实现,将传感器通过串口的发过来的数据通过EC20模块发送出去:
- void stm32_recv_task(void)
- {
- uint8_t rs, err, resend = 0;
- MSG *cmsg;
-
- while(1)
- {
- err = getting_queue_stm32((void*)&cmsg, global.reboot_time_set);//无限等待传感器队列消息
- if(err == pdTRUE)
- {
- global.reboot_time_count = xTaskGetTickCount();
- if(global.socket_state != 1)//tcp未连接
- {
- msg_free(cmsg);//不处理,并释放队列空间
- printf("stm32 recv data no dealwith\r\n");
- }
- else
- {
- //1.将数据发送至ec20
- //2.查询数据是否发送成功,即tcp是有否回应。如果没有发送成功,此条数据重新丢进队列,关闭TCP,重新连接tcp,重新发送此数据
- rs = 0xff; resend = 0;
- do
- {
- rs = send_commucation_head(cmsg->len);
- }while(resend++ < 3 && rs != 1);
-
- if(rs == 1)//发送数据头,通知ec20即将发送数据
- {
- u8 i = 0;
- do{
- uart1_send(cmsg->buf, cmsg->len, 0);//发数据
- rs = sended_result();
- if(rs != 1)//发送失败(EC20本身发送失败,并不是发送远端失败)
- {
- printf("ec20 send err\r\n\r\n");
- }
- else//发送成功
- {
- rs = query_sended_result(cmsg->len);//检查发送到remote是否成功
- if(rs == 0)//超时90s
- {
- rs = 111;
- global.socket_state = 2;//重启
- printf("sended no ack\r\n\r\n");
- }
- }
- }while(i++ < 3 && rs != 1);
-
- if(rs == 1)//发送remote成功
- {
-
- }
- else/发送失败
- {
- printf("send data err\r\n\r\n");
- if(rs != 111)
- {
- global.socket_state = 0;//重新建立tcp
- printf("sended data fail\r\n\r\n");
- }
- }
- }
- else//发送数据头,无'>'回复
- {
- printf("head is no ack\r\n\r\n");
- global.socket_state = 2;//重启
- }
- msg_free(cmsg);//释放消息,这里无论remote是否收到没有
- }
- }
- else//超过最长发送时间间隔
- {
- global.socket_state = 2;//重新建立TCP
- printf("global timeout\r\n\r\n");
- }
- }
- }
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/129848
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。