#include "AT_H.h" #include "Stdlib.h" //函数声明 static int at_query_cver(void); static int at_exec_ireboot(void); static int at_exec_crestore(void); static int at_query_tecfg(void); static int at_query_ubaud(void); static int at_exec_ubaud(char* str); static int at_query_uparity(void); static int at_exec_uparity(char* str); static int at_query_htxcfg(void); static int at_exec_htxcfg(char* str); static int at_exec_hsendb(char* str); static int at_exec_hsend(char* str); static int at_query_hrxcfg(void); static int at_exec_hrxcfg(char* str); static int at_exec_hrecb(char* str); static int at_exec_hrec(char* str); static atcmd_t g_at_cmd_list[] = { /*01 查询at版本*/ { LORA_AT_IVER, " Get the version of the AT_Slave FW", at_query_cver, NULL, NULL }, /*02 重启*/ { LORA_AT_IREBOOT, " Trig a reset of the MCU", NULL, NULL, at_exec_ireboot }, /*03 重置到出厂模式*/ { LORA_AT_IDEFAULT, " Default Set", NULL, NULL, at_exec_crestore }, /*04 查询终端参数*/ { LORA_AT_GETSTATUS, " Get terminal configuration status", at_query_tecfg, NULL, NULL }, /*05 查询、设置串口波特率*/ { LORA_AT_UBAUD, " Set USART Baud Rate", at_query_ubaud, at_exec_ubaud, NULL }, /*06 查询、设置串口校验位*/ { LORA_AT_UPARITY, " Set USART Parity", at_query_uparity, at_exec_uparity, NULL }, //LoRa /*07 查询、设置LoRa发送参数*/ { LORA_AT_HTXCFG, " Set lora send config", at_query_htxcfg, at_exec_htxcfg, NULL }, /*08 以16进制形式发送*/ { LORA_AT_HSENDB, " Send hexadecimal data", NULL, at_exec_hsendb, NULL }, /*09 以ASCII码形式发送*/ { LORA_AT_HSEND, " Send text data", NULL, at_exec_hsend, NULL }, /*10 查询、设置LoRa接收参数*/ { LORA_AT_HRXCFG, " Set lora receive config", at_query_hrxcfg, at_exec_hrxcfg, NULL }, /*11 设置以16进制接收数据*/ { LORA_AT_HRECB, " receive hexadecimal data", NULL, at_exec_hrecb, NULL}, /*12 设置以ASCII码形式接收*/ { LORA_AT_HREC, " receive text data", NULL, at_exec_hrec, NULL }, }; static char at_query_buf[RETURN_BUFF_SZIE]; //at指令查询输出缓冲 static bool uart_cfg_change = false; //删除字符串首尾所有空字符 char* string_trim(char *str) { char *str_head = str; char *str_tail = str + strlen(str) - 1; while(*str_head == ' ') { str_head++; } while(*str_tail == ' ') { str_tail--; } *(str_tail + 1) = '\0'; return str_head; } //判断字符串里是否有空字符,有:-1,无:0 int8_t just_string_trim(char *str) { uint8_t str_length = strlen(str); for(uint8_t h = 0; h < str_length; h++) { if(*(str + h) == ' ') { return -1; } } return 0; } //判断字符串是否符合格式,符合:0,不符合:非0 int8_t string_islegal(char *str, uint8_t decimal) { uint8_t length = strlen(str); if((decimal != 10) && (decimal != 16)) //目前只支持10进制及16进制 { return -2; } if(length == 0) //空字符,非法 { return -1; } switch(decimal) { case 10: for(uint8_t i = 0; i < length; i++) { if((*(str + i) > '9') || (*(str + i) < '0')) //对十进制为非法字符 { return -1; } } break; case 16: for(uint8_t i = 0; i < length; i++) { if((*(str + i) <= '9' && *(str + i) >= '0') || (*(str + i) <= 'F' && *(str + i) >= 'A') || (*(str + i) <= 'f' && *(str + i) >= 'a')) { continue; } else //不在上述范围内为非法字符 { return -1; } } break; default: return -2; } return 0; } //字符串按分隔符分离 char* string_split(char *str, char split) { static char str_temp[256] = {'\0'}; static int split_point = 0; static int length = 0; char *ret; int i = 0; if(str != NULL) //新的字符串分离 { split_point = 0; //初始化分离位置 length = strlen(str); //初始化最原始字符串长度 if(length == 0) //空字符直接返回,肯定找不到分隔字符 { return NULL; } for(i = 0; i < length; i++) { str_temp[i] = str[i]; } str_temp[i] = '\0'; ret = &str_temp[0]; //第一次指向头位置 for(i = 0; i < length; i++) { if(str_temp[i] == split) //找到字符 { str_temp[i] = '\0'; //对应位置填空,分离第一个字符串 split_point = i; //记录位置,为查找下一个字符做准备 return ret; //返回第一个字符串 } } split_point = length; //从头到尾都没有 return ret; //整体返回 } else { if(split_point == length) //上次寻找已经找寻到尾巴,说明已经全部分割完毕 { return NULL; } else { ret = &str_temp[split_point + 1]; for(i = split_point + 1; i < length; i++) //从上回记录的下一个位置开始找起 { if(str_temp[i] == split) //寻找 { str_temp[i] = '\0'; //分离 split_point = i; //记录位置 return ret; //返回该字符串 } } split_point = length; //剩余部分找不到匹配字符 return ret; //剩余部分整体返回 } } } int8_t hex2bin(const char *hex, uint8_t *bin, uint16_t bin_length) { uint16_t hex_length = strlen(hex); const char *hex_end = hex + hex_length; uint8_t *cur = bin; uint8_t num_chars = hex_length & 1; uint8_t byte = 0; if(hex_length % 2 != 0) { return -1; } if(hex_length / 2 > bin_length) { return -1; } while(hex < hex_end) { if('A' <= *hex && *hex <= 'F') { byte |= 10 + (*hex - 'A'); } else if('a' <= *hex && *hex <= 'f') { byte |= 10 + (*hex - 'a'); } else if('0' <= *hex && *hex <= '9') { byte |= *hex - '0'; } else { return -1; } hex++; num_chars++; if(num_chars >= 2) { num_chars = 0; *cur++ = byte; byte = 0; } else { byte <<= 4; } } return cur - bin; } void lora_at_process(void) { if(!is_recive_data) { return ; } if(at_cipmode_flag) { //透传 } else { const char *cmd_name; int i=0; int ret=AT_OK; char at_returnbuf[100]={0}; // printf("RxLen=%d\r\n",RxLen); // UART1_SendString(RxBuff, RxLen); // printf("\r\n"); //验证数据 if(RxBuff[0]!='A'||RxBuff[1]!='T'||RxBuff[RxLen-1]!='\n'||RxBuff[RxLen-2]!='\r') { ret=AT_FORMAT_ERR; printf("err code:%d\r\n",ret); //长度置为0,方便下次接收 memset(RxBuff,0,255); RxLen=0; is_recive_data=false; return; } //执行相关设置函数 for (i = 0; i < sizeof(g_at_cmd_list) / sizeof(atcmd_t); i++) { cmd_name = g_at_cmd_list[i].cmd_name; uint8_t cmd_len = strlen(cmd_name); char cmd_cache[cmd_len+1];//结束符\0的空间 snprintf(cmd_cache, cmd_len+1, "%s", &RxBuff[2]);//要写入的最大字符数(包括结尾的null字符) if (strncmp(cmd_cache, cmd_name, cmd_len) != 0) { continue; } /* query cmd */ if(RxBuff[cmd_len+2]=='='&&RxBuff[cmd_len+3]=='?') { if (g_at_cmd_list[i].query_cmd != NULL) { ret = g_at_cmd_list[i].query_cmd(); if (ret == AT_OK) { snprintf(at_returnbuf, RETURN_BUFF_SZIE, "%s\r\n+OK\r\n", at_query_buf); } } else { ret = AT_NOTALLOW_ERR; } } /* help cmd */ else if(RxBuff[cmd_len+2]=='?') { if (g_at_cmd_list[i].test_cmd_str) { snprintf(at_returnbuf, RETURN_BUFF_SZIE, "AT%s:%s\r\n+OK\r\n",cmd_name, g_at_cmd_list[i].test_cmd_str); } else { ret = AT_HELPNULL_ERR; } } /* exec cmd */ else if(RxBuff[cmd_len+2]=='='&&RxBuff[cmd_len+3]!='?') { if (g_at_cmd_list[i].exec_cmd != NULL) { //把等号后面,\r前面的内容传到执行函数去 RxBuff[RxLen-1]='\0'; RxBuff[RxLen-2]='\0'; ret = g_at_cmd_list[i].exec_cmd(&RxBuff[cmd_len+3]); if (ret == AT_OK) { snprintf(at_returnbuf, RETURN_BUFF_SZIE, "+OK\r\n"); } } else { ret = AT_NOTALLOW_ERR; } } /* exec cmd with out parameter */ else if(cmd_len+4==RxLen) { if (g_at_cmd_list[i].exec_cmd_no_para != NULL) { ret = g_at_cmd_list[i].exec_cmd_no_para(); if (ret == 0)//暂时只有重启和复位指令,执行不到这里来 { } } else { ret = AT_NOTALLOW_ERR; } } /* other error cmd */ else { ret = AT_FORMAT_ERR; } break; } //遍历完了都没找到匹配的 if (i == sizeof(g_at_cmd_list) / sizeof(atcmd_t)) { ret = AT_NOTFOUND_ERR; } //打印结果 if(ret==AT_OK) { printf("%s",at_returnbuf); } else { printf("err code:%d\r\n",ret); } //长度置为0,方便下次接收 memset(RxBuff,0,255); RxLen=0; is_recive_data=false; //串口这里特殊处理,AT指令修改串口配置,需应答完毕后修改 if(uart_cfg_change) { DelayMs(10); uart1_init(); uart_cfg_change=false; } } } //查询AT版本 static int at_query_cver(void) { char* ver = AT_VER; memset(at_query_buf,0,RETURN_BUFF_SZIE); snprintf(at_query_buf, RETURN_BUFF_SZIE, "%s", ver); return AT_OK; } //重启 static int at_exec_ireboot(void) { SYS_ResetExecute(); return AT_OK; } //恢复出厂 static int at_exec_crestore(void) { config_set_def(); SYS_ResetExecute(); return AT_OK; } //查询主要配置 static int at_query_tecfg(void) { return AT_OK; } //查询波特率 static int at_query_ubaud(void) { uint32_t baud; baud=uart1_get_baud(); memset(at_query_buf,0,RETURN_BUFF_SZIE); snprintf(at_query_buf, RETURN_BUFF_SZIE, "+BAUD:%d", baud); return AT_OK; } //设置波特率 static int at_exec_ubaud(char* str) { uint32_t baudrate = 0; str = string_trim(str); if(string_islegal(str, 10) != 0) { return AT_PARA_ERR; } baudrate = strtol(str, NULL, 0); if((baudrate != 38400) && (baudrate != 57600) && (baudrate != 115200)&& (baudrate != 1200)&& (baudrate != 2400)&& (baudrate != 4800)&& (baudrate != 9600)&& (baudrate != 19200)) { return AT_PARA_ERR; } uart_param.baud=baudrate; //flash保存 uart_cfg_change=true; return AT_OK; } //查询奇偶校验 static int at_query_uparity(void) { memset(at_query_buf,0,RETURN_BUFF_SZIE); switch (uart_param.parity) { case NO_PARITY: snprintf(at_query_buf, RETURN_BUFF_SZIE, "+PARITY:%s", "none"); break; case ODD_PARITY: snprintf(at_query_buf, RETURN_BUFF_SZIE, "+PARITY:%s", "Even"); break; case EVEN_PARITY: snprintf(at_query_buf, RETURN_BUFF_SZIE, "+PARITY:%s", "Odd"); break; default: snprintf(at_query_buf, RETURN_BUFF_SZIE, "+PARITY:%s", "none"); break; } return AT_OK; } //设置奇偶校验 static int at_exec_uparity(char* str) { uint8_t parity = 0; str = string_trim(str); if(string_islegal(str, 10) != 0) { return AT_PARA_ERR; } parity = strtol(str, NULL, 0); if((parity != 0) && (parity != 1) && (parity != 2)) { return AT_PARA_ERR; } uart_param.parity=(proto_parity_t)parity; //flash保存 uart_cfg_change=true; return AT_OK; } //查询LoRa配置 static int at_query_htxcfg(void) { int8_t sf = lora_param.sf_tx; int8_t bw = lora_param.bw_tx; int8_t power = lora_param.power; uint32_t freq = lora_param.freq_tx; uint16_t pream_len = lora_param.preamble_len_tx; uint32_t tx_timeout = lora_param.tx_timeout; int bwTemp=0; switch(bw) { case 0:bwTemp=125; break; case 1:bwTemp=250; break; case 2:bwTemp=500; break; default: break; } memset(at_query_buf,0,RETURN_BUFF_SZIE); snprintf(at_query_buf, RETURN_BUFF_SZIE, "+HTXCFG:sf:%d,bw:%d,power:%d,freq:%d,preamble len:%d,tx timeout:%d",sf, bwTemp, power, freq, pream_len, tx_timeout); return AT_OK; } //设置LoRa参数 static int at_exec_htxcfg(char* str) { char* param; int8_t sf = 0; int32_t bw = 0; int8_t power = 0; uint32_t freq = 0; uint16_t preamble_len = 0; uint32_t tx_timeout = 0; /* check sf parameter */ param = string_split(str, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } sf = strtol(param, NULL, 0); if((sf < 7) || (sf > 12)) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check bw parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } bw = strtol(param, NULL, 0); if(bw != 125 && bw != 250 && bw != 500) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check power parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } power = strtol(param, NULL, 0); if((power < 0) || (power > 22)) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check freq parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } freq = strtol(param, NULL, 0); if((freq < 433000000) || (freq > 900000000)) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check preamble length parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } preamble_len = strtol(param, NULL, 0); if(preamble_len <= 0 || preamble_len > 50) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check preamble timeout parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } tx_timeout = strtol(param, NULL, 0); if(tx_timeout < 0 || tx_timeout > 100000) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } lora_param.sf_tx=sf ; int bwTemp=0; switch(bw) { case 125:bwTemp=0; break; case 250:bwTemp=1; break; case 500:bwTemp=2; break; default: break; } lora_param.bw_tx=bwTemp; lora_param.power=power; lora_param.freq_tx=freq; lora_param.preamble_len_tx=preamble_len; lora_param.tx_timeout=tx_timeout; //flash保存参数 //printf("%d,%d,%d,%d,%d,%d\r\n",sf,bw,power,freq,preamble_len,tx_timeout); return AT_OK; } //查询LoRa接收参数 static int at_query_hrxcfg(void) { int8_t sf = lora_param.sf_rx; int8_t bw = lora_param.bw_rx; uint32_t freq = lora_param.freq_rx; int8_t pream_len = lora_param.preamble_len_rx; uint32_t rx_timeout = lora_param.rx_timeout; int bwTemp=0; switch(bw) { case 0:bwTemp=125; break; case 1:bwTemp=250; break; case 2:bwTemp=500; break; default: break; } memset(at_query_buf,0,RETURN_BUFF_SZIE); snprintf(at_query_buf, RETURN_BUFF_SZIE, "+HRXCFG:sf:%d,bw:%d,freq:%d,preamble len:%d,rx timeout:%d",sf, bwTemp, freq, pream_len, rx_timeout); return AT_OK; } //设置LoRa接收参数 static int at_exec_hrxcfg(char* str) { char *param; int8_t sf = 0; int32_t bw = 0; uint32_t freq = 0; uint16_t preamble_len = 0; /* check sf parameter */ param = string_split(str, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } sf = strtol(param, NULL, 0); if((sf < 7) || (sf > 12)) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check bw parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } bw = strtol(param, NULL, 0); if(bw != 125 && bw != 250 && bw != 500) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check freq parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } freq = strtol(param, NULL, 0); if((freq < 433000000) || (freq > 900000000)) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } /* check preamble length parameter */ param = string_split(NULL, ','); if(param != NULL) { param = string_trim(param); if(string_islegal(param, 10) != 0) { return AT_PARA_ERR; } preamble_len = strtol(param, NULL, 0); if(preamble_len <= 0 || preamble_len > 50) { return AT_PARA_ERR; } } else { return AT_PARA_ERR; } lora_param.sf_rx=sf ; int bwTemp=0; switch(bw) { case 125:bwTemp=0; break; case 250:bwTemp=1; break; case 500:bwTemp=2; break; default: break; } lora_param.bw_rx=bwTemp; lora_param.freq_rx=freq; lora_param.preamble_len_rx=preamble_len; //写入flash return AT_OK; } //以16进制接收数据 static int at_exec_hrecb(char* str) { str = string_trim(str); printf("%s\r\n",str); return AT_OK; } //以ASCII码形式接收 static int at_exec_hrec(char* str) { str = string_trim(str); printf("%s\r\n",str); return AT_OK; } //以16进制发送数据 static int at_exec_hsendb(char* str) { str = string_trim(str); printf("%s\r\n",str); return AT_OK; } //以ASCII码发送数据 static int at_exec_hsend(char* str) { str = string_trim(str); printf("%s\r\n",str); return AT_OK; }