AT解析层的思路分析及代码实现
生活随笔
收集整理的這篇文章主要介紹了
AT解析层的思路分析及代码实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1 AT解析層的思路分析
- 1.1 AT解析層的接口API分析
- 1.2 AT解析層代碼流程
- 2 AT解析層代碼實現
- 2.1 代碼實現
1 AT解析層的思路分析
1.1 AT解析層的接口API分析
如下:
對應到頭文件內容如下:
1.2 AT解析層代碼流程
2 AT解析層代碼實現
2.1 代碼實現
at_parse.c:
#include <stdbool.h> #include <string.h> #include "at_parse.h" #include "at_uart_hal.h" #include "app_debug.h"#include "FreeRTOS.h" #include "task.h" #include "semphr.h"#define MAX_OBJ_COUNT 10 #define MAX_RECV_BUF_LEN 200typedef struct {char *prefix;at_recv_cb callback;void *arg; }at_obj_t;typedef struct {char *cmd;char *right_prefix;char *fail_prefix;char *reply_buf;uint16_t *reply_len;bool result; }at_send_process_t;typedef struct {TaskHandle_t task_recv;SemaphoreHandle_t sem_send;SemaphoreHandle_t mutex_send;at_send_process_t send_procees;at_obj_t obj[MAX_OBJ_COUNT];char recv_buf[MAX_RECV_BUF_LEN];uint16_t recv_counter; }at_parse_t;static bool is_inited=false; static at_parse_t at;static bool at_parse_match_obj(char *pdata,uint16_t datalen) {for(uint8_t i=0;i<MAX_OBJ_COUNT;i++){if(strstr(pdata,at.obj[i].prefix)!=NULL){at.obj[i].callback(pdata,datalen,at.obj[i].arg);return true;}}return false; }static void at_parse_recv_task(void *param) {char ch;memset(at.recv_buf,0,MAX_RECV_BUF_LEN);at.recv_counter=0;while(1){if(at_uart_receive(&ch,1,1000)==0){continue;}at.recv_buf[at.recv_counter++]=ch;if(ch!=AT_END_CHAR){if(at.recv_counter>=MAX_RECV_BUF_LEN){memset(at.recv_buf,0,MAX_RECV_BUF_LEN);at.recv_counter=0; DEBUG("recv buf is full"); }continue;}//received at end chardo{if(at.recv_counter<=2)break;at.recv_counter-=2;at.recv_buf[at.recv_counter]='\0';DEBUG("at recv:%d,%s",at.recv_counter,at.recv_buf);//match obj prefixif(at_parse_match_obj(at.recv_buf,at.recv_counter))break;//match fail prefixif(at.send_procees.fail_prefix!=NULL) // 必須上層有發才處理{if(strstr(at.recv_buf,at.send_procees.fail_prefix)!=NULL){at.send_procees.result=false;xSemaphoreGive(at.sem_send);break;}}//match right prefixif(at.send_procees.right_prefix!=NULL) // 必須上層有發才處理{if(strstr(at.recv_buf,at.send_procees.right_prefix)!=NULL){//copy recv data to reply bufferif((at.send_procees.reply_buf!=NULL)&&(at.send_procees.reply_len!=NULL)){if(*at.send_procees.reply_len>at.recv_counter){memcpy(at.send_procees.reply_buf,at.recv_buf,at.recv_counter);*at.send_procees.reply_len=at.recv_counter;} else{DEBUG("reply buffer is too small");}}at.send_procees.result=true;xSemaphoreGive(at.sem_send);break;}}} while (0);memset(at.recv_buf,0,MAX_RECV_BUF_LEN);at.recv_counter=0; } }bool at_parse_init(void) {if(is_inited)return true;DEBUG("at parse init");memset(&at,0,sizeof(at));do{if(at_uart_init()==false)break;//freertos resource initif(xTaskCreate(at_parse_recv_task,"at_parse_recv",128,NULL,3,&at.task_recv)!=pdTRUE)break;at.sem_send=xSemaphoreCreateBinary();if(at.sem_send==NULL)break;at.mutex_send=xSemaphoreCreateMutex(); if(at.mutex_send==NULL)break;is_inited=true;return true;} while (0);//cleanat_parse_deinit();return false;} bool at_parse_deinit(void) {is_inited=false;DEBUG("at parse deinit");at_uart_deinit();if(at.task_recv!=NULL){vTaskDelete(at.task_recv);}if(at.sem_send!=NULL){vSemaphoreDelete(at.sem_send);}if(at.mutex_send!=NULL){vSemaphoreDelete(at.mutex_send);}vTaskDelay(100);memset(&at,0,sizeof(at));return true; } bool at_send_wait_reply(const char *cmd,bool delimiter,char *right_prefix,char *fail_prefix,char *reply_buf, uint16_t *reply_size,uint32_t timeout) {bool result=false;if(is_inited==false)return false;if(cmd==NULL)return false;if(right_prefix==NULL)return false;//lockif(xSemaphoreTake(at.mutex_send,timeout)!=pdTRUE)return false;//save parametersmemset(&at.send_procees,0,sizeof(at.send_procees));at.send_procees.cmd=(char *)cmd;at.send_procees.right_prefix=right_prefix;at.send_procees.fail_prefix=fail_prefix;at.send_procees.reply_buf=reply_buf;at.send_procees.reply_len=reply_size;do{//send dataDEBUG("at cmd:%s",cmd);if(at_uart_send(cmd,strlen(cmd),timeout)!=strlen(cmd))break;if(delimiter){if(at_uart_send(AT_DELIMITER,strlen(AT_DELIMITER),timeout)!=strlen(AT_DELIMITER))break; }//wait semxSemaphoreTake(at.sem_send,0);xSemaphoreTake(at.sem_send,timeout);result=at.send_procees.result;} while (0);//unlockmemset(&at.send_procees,0,sizeof(at.send_procees)); // 這里必須記得清空,否則很容易出bugxSemaphoreGive(at.mutex_send);return result; }bool at_send_no_reply(const char *data, uint16_t datalen, bool delimiter,uint32_t timeout) {bool result=false;if(is_inited==false)return false;if(data==NULL)return false;if(datalen==0)return false;//lockif(xSemaphoreTake(at.mutex_send,timeout)!=pdTRUE)return false;do{if(at_uart_send(data,datalen,timeout)!=datalen)break;if(delimiter){if(at_uart_send(AT_DELIMITER,strlen(AT_DELIMITER),timeout)!=strlen(AT_DELIMITER))break; }result=true;} while (0);//unlockxSemaphoreGive(at.mutex_send);return result; }bool at_register_callback(const char *prefix, at_recv_cb cb, void *arg) {for(uint8_t i=0;i<MAX_OBJ_COUNT;i++){if(strcmp(prefix,at.obj[i].prefix)==0){DEBUG("This prefix has been registered");return false;}}for(uint8_t i=0;i<MAX_OBJ_COUNT;i++){if(at.obj[i].prefix==NULL){memset(&at.obj[i],0,sizeof(at_obj_t));at.obj[i].prefix=(char *)prefix;at.obj[i].callback=cb;at.obj[i].arg=arg;return true;}}return false; }測試代碼如下:
/* USER CODE BEGIN Header_StartDefaultTask */ /*** @brief Function implementing the defaultTask thread.* @param argument: Not used* @retval None*/ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) {/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */float temp,humi;uint8_t write_buf[]="1234567890";uint8_t read_buf[20];uint16_t read_len;#define TEST_NAME 0X0001uint8_t buf[5];char reply_buf[30];uint16_t reply_len;debug_init();led_init();key_init();led_blink(2,5);sht30_init();at_parse_init();at_register_callback("+MQTT",test_callback,NULL);for(;;){memset(reply_buf,0,30);reply_len=30;if(at_send_wait_reply("AT+CSQ",true,"+CSQ","ERROR",reply_buf,&reply_len,1000)){DEBUG("-----recv %d,%s------",reply_len,reply_buf);}//at_send_no_reply("AT",2,true,1000);//at_uart_send("12345\r\n",7,1000);// storage_write(TEST_NAME,sizeof(write_buf),write_buf);// memset(read_buf,0,20);// read_len=20;// if(storage_read(TEST_NAME,&read_len,read_buf))// {// DEBUG("------%s-----",read_buf);// }// if(sht30_get_temp_humi(&temp,&humi))// {// DEBUG("temp=%f,humi=%f",temp,humi);// }osDelay(1000);}/* USER CODE END StartDefaultTask */ }總結
以上是生活随笔為你收集整理的AT解析层的思路分析及代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支付宝互助金只能用一次么
- 下一篇: NB模块开机、关机、重启的实现