mirror of
https://gitee.com/moluo-tech/AT-Command
synced 2025-06-17 16:07:52 +00:00
1.解决链表未初始化导致段错误问题。
2.调通单行命令、多行命令、自定义命令收发功能。
This commit is contained in:
parent
0d978ff3c2
commit
84bfaa01c4
228
at_chat.c
228
at_chat.c
@ -1,13 +1,15 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @brief AT指令通信
|
* @brief AT指令通信管理
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020, <morro_luo@163.com>
|
* Copyright (c) 2020~2021, <morro_luo@163.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apathe-2.0
|
* SPDX-License-Identifier: Apathe-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2020-01-02 Morro 初版
|
* 2020-01-02 Morro 初版
|
||||||
|
* 2021-01-20 Morro 增加debug调试接口, 解决链表未初始化导至段错误的问题
|
||||||
|
* 调通单行命令、多行命令、自定义命令等接口
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "at_chat.h"
|
#include "at_chat.h"
|
||||||
@ -16,13 +18,17 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
//超时判断
|
//超时判断
|
||||||
#define AT_IS_TIMEOUT(start, time) (at_get_ms() - (start) > (time))
|
#define AT_IS_TIMEOUT(start, time) (AT_GET_TICK() - (start) > (time))
|
||||||
|
|
||||||
/**AT作业类型(实际是4种类型的状态机轮询程序) -----------------------------------*/
|
/**AT作业类型(实际是4种类型的状态机轮询程序) -----------------------------------*/
|
||||||
#define AT_TYPE_WORK 0 /* 普通作业 ----------*/
|
#define AT_TYPE_WORK 0 /* 普通作业 ----------*/
|
||||||
#define AT_TYPE_CMD 1 /* 标准命令 ----------*/
|
#define AT_TYPE_CMD 1 /* 标准命令 ----------*/
|
||||||
#define AT_TYPE_MULTILINE 3 /* 多行命令 ----------*/
|
#define AT_TYPE_MULTILINE 2 /* 多行命令 ----------*/
|
||||||
#define AT_TYPE_SINGLLINE 4 /* 单行命令 ----------*/
|
#define AT_TYPE_SINGLLINE 3 /* 单行命令 ----------*/
|
||||||
|
|
||||||
|
#ifndef AT_DEBUG
|
||||||
|
#define AT_DEBUG(...) do {}while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef int (*base_work)(at_obj_t *at, ...);
|
typedef int (*base_work)(at_obj_t *at, ...);
|
||||||
|
|
||||||
@ -33,9 +39,9 @@ static const inline at_adapter_t *__get_adapter(at_obj_t *at)
|
|||||||
return &at->adap;
|
return &at->adap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_timeout(at_obj_t *at, unsigned int ms)
|
static bool at_is_timeout(at_obj_t *at, unsigned int ms)
|
||||||
{
|
{
|
||||||
return AT_IS_TIMEOUT(at->resp_timer, ms);
|
return AT_IS_TIMEOUT(at->timer, ms);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief 发送数据
|
* @brief 发送数据
|
||||||
@ -85,13 +91,20 @@ static char *search_string(at_obj_t *at, const char *str)
|
|||||||
return strstr(get_recv_buf(at), str);
|
return strstr(get_recv_buf(at), str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**前向查找字串*/
|
/**
|
||||||
|
* @brief 终止执行
|
||||||
|
*/
|
||||||
static bool at_isabort(at_obj_t *at)
|
static bool at_isabort(at_obj_t *at)
|
||||||
{
|
{
|
||||||
return at->cursor ? at->cursor->abort : 1;
|
return at->cursor ? at->cursor->abort : 1;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @brief 重置计时器
|
||||||
|
*/
|
||||||
|
static void at_reset_timer(at_obj_t *at)
|
||||||
|
{
|
||||||
|
at->timer = AT_GET_TICK();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief AT执行回调
|
* @brief AT执行回调
|
||||||
*/
|
*/
|
||||||
@ -110,27 +123,7 @@ static void do_at_callbatk(at_obj_t *a, at_item_t *i, at_callbatk_t cb, at_retur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/* 添加作业到队列*/
|
||||||
* @brief AT控制器初始化
|
|
||||||
* @param[in] cfg - AT响应
|
|
||||||
*/
|
|
||||||
void at_core_init(at_obj_t *at, const at_adapter_t *adap)
|
|
||||||
{
|
|
||||||
at_env_t *e;
|
|
||||||
at->adap = *adap;
|
|
||||||
e = &at->env;
|
|
||||||
at->recv_cnt = 0;
|
|
||||||
|
|
||||||
e->is_timeout = is_timeout;
|
|
||||||
e->printf = print;
|
|
||||||
e->recvbuf = get_recv_buf;
|
|
||||||
e->recvclr = recv_buf_clear;
|
|
||||||
e->recvlen = get_recv_count;
|
|
||||||
e->find = search_string;
|
|
||||||
e->abort = at_isabort;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**添加作业到队列*/
|
|
||||||
static bool add_work(at_obj_t *at, void *params, void *info, int type)
|
static bool add_work(at_obj_t *at, void *params, void *info, int type)
|
||||||
{
|
{
|
||||||
at_item_t *i;
|
at_item_t *i;
|
||||||
@ -152,14 +145,14 @@ static bool add_work(at_obj_t *at, void *params, void *info, int type)
|
|||||||
static int do_work_handler(at_obj_t *at)
|
static int do_work_handler(at_obj_t *at)
|
||||||
{
|
{
|
||||||
at_item_t *i = at->cursor;
|
at_item_t *i = at->cursor;
|
||||||
return ((int (*)(at_env_t *e))i->info)(i->param);
|
return ((int (*)(at_env_t *e))i->info)(&at->env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/**
|
||||||
* @brief 通用命令执行
|
* @brief 通用命令处理
|
||||||
* @param[in] a - AT管理器
|
* @param[in] a - AT控制器
|
||||||
* @return 0 - 保持工作,非0 - 结束工作
|
* @return true - 结束作业, false - 保持作业,
|
||||||
******************************************************************************/
|
*/
|
||||||
static int do_cmd_handler(at_obj_t *a)
|
static int do_cmd_handler(at_obj_t *a)
|
||||||
{
|
{
|
||||||
at_item_t *i = a->cursor;
|
at_item_t *i = a->cursor;
|
||||||
@ -172,28 +165,30 @@ static int do_cmd_handler(at_obj_t *a)
|
|||||||
e->reset_timer(a);
|
e->reset_timer(a);
|
||||||
e->recvclr(a);
|
e->recvclr(a);
|
||||||
break;
|
break;
|
||||||
case 1: /*接收状态 -----------------------------------0-------------------*/
|
case 1:
|
||||||
if (search_string(a, c->matcher)) {
|
if (search_string(a, c->matcher)) { //接收匹配
|
||||||
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
do_at_callbatk(a, i, c->cb, AT_RET_OK);
|
do_at_callbatk(a, i, c->cb, AT_RET_OK);
|
||||||
return true;
|
return true;
|
||||||
} else if (search_string(a, "ERROR")) {
|
} else if (search_string(a, "ERROR")) {
|
||||||
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
if (++e->i >= c->retry) {
|
if (++e->i >= c->retry) {
|
||||||
do_at_callbatk(a, i, c->cb, AT_RET_ERROR);
|
do_at_callbatk(a, i, c->cb, AT_RET_ERROR);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e->state = 2; /* 出错之后延时一段时间*/
|
e->state = 2; /* 出错之后延时一段时间*/
|
||||||
e->reset_timer(a); /* 重置定时器*/
|
e->reset_timer(a); /* 重置定时器*/
|
||||||
} else if (e->is_timeout(a, c->timeout)) {
|
} else if (e->is_timeout(a, c->timeout)) { /* 响应超时*/
|
||||||
if (++e->i >= c->retry) {
|
if (++e->i >= c->retry) {
|
||||||
do_at_callbatk(a, i, c->cb, AT_RET_TIMEOUT);
|
do_at_callbatk(a, i, c->cb, AT_RET_TIMEOUT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e->state = 0; /**返回上一状态*/
|
e->state = 0; /*返回上一状态*/
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (e->is_timeout(a, 500))
|
if (e->is_timeout(a, 500))
|
||||||
e->state = 0; /**返回初始状态*/
|
e->state = 0; /*返回初始状态*/
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
e->state = 0;
|
e->state = 0;
|
||||||
@ -201,11 +196,11 @@ static int do_cmd_handler(at_obj_t *a)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/**
|
||||||
* @brief 单行命令处理
|
* @brief 单行命令处理
|
||||||
* @param[in] a - AT管理器
|
* @param[in] a - AT控制器
|
||||||
* @return 0 - 保持工作,非0 - 结束工作
|
* @return true - 结束作业, false - 保持作业,
|
||||||
******************************************************************************/
|
*/
|
||||||
static int send_signlline_handler(at_obj_t *a)
|
static int send_signlline_handler(at_obj_t *a)
|
||||||
{
|
{
|
||||||
at_item_t *i = a->cursor;
|
at_item_t *i = a->cursor;
|
||||||
@ -220,23 +215,25 @@ static int send_signlline_handler(at_obj_t *a)
|
|||||||
e->reset_timer(a);
|
e->reset_timer(a);
|
||||||
e->recvclr(a);
|
e->recvclr(a);
|
||||||
break;
|
break;
|
||||||
case 1: /*接收状态 -------------------------------------------------------*/
|
case 1:
|
||||||
if (search_string(a, "OK")) {
|
if (search_string(a, "OK")) {
|
||||||
do_at_callbatk(a, i, cb, AT_RET_OK);
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
|
do_at_callbatk(a, i, cb, AT_RET_OK); //接收匹配
|
||||||
return true;
|
return true;
|
||||||
} else if (search_string(a, "ERROR")) {
|
} else if (search_string(a, "ERROR")) {
|
||||||
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
if (++e->i >= 3) {
|
if (++e->i >= 3) {
|
||||||
do_at_callbatk(a, i, cb, AT_RET_ERROR);
|
do_at_callbatk(a, i, cb, AT_RET_ERROR);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e->state = 2; /**出错之后延时一段时间*/
|
e->state = 2; /*出错之后延时一段时间*/
|
||||||
e->reset_timer(a); /**重置定时器*/
|
e->reset_timer(a); /*重置定时器*/
|
||||||
} else if (e->is_timeout(a, 3000 + e->i * 2000)) {
|
} else if (e->is_timeout(a, 3000 + e->i * 2000)) {
|
||||||
if (++e->i >= 3) {
|
if (++e->i >= 3) {
|
||||||
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
|
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e->state = 0; /**返回上一状态*/
|
e->state = 0; /*返回上一状态*/
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -248,11 +245,12 @@ static int send_signlline_handler(at_obj_t *a)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/*******************************************************************************
|
|
||||||
|
/**
|
||||||
* @brief 多行命令管理
|
* @brief 多行命令管理
|
||||||
* @param[in] a - AT管理器
|
* @param[in] a - AT控制器
|
||||||
* @return 0 - 保持工作,非0 - 结束工作
|
* @return true - 结束作业, false - 保持作业,
|
||||||
******************************************************************************/
|
*/
|
||||||
static int send_multiline_handler(at_obj_t *a)
|
static int send_multiline_handler(at_obj_t *a)
|
||||||
{
|
{
|
||||||
at_item_t *i = a->cursor;
|
at_item_t *i = a->cursor;
|
||||||
@ -271,22 +269,28 @@ static int send_multiline_handler(at_obj_t *a)
|
|||||||
e->state++;
|
e->state++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (search_string(a, "OK")){
|
if (search_string(a, "OK")) {
|
||||||
e->state = 0;
|
e->state = 0;
|
||||||
e->i++;
|
e->i++;
|
||||||
e->i = 0;
|
e->j = 0;
|
||||||
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
} else if (search_string(a, "ERROR")) {
|
} else if (search_string(a, "ERROR")) {
|
||||||
|
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
|
||||||
if (++e->j >= 3) {
|
if (++e->j >= 3) {
|
||||||
do_at_callbatk(a, i, cb, AT_RET_ERROR);
|
do_at_callbatk(a, i, cb, AT_RET_ERROR);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
e->state = 2; /**出错之后延时一段时间*/
|
e->state = 2; /*出错之后延时一段时间*/
|
||||||
e->reset_timer(a); /**重置定时器*/
|
e->reset_timer(a); /*重置定时器*/
|
||||||
} else if (e->is_timeout(a, 3000)) {
|
} else if (e->is_timeout(a, 3000)) {
|
||||||
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
|
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
if (e->is_timeout(a, 500))
|
||||||
|
e->state = 0; /**返回初始状态*/
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
e->state = 0;
|
e->state = 0;
|
||||||
}
|
}
|
||||||
@ -296,7 +300,7 @@ static int send_multiline_handler(at_obj_t *a)
|
|||||||
/**
|
/**
|
||||||
* @brief 发送行
|
* @brief 发送行
|
||||||
* @param[in] fmt - 格式化输出
|
* @param[in] fmt - 格式化输出
|
||||||
* @param[in] args - 如变参数列表
|
* @param[in] args - 可变参数列表
|
||||||
*/
|
*/
|
||||||
static void at_send_line(at_obj_t *at, const char *fmt, va_list args)
|
static void at_send_line(at_obj_t *at, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
@ -308,21 +312,29 @@ static void at_send_line(at_obj_t *at, const char *fmt, va_list args)
|
|||||||
recv_buf_clear(at); //清空接收缓存
|
recv_buf_clear(at); //清空接收缓存
|
||||||
send_data(at, buf, len);
|
send_data(at, buf, len);
|
||||||
send_data(at, "\r\n", 2);
|
send_data(at, "\r\n", 2);
|
||||||
|
|
||||||
|
AT_DEBUG("->\r\n%s\r\n", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief urc 处理总入口
|
* @brief urc(unsolicited code) 处理总入口
|
||||||
* @param[in] urc
|
* @param[in] urc - 接收缓冲区
|
||||||
|
* @param[in] size - 缓冲区大小
|
||||||
* @return none
|
* @return none
|
||||||
*/
|
*/
|
||||||
static void urc_handler_entry(at_obj_t *at, char *urc, unsigned int size)
|
static void urc_handler_entry(at_obj_t *at, char *urc, unsigned int size)
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
utc_item_t *tbl = at->adap.utc_tbl;
|
utc_item_t *tbl = at->adap.utc_tbl;
|
||||||
for (i = 0; i < at->adap.urc_tbl_count; i++){
|
for (i = 0; i < at->adap.urc_tbl_count; i++) {
|
||||||
n = strlen(tbl->prefix);
|
n = strlen(tbl->prefix);
|
||||||
if (strncmp(urc, tbl->prefix, n) == 0)
|
if (strncmp(urc, tbl->prefix, n) == 0) { /* 匹配前缀 */
|
||||||
tbl[i].handler(urc, size);
|
tbl[i].handler(urc, size); /* 回调处理*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (at->cursor == NULL)
|
||||||
|
AT_DEBUG("<=\r\n%s\r\n", urc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,21 +348,23 @@ static void urc_recv_process(at_obj_t *at, char *buf, unsigned int size)
|
|||||||
unsigned short urc_size;
|
unsigned short urc_size;
|
||||||
urc_buf = (char *)at->adap.urc_buf;
|
urc_buf = (char *)at->adap.urc_buf;
|
||||||
urc_size = at->adap.urc_bufsize;
|
urc_size = at->adap.urc_bufsize;
|
||||||
|
|
||||||
if (size == 0 && at->urc_cnt > 0) {
|
if (size == 0 && at->urc_cnt > 0) {
|
||||||
if (AT_IS_TIMEOUT(at->urc_timer, 2000)){
|
if (AT_IS_TIMEOUT(at->urc_timer, 2000)) { /* 接收超时*/
|
||||||
urc_handler_entry(at, urc_buf, at->urc_cnt);
|
urc_handler_entry(at, urc_buf, at->urc_cnt);
|
||||||
at->recv_cnt = 0;
|
at->recv_cnt = 0;
|
||||||
|
AT_DEBUG("Urc recv timeout.\r\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else if (urc_buf != NULL){
|
||||||
at->urc_timer = at_get_ms();
|
at->urc_timer = AT_GET_TICK();
|
||||||
while (size--) {
|
while (size--) {
|
||||||
if (*buf == '\n') {
|
if (*buf == '\n') { /*逐行处理*/
|
||||||
urc_buf[at->urc_cnt] = '\0';
|
urc_buf[at->urc_cnt] = '\0';
|
||||||
urc_handler_entry(at, urc_buf, at->urc_cnt);
|
urc_handler_entry(at, urc_buf, at->urc_cnt);
|
||||||
} else {
|
} else {
|
||||||
urc_buf[at->urc_cnt++] = *buf++;
|
urc_buf[at->urc_cnt++] = *buf++;
|
||||||
if (at->urc_cnt >= urc_size)
|
if (at->urc_cnt >= urc_size) /* 溢出处理 */
|
||||||
at->urc_cnt = 0;
|
at->urc_cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,8 +391,40 @@ static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 执行AT作业
|
* @brief AT控制器初始化
|
||||||
* @param[in] a - AT管理器
|
* @param[in] at - AT控制器
|
||||||
|
* @param[in] adap - AT适配器
|
||||||
|
*/
|
||||||
|
void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
at_env_t *e;
|
||||||
|
at->adap = *adap;
|
||||||
|
e = &at->env;
|
||||||
|
at->recv_cnt = 0;
|
||||||
|
|
||||||
|
e->is_timeout = at_is_timeout;
|
||||||
|
e->printf = print;
|
||||||
|
e->recvbuf = get_recv_buf;
|
||||||
|
e->recvclr = recv_buf_clear;
|
||||||
|
e->recvlen = get_recv_count;
|
||||||
|
e->find = search_string;
|
||||||
|
e->abort = at_isabort;
|
||||||
|
e->reset_timer = at_reset_timer;
|
||||||
|
|
||||||
|
/* 链表初始化*/
|
||||||
|
INIT_LIST_HEAD(&at->ls_idle);
|
||||||
|
INIT_LIST_HEAD(&at->ls_ready);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(at->items) / sizeof(at_item_t); i++)
|
||||||
|
list_add_tail(&at->items[i].node, &at->ls_idle);
|
||||||
|
|
||||||
|
while (adap->recv_buf == NULL) {} //确保缓冲区为非空
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 执行AT作业(自定义作业)
|
||||||
|
* @param[in] a - AT控制器
|
||||||
* @param[in] work - AT作业入口
|
* @param[in] work - AT作业入口
|
||||||
* @param[in] params -
|
* @param[in] params -
|
||||||
*/
|
*/
|
||||||
@ -389,7 +435,7 @@ bool at_do_work(at_obj_t *at, int (*work)(at_env_t *e), void *params)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 执行AT指令
|
* @brief 执行AT指令
|
||||||
* @param[in] a - AT管理器
|
* @param[in] a - AT控制器
|
||||||
* @param[in] cmd - cmd命令
|
* @param[in] cmd - cmd命令
|
||||||
*/
|
*/
|
||||||
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd)
|
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd)
|
||||||
@ -398,8 +444,8 @@ bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 发送单行AT命令
|
* @brief 发送单行AT命令(默认等待OK返回, 3s超时)
|
||||||
* @param[in] at - AT管理器
|
* @param[in] at - AT控制器
|
||||||
* @param[in] cb - 执行回调
|
* @param[in] cb - 执行回调
|
||||||
* @param[in] singlline - 单行命令
|
* @param[in] singlline - 单行命令
|
||||||
* @note 在命令执行完毕之前,singlline必须始终有效
|
* @note 在命令执行完毕之前,singlline必须始终有效
|
||||||
@ -410,8 +456,8 @@ bool at_send_singlline(at_obj_t *at, at_callbatk_t cb, const char *singlline)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 发送多行AT命令
|
* @brief 发送多行AT命令(多用于初始化模组, 默认等待OK返回, 3s超时)
|
||||||
* @param[in] at - AT管理器
|
* @param[in] at - AT控制器
|
||||||
* @param[in] cb - 执行回调
|
* @param[in] cb - 执行回调
|
||||||
* @param[in] multiline - 单行命令
|
* @param[in] multiline - 单行命令
|
||||||
* @note 在命令执行完毕之前,multiline
|
* @note 在命令执行完毕之前,multiline
|
||||||
@ -422,7 +468,7 @@ bool at_send_multiline(at_obj_t *at, at_callbatk_t cb, const char **multiline)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 强行中止AT作业
|
* @brief 强行中止AT作业
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void at_item_abort(at_item_t *i)
|
void at_item_abort(at_item_t *i)
|
||||||
@ -431,10 +477,10 @@ void at_item_abort(at_item_t *i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief AT忙判断
|
* @brief AT忙判断
|
||||||
* @return true - 有AT指令或者任务正在执行中
|
* @return true - 有AT指令或者任务正在执行中
|
||||||
*/
|
*/
|
||||||
bool at_core_busy(at_obj_t *at)
|
bool at_obj_busy(at_obj_t *at)
|
||||||
{
|
{
|
||||||
return !list_empty(&at->ls_ready);
|
return !list_empty(&at->ls_ready);
|
||||||
}
|
}
|
||||||
@ -444,14 +490,13 @@ bool at_core_busy(at_obj_t *at)
|
|||||||
*/
|
*/
|
||||||
static void at_work_manager(at_obj_t *at)
|
static void at_work_manager(at_obj_t *at)
|
||||||
{
|
{
|
||||||
register at_item_t *cursor = at->cursor;
|
|
||||||
at_env_t *e = &at->env;
|
at_env_t *e = &at->env;
|
||||||
/*通用工作处理者 ---------------------------------------------------------*/
|
/*作业处理表 --------------------------------------------------------------*/
|
||||||
static int (*const work_handler_table[])(at_obj_t *) = {
|
static int (*const work_handler_table[])(at_obj_t *) = {
|
||||||
do_work_handler,
|
do_work_handler,
|
||||||
do_cmd_handler,
|
do_cmd_handler,
|
||||||
send_signlline_handler,
|
send_multiline_handler,
|
||||||
send_multiline_handler
|
send_signlline_handler
|
||||||
};
|
};
|
||||||
if (at->cursor == NULL) {
|
if (at->cursor == NULL) {
|
||||||
if (list_empty(&at->ls_ready)) //就绪链为空
|
if (list_empty(&at->ls_ready)) //就绪链为空
|
||||||
@ -459,17 +504,18 @@ static void at_work_manager(at_obj_t *at)
|
|||||||
e->i = 0;
|
e->i = 0;
|
||||||
e->j = 0;
|
e->j = 0;
|
||||||
e->state = 0;
|
e->state = 0;
|
||||||
e->params = cursor->param;
|
at->cursor = list_first_entry(&at->ls_ready, at_item_t, node);
|
||||||
|
e->params = at->cursor->param;
|
||||||
e->recvclr(at);
|
e->recvclr(at);
|
||||||
e->reset_timer(at);
|
e->reset_timer(at);
|
||||||
at->cursor = list_first_entry(&at->ls_ready, at_item_t, node);
|
|
||||||
}
|
}
|
||||||
/**工作执行完成,则将它放入到空闲工作链 ------------------------------------*/
|
/* 工作执行完成,则将它放入到空闲工作链 -------------------------------------*/
|
||||||
if (work_handler_table[cursor->type](at) || cursor->abort) {
|
if (work_handler_table[at->cursor->type](at) || at->cursor->abort) {
|
||||||
list_move_tail(&at->cursor->node, &at->ls_idle);
|
list_move_tail(&at->cursor->node, &at->ls_idle);
|
||||||
at->cursor = NULL;
|
at->cursor = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief AT轮询任务
|
* @brief AT轮询任务
|
||||||
*/
|
*/
|
||||||
|
41
at_chat.h
41
at_chat.h
@ -1,24 +1,35 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @brief AT指令通信
|
* @brief AT指令通信管理
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020, <morro_luo@163.com>
|
* Copyright (c) 2020~2021, <morro_luo@163.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apathe-2.0
|
* SPDX-License-Identifier: Apathe-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2020-01-02 Morro 初版
|
* 2020-01-02 Morro 初版
|
||||||
|
* 2021-01-20 Morro 增加debug调试接口, 解决链表未初始化导至段错误的问题
|
||||||
|
* 调通单行命令、多行命令、自定义命令等接口
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifndef _ATCHAT_H_
|
#ifndef _ATCHAT_H_
|
||||||
#define _ATCHAT_H_
|
#define _ATCHAT_H_
|
||||||
|
|
||||||
#include "at_util.h"
|
|
||||||
#include <list.h>
|
#include <list.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*最大AT命令长度 --------------------------------------------------------------*/
|
||||||
#define MAX_AT_CMD_LEN 128
|
#define MAX_AT_CMD_LEN 128
|
||||||
|
|
||||||
|
/* debug 打印接口 ------------------------------------------------------------*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#define AT_DEBUG(...) printf("[AT]:");printf(__VA_ARGS__) /*do{}while(0)*/
|
||||||
|
|
||||||
|
/* 获取系统滴答(ms) -----------------------------------------------------------*/
|
||||||
|
#include "platform.h"
|
||||||
|
#define AT_GET_TICK() get_tick()
|
||||||
|
|
||||||
struct at_obj;
|
struct at_obj;
|
||||||
|
|
||||||
/*urc处理项 -----------------------------------------------------------------*/
|
/*urc处理项 -----------------------------------------------------------------*/
|
||||||
@ -81,23 +92,23 @@ typedef enum {
|
|||||||
|
|
||||||
/*AT作业项*/
|
/*AT作业项*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
at_work_state state : 3;
|
unsigned int state : 3;
|
||||||
unsigned char type : 3;
|
unsigned int type : 3; /* 作业类型*/
|
||||||
unsigned char abort : 1;
|
unsigned int abort : 1;
|
||||||
void *param;
|
void *param; /* 通用参数*/
|
||||||
void *info;
|
void *info; /* 通用信息指针*/
|
||||||
struct list_head node;
|
struct list_head node; /* 链表结点*/
|
||||||
}at_item_t;
|
}at_item_t;
|
||||||
|
|
||||||
/*AT管理器 ------------------------------------------------------------------*/
|
/*AT管理器 ------------------------------------------------------------------*/
|
||||||
typedef struct at_obj{
|
typedef struct at_obj{
|
||||||
at_adapter_t adap;
|
at_adapter_t adap;
|
||||||
at_env_t env;
|
at_env_t env; /* 作业运行环境*/
|
||||||
at_item_t tbl[10];
|
at_item_t items[10]; /* 最大容纳10个作业*/
|
||||||
at_item_t *cursor;
|
at_item_t *cursor; /* 当前作业项*/
|
||||||
struct list_head ls_ready, ls_idle; /*就绪,空闲作业链*/
|
struct list_head ls_ready, ls_idle; /* 就绪,空闲作业链*/
|
||||||
unsigned int resp_timer;
|
unsigned int timer;
|
||||||
unsigned int urc_timer;
|
unsigned int urc_timer; /* urc接收计时器*/
|
||||||
at_return ret;
|
at_return ret;
|
||||||
//urc接收计数, 命令响应接收计数器
|
//urc接收计数, 命令响应接收计数器
|
||||||
unsigned short urc_cnt, recv_cnt;
|
unsigned short urc_cnt, recv_cnt;
|
||||||
|
Loading…
Reference in New Issue
Block a user