You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
7.6 KiB
255 lines
7.6 KiB
#include "atcmd.h"
|
|
#include "zport.h"
|
|
|
|
#include <lwip/sockets.h>
|
|
#include "config.h"
|
|
|
|
extern ETH_HandleTypeDef heth;
|
|
|
|
#define at_address_cmd_template(_config_get) \
|
|
{ \
|
|
ip4_addr_t int_addr; \
|
|
char ip_address[16]; \
|
|
if (*p == '?') \
|
|
{ \
|
|
printf("config ip address:%s\r\n", inet_ntoa(_config_get)); \
|
|
} \
|
|
else \
|
|
{ \
|
|
if (len >= sizeof(ip_address)) \
|
|
{ /* 长度判断 */ \
|
|
printf("AT+ERR\r\n"); \
|
|
return AT_ERR; \
|
|
} /* 拷贝len有效字符长度的字符串到ip_address中 */ \
|
|
strncpy(ip_address, (const char *)p, len); \
|
|
ip_address[len] = 0; /* 这个必须要加,否则转换会出错 */ \
|
|
inet_aton(ip_address, &int_addr); \
|
|
_config_get = int_addr.addr; \
|
|
config_flash_write(); \
|
|
printf("AT+OK\r\n"); \
|
|
} \
|
|
return AT_SUCCESS; \
|
|
}
|
|
|
|
#define at_processer_rx_buf_size 128
|
|
#define at_processer_tx_buf_size 128
|
|
|
|
// 接收到了多少数据
|
|
volatile uint16_t s_at_cmd_uart_rx_off = 0;
|
|
// 当前是否正在处理接收到的数据
|
|
volatile bool s_at_cmd_uart_rx_buf_is_processing = false;
|
|
|
|
static uint8_t at_rx_buf[at_processer_rx_buf_size];
|
|
// static uint8_t at_tx_buf[at_processer_tx_buf_size];
|
|
|
|
/* AT指令表 */
|
|
const AT_cmd_func at_cmd_func[] = {
|
|
{AT_CMD_TEST, "AT", at_cmd_test},
|
|
{AT_CMD_IP, "AT+IP=", at_cmd_ip},
|
|
{AT_CMD_GW, "AT+GW=", at_cmd_gw},
|
|
{AT_CMD_NETMASK, "AT+NETMASK=", at_cmd_netmask},
|
|
{AT_CMD_OBTAINING_IP_MODE, "AT+OBTAINING_IP_MODE=", at_cmd_obtaining_ip_mode},
|
|
{AT_CMD_MAC, "AT+MAC=", at_cmd_mac},
|
|
|
|
{AT_END, NULL, NULL}};
|
|
|
|
unsigned int mstrlen(const char *s)
|
|
{
|
|
|
|
const char *ss = s;
|
|
|
|
while (*ss)
|
|
ss++;
|
|
|
|
return ss - s;
|
|
}
|
|
|
|
int mstrncmp(const char *s1, const char *s2, int n)
|
|
{
|
|
|
|
const unsigned char *c1 = (const unsigned char *)s1;
|
|
const unsigned char *c2 = (const unsigned char *)s2;
|
|
unsigned char ch;
|
|
int d = 0;
|
|
|
|
while (n--)
|
|
{
|
|
d = (int)(ch = *c1++) - (int)*c2++;
|
|
if (d || !ch)
|
|
break;
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
/* 指令执行函数 */
|
|
AT_STATUS at_cmd_test(unsigned char *p, unsigned char len)
|
|
{
|
|
|
|
printf("AT+OK\r\n");
|
|
return AT_SUCCESS;
|
|
}
|
|
|
|
AT_STATUS at_cmd_ip(unsigned char *p, unsigned char len)
|
|
{
|
|
at_address_cmd_template(config_get()->ip);
|
|
}
|
|
|
|
AT_STATUS at_cmd_gw(unsigned char *p, unsigned char len)
|
|
{
|
|
at_address_cmd_template(config_get()->gw);
|
|
}
|
|
|
|
AT_STATUS at_cmd_netmask(unsigned char *p, unsigned char len)
|
|
{
|
|
at_address_cmd_template(config_get()->netmask);
|
|
}
|
|
|
|
AT_STATUS at_cmd_obtaining_ip_mode(unsigned char *p, unsigned char len)
|
|
{
|
|
if (*p == '?')
|
|
{
|
|
printf("config obtaining_ip_mode:%d\r\n", config_get()->obtaining_ip_mode);
|
|
}
|
|
else
|
|
{
|
|
if (((*p != '0') && (*p != '1')) || (len > 1))
|
|
{
|
|
printf("AT+ERR\r\n");
|
|
return AT_ERR;
|
|
}
|
|
config_get()->obtaining_ip_mode = *p - 48; /* ascii码字符0十进制为48 */
|
|
config_flash_write();
|
|
printf("AT+OK\r\n");
|
|
}
|
|
return AT_SUCCESS;
|
|
}
|
|
|
|
AT_STATUS at_cmd_mac(unsigned char *p, unsigned char len)
|
|
{
|
|
if (*p == '?')
|
|
{
|
|
printf("mac:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\r\n", //
|
|
heth.Init.MACAddr[0], heth.Init.MACAddr[1], heth.Init.MACAddr[2], //
|
|
heth.Init.MACAddr[3], heth.Init.MACAddr[4], heth.Init.MACAddr[5]); //
|
|
}
|
|
else
|
|
{
|
|
printf("AT+OK\r\n");
|
|
}
|
|
return AT_SUCCESS;
|
|
}
|
|
|
|
/* 查找指令表中对应的指令 */
|
|
unsigned char AT_cmd_search(unsigned char *p, unsigned char len)
|
|
{
|
|
|
|
unsigned char ret = 0;
|
|
// unsigned char *pstr;
|
|
unsigned char i, n;
|
|
|
|
for (i = 1; at_cmd_func[i].cmd != AT_END; i++)
|
|
{
|
|
|
|
n = mstrlen((const char *)at_cmd_func[i].str);
|
|
if (!mstrncmp((const char *)p, (const char *)at_cmd_func[i].str, n))
|
|
{
|
|
ret = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* AT指令解析 */
|
|
AT_STATUS at_cmd_parse(unsigned char *p, unsigned char len)
|
|
{
|
|
AT_STATUS ret = AT_SUCCESS;
|
|
unsigned char index = 0;
|
|
|
|
if (len < 4)
|
|
return AT_ERR; /* 不符合指令最小长度 */
|
|
|
|
if ((p[0] == 'A') && (p[1] == 'T') && (p[len - 2] == 0x0D) && (p[len - 1] == 0x0A))
|
|
{
|
|
if (len == 4)
|
|
{ /* 测试指令 */
|
|
|
|
if (at_cmd_func[AT_CMD_TEST].cb != NULL)
|
|
at_cmd_func[AT_CMD_TEST].cb(NULL, 0); /* 执行测试指令 */
|
|
}
|
|
else if (p[2] == '+')
|
|
{ /* 执行指令解析 */
|
|
|
|
index = AT_cmd_search(p, len); /* 查找匹配的执行指令,0-已匹配,!0-未匹配 */
|
|
if (index)
|
|
{
|
|
if (at_cmd_func[index].cb != NULL)
|
|
{ /* 判断指令对应执行函数是否存在 */
|
|
unsigned char n;
|
|
n = mstrlen((const char *)at_cmd_func[index].str);
|
|
ret = at_cmd_func[index].cb(p + n, len - n - 2); /* 执行对应的指令函数, p+n:将指令参数传输执行函数,len-n-2:指令参数有效长度 */
|
|
}
|
|
else
|
|
ret = AT_ERR_FUN_UNUSED; /* 没有可执行函数 */
|
|
}
|
|
else
|
|
{
|
|
ret = AT_ERR_UNINVAIL; /* 未找到匹配的指令 */
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ /* 格式不匹配 */
|
|
|
|
return AT_ERR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void at_cmd_processer_push_data(uint8_t rxdata)
|
|
{
|
|
if (!s_at_cmd_uart_rx_buf_is_processing)
|
|
{
|
|
if (s_at_cmd_uart_rx_off < at_processer_rx_buf_size)
|
|
{
|
|
at_rx_buf[s_at_cmd_uart_rx_off] = rxdata;
|
|
s_at_cmd_uart_rx_off++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void at_cmd_processer_try_process_data(void)
|
|
{
|
|
/**
|
|
* @brief
|
|
* 根据modbus协议,当超过3.5个字符时间后依然没有收到数据
|
|
*/
|
|
if (s_at_cmd_uart_rx_off != 0)
|
|
{
|
|
uint16_t modbus_uart_rx_off_before = s_at_cmd_uart_rx_off;
|
|
|
|
HAL_Delay(1);
|
|
|
|
sys_critical_enter();
|
|
if (s_at_cmd_uart_rx_off == modbus_uart_rx_off_before)
|
|
{
|
|
s_at_cmd_uart_rx_buf_is_processing = true;
|
|
}
|
|
sys_critical_exit();
|
|
|
|
if (s_at_cmd_uart_rx_buf_is_processing)
|
|
{
|
|
if (at_cmd_parse(at_rx_buf, s_at_cmd_uart_rx_off) != AT_SUCCESS)
|
|
{
|
|
printf("at cmd parse error\r\n");
|
|
}
|
|
sys_critical_enter();
|
|
s_at_cmd_uart_rx_off = 0;
|
|
s_at_cmd_uart_rx_buf_is_processing = false;
|
|
sys_critical_exit();
|
|
}
|
|
}
|
|
}
|