mirror of
https://gitee.com/moluo-tech/AT-Command.git
synced 2025-02-05 17:28:23 +08:00
增加OS版本的AT通信模块
This commit is contained in:
parent
34f1ec0a41
commit
88d9b816c8
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [2015~2020] [master_roger@sina.com]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
67
README.md
67
README.md
@ -1,7 +1,7 @@
|
|||||||
# AT Command
|
# AT Command
|
||||||
|
|
||||||
#### 介绍
|
#### 介绍
|
||||||
一种AT命令通信管理模块(支持单行发),支持裸机和OS版本。适用于modem、WIFI模块、蓝牙通信。
|
一种AT命令通信解析模块,支持裸机(at_chat)和OS版本(at)。适用于modem、WIFI模块、蓝牙通信。
|
||||||
|
|
||||||
#### 软件架构
|
#### 软件架构
|
||||||
软件架构说明
|
软件架构说明
|
||||||
@ -56,4 +56,69 @@ static void read_csq_callback(at_response_t *r)
|
|||||||
at_send_singlline(&at, read_csq_callback, "AT+CSQ");
|
at_send_singlline(&at, read_csq_callback, "AT+CSQ");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### at 模块(OS版本)
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
static at_obj_t at; //定义AT管理器
|
||||||
|
|
||||||
|
char urc_buf[128]; //URC主动上报缓冲区
|
||||||
|
|
||||||
|
utc_item_t utc_tbl[] = { //定义URC表
|
||||||
|
"+CSQ: ", csq_updated_handler
|
||||||
|
}
|
||||||
|
|
||||||
|
const at_conf_t conf = { //AT管理器配置参数
|
||||||
|
.urc_buf = urc_buf,
|
||||||
|
.urc_bufsize = sizeof(urc_buf),
|
||||||
|
.utc_tbl = utc_tbl,
|
||||||
|
.urc_tbl_count = sizeof(utc_tbl) / sizeof(utc_item_t),
|
||||||
|
|
||||||
|
//适配GPRS模块的串口读写接口
|
||||||
|
.write = uart_write,
|
||||||
|
.read = uart_read
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 初始化AT管理器并创建AT线程
|
||||||
|
|
||||||
|
```
|
||||||
|
void at_thread(void)
|
||||||
|
{
|
||||||
|
at_obj_create(&at, &conf);
|
||||||
|
while (1) {
|
||||||
|
/*do something ...*/
|
||||||
|
at_thread(&at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
4. 使用例子
|
||||||
|
查询GPRS模块信号质量:
|
||||||
|
=> AT+CSQ
|
||||||
|
|
||||||
|
<= +CSQ: 24, 0
|
||||||
|
<= OK
|
||||||
|
```
|
||||||
|
/*
|
||||||
|
* @brief 获取csq值
|
||||||
|
*/
|
||||||
|
bool read_csq_value(at_obj_t *at, int *rssi, int *error_rate)
|
||||||
|
{
|
||||||
|
//接收缓冲区
|
||||||
|
unsigned char recvbuf[32];
|
||||||
|
//AT响应
|
||||||
|
at_respond_t r = {"OK", recvbuf, sizeof(recvbuf), 3000};
|
||||||
|
//
|
||||||
|
if (at_do_cmd(at, &r, "AT+CSQ") != AT_RET_OK)
|
||||||
|
return false;
|
||||||
|
//解析响应响应
|
||||||
|
return (sscanf(recv, "%*[^+]+CSQ: %d,%d", rssi, error_rate) == 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
366
at.c
Normal file
366
at.c
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file at.h
|
||||||
|
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*
|
||||||
|
* @version 5.0
|
||||||
|
* @date 2020-05-11
|
||||||
|
* @author roger.luo
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2016-01-22 roger.luo Initial version.
|
||||||
|
* 2017-05-21 roger.luo 1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* 2018-02-11 roger.luo 3.0
|
||||||
|
* 2020-01-02 roger.luo 4.0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>os<EFBFBD>汾
|
||||||
|
*******************************************************************************/
|
||||||
|
#include "at.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//<2F><>ʱ<EFBFBD>ж<EFBFBD>
|
||||||
|
#define AT_IS_TIMEOUT(start, time) (at_get_ms() - (start) > (time))
|
||||||
|
|
||||||
|
static LIST_HEAD(atlist); /*<2A><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD> ----------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
static void put_string(at_obj_t *at, const char *s)
|
||||||
|
{
|
||||||
|
while (*s != '\0')
|
||||||
|
at->cfg.write(s++, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||||
|
*/
|
||||||
|
static void put_line(at_obj_t *at, const char *s)
|
||||||
|
{
|
||||||
|
put_string(at, s);
|
||||||
|
put_string(at, "\r\n");
|
||||||
|
at->cfg.debug("->\r\n%s\r\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
//<2F><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD>
|
||||||
|
static void at_print(at_obj_t *at, const char *cmd, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, cmd);
|
||||||
|
char buf[MAX_AT_CMD_LEN];
|
||||||
|
vsnprintf(buf, sizeof(buf), cmd, args);
|
||||||
|
put_line(at, buf);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
static void recvbuf_clr(at_obj_t *at)
|
||||||
|
{
|
||||||
|
at->rcv_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//<2F>ȴ<EFBFBD>AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ
|
||||||
|
static at_return wait_resp(at_obj_t *at, at_respond_t *r)
|
||||||
|
{
|
||||||
|
at->resp = r;
|
||||||
|
at->ret = AT_RET_TIMEOUT;
|
||||||
|
at->resp_timer = at_get_ms();
|
||||||
|
recvbuf_clr(at); //<2F><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD>
|
||||||
|
at->wait = 1;
|
||||||
|
at_sem_wait(&at->completed, r->timeout);
|
||||||
|
at->cfg.debug("<-\r\n%s\r\n", r->recvbuf);
|
||||||
|
at->resp = NULL;
|
||||||
|
at->wait = 0;
|
||||||
|
return at->ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӦAT<EFBFBD><EFBFBD>Ӧ
|
||||||
|
* @param[in] resp - <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD>(<EFBFBD><EFBFBD>"OK",">")
|
||||||
|
* @param[in] timeout - <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ʱʱ<EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
at_return wait_resp_sync(struct at_obj *at, const char *resp,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
int cnt = 0, len;
|
||||||
|
at_return ret = AT_RET_TIMEOUT;
|
||||||
|
unsigned int timer = at_get_ms();
|
||||||
|
while (at_get_ms() - timer < timeout) {
|
||||||
|
len = at->cfg.read(buf, sizeof(buf) - cnt);
|
||||||
|
cnt += len;
|
||||||
|
buf[cnt] = '\0';
|
||||||
|
if (strstr(buf, resp)) {
|
||||||
|
ret = AT_RET_OK;
|
||||||
|
break;
|
||||||
|
} else if (strstr(buf, "ERROR")) {
|
||||||
|
ret = AT_RET_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
at_delay(10);
|
||||||
|
}
|
||||||
|
at->cfg.debug("%s", buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief AT<EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
void at_obj_create(at_obj_t *at, const at_conf_t cfg)
|
||||||
|
{
|
||||||
|
at_work_env_t *e;
|
||||||
|
at->cfg = cfg;
|
||||||
|
at->rcv_cnt = 0;
|
||||||
|
|
||||||
|
at_sem_init(&at->cmd_lock, 1);
|
||||||
|
at_sem_init(&at->completed, 0);
|
||||||
|
e = &at->env;
|
||||||
|
e->at = at;
|
||||||
|
e->printf = at_print;
|
||||||
|
e->recvclr = recvbuf_clr;
|
||||||
|
e->read = cfg.read;
|
||||||
|
e->write = cfg.write;
|
||||||
|
e->wait_resp = wait_resp_sync;
|
||||||
|
|
||||||
|
list_add_tail(&at->node, &atlist);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AT
|
||||||
|
*/
|
||||||
|
void at_obj_destroy(at_obj_t *at)
|
||||||
|
{
|
||||||
|
list_del(&at->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] fmt - <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] r - <EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL, Ĭ<EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD>OK<EFBFBD><EFBFBD>ʾ<EFBFBD>ɹ<EFBFBD>,<EFBFBD>ȴ<EFBFBD>3s
|
||||||
|
* @param[in] args - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
|
||||||
|
*/
|
||||||
|
at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd)
|
||||||
|
{
|
||||||
|
at_return ret;
|
||||||
|
char defbuf[64];
|
||||||
|
at_respond_t default_resp = {"OK", defbuf, sizeof(defbuf), 3000};
|
||||||
|
if (r == NULL) {
|
||||||
|
r = &default_resp; //Ĭ<><C4AC><EFBFBD><EFBFBD>Ӧ
|
||||||
|
}
|
||||||
|
if (!at_sem_wait(&at->cmd_lock, r->timeout)) {
|
||||||
|
return AT_RET_TIMEOUT;
|
||||||
|
}
|
||||||
|
while (at->urc_cnt) {
|
||||||
|
at_delay(10);
|
||||||
|
}
|
||||||
|
put_line(at, cmd);
|
||||||
|
ret = wait_resp(at, r);
|
||||||
|
at_sem_post(&at->cmd_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief ִ<EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
|
||||||
|
* @param[in] urc
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
int at_do_work(at_obj_t *at, at_work work, void *params)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if (!at_sem_wait(&at->cmd_lock, 150 * 1000)) {
|
||||||
|
return AT_RET_TIMEOUT;
|
||||||
|
}
|
||||||
|
at->env.params = params;
|
||||||
|
at->dowork = true;
|
||||||
|
ret = work(&at->env);
|
||||||
|
at->dowork = false;
|
||||||
|
at_sem_post(&at->cmd_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>
|
||||||
|
* @param[in] recvbuf - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[out] lines - <EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
int at_split_respond_lines(char *recvbuf, char *lines[], int count)
|
||||||
|
{
|
||||||
|
char *s = recvbuf;
|
||||||
|
size_t i = 0;
|
||||||
|
if (s == NULL || lines == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lines[i++] = s;
|
||||||
|
while(*s && i < count) {
|
||||||
|
if (*s == ',') {
|
||||||
|
*s = '\0';
|
||||||
|
lines[i++] = s + 1; /*ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ӵ<EFBFBD>*/
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief urc <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] urcline - URC<EFBFBD><EFBFBD>
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static void urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
utc_item_t *tbl = at->cfg.utc_tbl;
|
||||||
|
|
||||||
|
for (i = 0; i < at->cfg.urc_tbl_count; i++){
|
||||||
|
n = strlen(tbl->prefix);
|
||||||
|
if (n > 0 && strncmp(urcline, tbl->prefix, n) == 0) {
|
||||||
|
tbl->handler(urcline, size);
|
||||||
|
at->cfg.debug("<=\r\n%s\r\n", urcline);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tbl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size >= 2 && !at->wait) //<2F>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
at->cfg.debug("%s\r\n", urcline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief urc <EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size)
|
||||||
|
{
|
||||||
|
char *urc_buf;
|
||||||
|
unsigned short urc_size;
|
||||||
|
unsigned char c;
|
||||||
|
urc_buf = (char *)at->cfg.urc_buf;
|
||||||
|
urc_size = at->cfg.urc_bufsize;
|
||||||
|
if (at->urc_cnt > 0 && size == 0) {
|
||||||
|
if (AT_IS_TIMEOUT(at->urc_timer, 100)) { //100ms<6D><73>ʱ
|
||||||
|
urc_buf[at->urc_cnt] = '\0';
|
||||||
|
at->urc_cnt = 0;
|
||||||
|
at->cfg.debug("urc recv timeout=>%s\r\n", urc_buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
at->urc_timer = at_get_ms();
|
||||||
|
while (size--) {
|
||||||
|
c = *buf++;
|
||||||
|
if (c == '\r' || c == '\n') { //<2F>յ<EFBFBD>1<EFBFBD><31>
|
||||||
|
urc_buf[at->urc_cnt] = '\0';
|
||||||
|
if (at->urc_cnt > 2)
|
||||||
|
urc_handler_entry(at, urc_buf, at->urc_cnt);
|
||||||
|
at->urc_cnt = 0;
|
||||||
|
} else {
|
||||||
|
urc_buf[at->urc_cnt++] = c;
|
||||||
|
if (at->urc_cnt >= urc_size) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
at->urc_cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size)
|
||||||
|
{
|
||||||
|
char *rcv_buf;
|
||||||
|
unsigned short rcv_size;
|
||||||
|
at_respond_t *resp = at->resp;
|
||||||
|
|
||||||
|
if (resp == NULL || size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rcv_buf = (char *)resp->recvbuf;
|
||||||
|
rcv_size = resp->bufsize;
|
||||||
|
|
||||||
|
if (at->rcv_cnt + size >= rcv_size) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
at->rcv_cnt = 0;
|
||||||
|
at->cfg.debug("Receive overflow:%s", rcv_buf);
|
||||||
|
}
|
||||||
|
/*<2A><><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD>rcv_buf<75><66> ---------------------------------------------*/
|
||||||
|
memcpy(rcv_buf + at->rcv_cnt, buf, size);
|
||||||
|
at->rcv_cnt += size;
|
||||||
|
rcv_buf[at->rcv_cnt] = '\0';
|
||||||
|
|
||||||
|
|
||||||
|
if (!at->wait)
|
||||||
|
return;
|
||||||
|
if (strstr(rcv_buf, resp->matcher)) { //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
|
||||||
|
at->ret = AT_RET_OK;
|
||||||
|
} else if (strstr(rcv_buf, "ERROR")) {
|
||||||
|
at->ret = AT_RET_ERROR;
|
||||||
|
} else if (AT_IS_TIMEOUT(at->resp_timer, resp->timeout)) {
|
||||||
|
at->ret = AT_RET_TIMEOUT;
|
||||||
|
} else if (at->suspend) //ǿ<><C7BF><EFBFBD><EFBFBD>ֹ
|
||||||
|
at->ret = AT_RET_ABORT;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
at_sem_post(&at->completed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief ATæ<EFBFBD>ж<EFBFBD>
|
||||||
|
* @return true - <EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
bool at_obj_busy(at_obj_t *at)
|
||||||
|
{
|
||||||
|
return at->wait == 0 && AT_IS_TIMEOUT(at->urc_timer, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void at_suspend(at_obj_t *at)
|
||||||
|
{
|
||||||
|
at->suspend = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief <EFBFBD>ָ<EFBFBD>AT<EFBFBD><EFBFBD>ҵ
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void at_resume(at_obj_t *at)
|
||||||
|
{
|
||||||
|
at->suspend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief AT<EFBFBD><EFBFBD>ѯ<EFBFBD>߳<EFBFBD>
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void at_thread(void)
|
||||||
|
{
|
||||||
|
at_obj_t *at;
|
||||||
|
struct list_head *list ,*n = NULL;
|
||||||
|
int len;
|
||||||
|
char buf[32];
|
||||||
|
while (1) {
|
||||||
|
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>at_obj<62><6A><EFBFBD><EFBFBD>*/
|
||||||
|
list_for_each_safe(list, n, &atlist) {
|
||||||
|
at = list_entry(list, at_obj_t, node);
|
||||||
|
if (!at->dowork) {
|
||||||
|
#warning "<22><>ȡ<EFBFBD>Ż<EFBFBD>(readline) ..."
|
||||||
|
len = at->cfg.read(buf, sizeof(buf));
|
||||||
|
urc_recv_process(at, (char *)buf, len);
|
||||||
|
if (len > 0) {
|
||||||
|
resp_recv_process(at, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
at_delay(1);
|
||||||
|
}
|
||||||
|
}
|
111
at.h
Normal file
111
at.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file at.h
|
||||||
|
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
*
|
||||||
|
* @version 5.0
|
||||||
|
* @date 2020-05-11
|
||||||
|
* @author roger.luo
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2016-01-22 roger.luo Initial version.
|
||||||
|
* 2017-05-21 roger.luo 1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* 2018-02-11 roger.luo 3.0
|
||||||
|
* 2020-01-02 roger.luo 4.0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>os<EFBFBD>汾
|
||||||
|
*******************************************************************************/
|
||||||
|
#ifndef _AT_H_
|
||||||
|
#define _AT_H_
|
||||||
|
|
||||||
|
#include "at_util.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MAX_AT_CMD_LEN 64
|
||||||
|
|
||||||
|
struct at_obj; /*AT<41><54><EFBFBD><EFBFBD>*/
|
||||||
|
|
||||||
|
/*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -----------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
const char *prefix; //URCǰ
|
||||||
|
void (*handler)(char *recvbuf, int size);
|
||||||
|
}utc_item_t;
|
||||||
|
|
||||||
|
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
/*<2A><><EFBFBD>ݶ<EFBFBD>д<EFBFBD>ӿ<EFBFBD> -----------------------------------------------------------*/
|
||||||
|
unsigned int (*read)(void *buf, unsigned int len);
|
||||||
|
unsigned int (*write)(const void *buf, unsigned int len);
|
||||||
|
void (*debug)(const char *fmt, ...);
|
||||||
|
utc_item_t *utc_tbl; /*utc <20><>*/
|
||||||
|
char *urc_buf; /*urc<72><63><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
|
unsigned short urc_tbl_count;
|
||||||
|
unsigned short urc_bufsize; /*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
|
||||||
|
}at_conf_t;
|
||||||
|
|
||||||
|
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6> ---------------------------------------------------------------*/
|
||||||
|
typedef enum {
|
||||||
|
AT_RET_OK = 0, /*ִ<>гɹ<D0B3>*/
|
||||||
|
AT_RET_ERROR, /*ִ<>д<EFBFBD><D0B4><EFBFBD>*/
|
||||||
|
AT_RET_TIMEOUT, /*<2A><>Ӧ<EFBFBD><D3A6>ʱ*/
|
||||||
|
AT_RET_ABORT, /*δ֪<CEB4><D6AA><EFBFBD><EFBFBD>*/
|
||||||
|
}at_return;
|
||||||
|
|
||||||
|
/*AT<41><54>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD> -----------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
const char *matcher; /*<2A><><EFBFBD><EFBFBD>ƥ<EFBFBD>䴮*/
|
||||||
|
char *recvbuf; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
|
unsigned short bufsize; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD><D5B3><EFBFBD>*/
|
||||||
|
unsigned int timeout; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1> */
|
||||||
|
}at_respond_t;
|
||||||
|
|
||||||
|
/*AT<41><54>ҵ ---------------------------------------------------------------------*/
|
||||||
|
typedef struct at_work_env{
|
||||||
|
struct at_obj *at;
|
||||||
|
void *params;
|
||||||
|
unsigned int (*write)(const void *buf, unsigned int len);
|
||||||
|
unsigned int (*read)(void *buf, unsigned int len);
|
||||||
|
|
||||||
|
void (*printf)(struct at_obj *at, const char *frm, ...);
|
||||||
|
at_return (*wait_resp)(struct at_obj *at, const char *resp, unsigned int timeout);
|
||||||
|
void (*recvclr)(struct at_obj *at); /*<2A><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
|
}at_work_env_t;
|
||||||
|
|
||||||
|
/*AT<41><54><EFBFBD><EFBFBD> ---------------------------------------------------------------------*/
|
||||||
|
typedef struct at_obj {
|
||||||
|
struct list_head node;
|
||||||
|
at_conf_t cfg;
|
||||||
|
at_work_env_t env;
|
||||||
|
at_sem_t cmd_lock; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
|
at_sem_t completed; /*<2A><><EFBFBD><EFBFBD><EEB4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
|
at_respond_t *resp;
|
||||||
|
unsigned int resp_timer;
|
||||||
|
unsigned int urc_timer;
|
||||||
|
at_return ret;
|
||||||
|
//urc<72><63><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned short urc_cnt, rcv_cnt;
|
||||||
|
unsigned char wait : 1;
|
||||||
|
unsigned char suspend: 1;
|
||||||
|
unsigned char dowork : 1;
|
||||||
|
}at_obj_t;
|
||||||
|
|
||||||
|
typedef int (*at_work)(at_work_env_t *);
|
||||||
|
|
||||||
|
void at_obj_create(at_obj_t *at, const at_conf_t cfg); /*AT<41><54>ʼ<EFBFBD><CABC>*/
|
||||||
|
|
||||||
|
void at_obj_destroy(at_obj_t *at);
|
||||||
|
|
||||||
|
bool at_obj_busy(at_obj_t *at);
|
||||||
|
|
||||||
|
void at_suspend(at_obj_t *at); /*<2A><><EFBFBD><EFBFBD>*/
|
||||||
|
|
||||||
|
void at_resume(at_obj_t *at); /*<2A>ָ<EFBFBD>*/
|
||||||
|
|
||||||
|
at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd);
|
||||||
|
|
||||||
|
int at_split_respond_lines(char *recvbuf, char *lines[], int count);
|
||||||
|
|
||||||
|
int at_do_work(at_obj_t *at, at_work work, void *params); /*ִ<><D6B4>AT<41><54>ҵ*/
|
||||||
|
|
||||||
|
void at_thread(void); /*AT<41>߳<EFBFBD>*/
|
||||||
|
|
||||||
|
#endif
|
64
at_chat.c
64
at_chat.c
@ -1,17 +1,19 @@
|
|||||||
/******************************************************************************
|
/*******************************************************************************
|
||||||
* @brief AT ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>OS<EFBFBD>汾)
|
* @file at_core.h
|
||||||
*
|
* @brief AT command communications.
|
||||||
* Copyright (c) 2019, <master_roger@sina.com>
|
*
|
||||||
*
|
* @version 5.0
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* @date 2020-05-11
|
||||||
*
|
* @author roger.luo
|
||||||
* Change Logs:
|
*
|
||||||
* Date Author Notes
|
* Change Logs:
|
||||||
* 2016-01-22 Morro Initial version.
|
* Date Author Notes
|
||||||
* 2018-02-11 Morro ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
|
* 2016-01-22 roger.luo Initial version.
|
||||||
* 2020-05-21 Morro ֧<EFBFBD><EFBFBD>at_core<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
* 2017-05-21 roger.luo 1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
******************************************************************************/
|
* 2018-02-11 roger.luo 3.0
|
||||||
|
* 2020-01-02 roger.luo 4.0 os version
|
||||||
|
* 2020-05-21 roger.luo 5.0 <EFBFBD><EFBFBD>OS<EFBFBD>汾
|
||||||
|
*******************************************************************************/
|
||||||
#include "at_chat.h"
|
#include "at_chat.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -52,10 +54,10 @@ static void send_data(at_core_t *ac, const void *buf, unsigned int len)
|
|||||||
*/
|
*/
|
||||||
static void print(at_core_t *ac, const char *cmd, ...)
|
static void print(at_core_t *ac, const char *cmd, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, cmd);
|
va_start(args, cmd);
|
||||||
at_send_line(ac, cmd, args);
|
at_send_line(ac, cmd, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ճ<EFBFBD><EFBFBD><EFBFBD>
|
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ճ<EFBFBD><EFBFBD><EFBFBD>
|
||||||
@ -90,7 +92,7 @@ static char *search_string(at_core_t *ac, const char *str)
|
|||||||
/*ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>*/
|
/*ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>*/
|
||||||
static bool at_isabort(at_core_t *ac)
|
static bool at_isabort(at_core_t *ac)
|
||||||
{
|
{
|
||||||
return ac->cursor ? ac->cursor->abort : 1;
|
return ac->cursor ? ac->cursor->abort : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -164,7 +166,7 @@ static int do_cmd_handler(at_core_t *a)
|
|||||||
{
|
{
|
||||||
at_item_t *i = a->cursor;
|
at_item_t *i = a->cursor;
|
||||||
at_env_t *e = &a->env;
|
at_env_t *e = &a->env;
|
||||||
const at_cmd_t *c = (at_cmd_t *)i->info;
|
const at_respond_t *c = (at_respond_t *)i->info;
|
||||||
switch(e->state) {
|
switch(e->state) {
|
||||||
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
||||||
c->sender(e);
|
c->sender(e);
|
||||||
@ -173,7 +175,7 @@ static int do_cmd_handler(at_core_t *a)
|
|||||||
e->recvclr(a);
|
e->recvclr(a);
|
||||||
break;
|
break;
|
||||||
case 1: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
case 1: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
||||||
if (search_string(a, c->matcher)) {
|
if (search_string(a, c->matcher)) {
|
||||||
do_at_callback(a, i, c->cb, AT_RET_OK);
|
do_at_callback(a, i, c->cb, AT_RET_OK);
|
||||||
return true;
|
return true;
|
||||||
} else if (search_string(a, "ERROR")) {
|
} else if (search_string(a, "ERROR")) {
|
||||||
@ -221,7 +223,7 @@ static int send_signlline_handler(at_core_t *a)
|
|||||||
e->recvclr(a);
|
e->recvclr(a);
|
||||||
break;
|
break;
|
||||||
case 1: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
case 1: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
|
||||||
if (search_string(a, "OK")) {
|
if (search_string(a, "OK")) {
|
||||||
do_at_callback(a, i, cb, AT_RET_OK);
|
do_at_callback(a, i, cb, AT_RET_OK);
|
||||||
return true;
|
return true;
|
||||||
} else if (search_string(a, "ERROR")) {
|
} else if (search_string(a, "ERROR")) {
|
||||||
@ -332,10 +334,10 @@ static void urc_handler_entry(at_core_t *ac, char *urc, unsigned int size)
|
|||||||
*/
|
*/
|
||||||
static void urc_recv_process(at_core_t *ac, char *buf, unsigned int size)
|
static void urc_recv_process(at_core_t *ac, char *buf, unsigned int size)
|
||||||
{
|
{
|
||||||
char *urc_buf;
|
char *urc_buf;
|
||||||
unsigned short urc_size;
|
unsigned short urc_size;
|
||||||
urc_buf = (char *)ac->cfg.urc_buf;
|
urc_buf = (char *)ac->cfg.urc_buf;
|
||||||
urc_size = ac->cfg.urc_bufsize;
|
urc_size = ac->cfg.urc_bufsize;
|
||||||
if (size == 0 && ac->urc_cnt > 0) {
|
if (size == 0 && ac->urc_cnt > 0) {
|
||||||
if (AT_IS_TIMEOUT(ac->urc_timer, 2000)){
|
if (AT_IS_TIMEOUT(ac->urc_timer, 2000)){
|
||||||
urc_handler_entry(ac, urc_buf, ac->urc_cnt);
|
urc_handler_entry(ac, urc_buf, ac->urc_cnt);
|
||||||
@ -364,7 +366,7 @@ static void urc_recv_process(at_core_t *ac, char *buf, unsigned int size)
|
|||||||
static void resp_recv_process(at_core_t *ac, const char *buf, unsigned int size)
|
static void resp_recv_process(at_core_t *ac, const char *buf, unsigned int size)
|
||||||
{
|
{
|
||||||
char *rcv_buf;
|
char *rcv_buf;
|
||||||
unsigned short rcv_size;
|
unsigned short rcv_size;
|
||||||
|
|
||||||
rcv_buf = (char *)ac->cfg.rcv_buf;
|
rcv_buf = (char *)ac->cfg.rcv_buf;
|
||||||
rcv_size = ac->cfg.rcv_bufsize;
|
rcv_size = ac->cfg.rcv_bufsize;
|
||||||
@ -372,7 +374,7 @@ static void resp_recv_process(at_core_t *ac, const char *buf, unsigned int size)
|
|||||||
if (ac->rcv_cnt + size >= rcv_size) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
if (ac->rcv_cnt + size >= rcv_size) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
ac->rcv_cnt = 0;
|
ac->rcv_cnt = 0;
|
||||||
|
|
||||||
memcpy(rcv_buf, buf, size);
|
memcpy(rcv_buf + rcv_cnt, buf, size);
|
||||||
ac->rcv_cnt += size;
|
ac->rcv_cnt += size;
|
||||||
rcv_buf[ac->rcv_cnt] = '\0';
|
rcv_buf[ac->rcv_cnt] = '\0';
|
||||||
|
|
||||||
@ -394,7 +396,7 @@ bool at_do_work(at_core_t *ac, int (*work)(at_env_t *e), void *params)
|
|||||||
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
* @param[in] cmd - cmd<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
* @param[in] cmd - cmd<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
*/
|
*/
|
||||||
bool at_do_cmd(at_core_t *ac, void *params, const at_cmd_t *cmd)
|
bool at_do_cmd(at_core_t *ac, void *params, const at_respond_t *cmd)
|
||||||
{
|
{
|
||||||
return add_work(ac, params, (void *)cmd, AT_TYPE_CMD);
|
return add_work(ac, params, (void *)cmd, AT_TYPE_CMD);
|
||||||
}
|
}
|
||||||
@ -429,7 +431,7 @@ bool at_send_multiline(at_core_t *ac, at_callback_t cb, const char **multiline)
|
|||||||
|
|
||||||
void at_item_abort(at_item_t *i)
|
void at_item_abort(at_item_t *i)
|
||||||
{
|
{
|
||||||
i->abort = 1;
|
i->abort = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -450,7 +452,7 @@ static void at_work_manager(at_core_t *ac)
|
|||||||
at_env_t *e = &ac->env;
|
at_env_t *e = &ac->env;
|
||||||
/*ͨ<>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------*/
|
/*ͨ<>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------*/
|
||||||
static int (*const work_handler_table[])(at_core_t *) = {
|
static int (*const work_handler_table[])(at_core_t *) = {
|
||||||
do_work_handler,
|
do_work_handler,
|
||||||
do_cmd_handler,
|
do_cmd_handler,
|
||||||
send_signlline_handler,
|
send_signlline_handler,
|
||||||
send_multiline_handler
|
send_multiline_handler
|
||||||
@ -468,10 +470,10 @@ static void at_work_manager(at_core_t *ac)
|
|||||||
}
|
}
|
||||||
/*<2A><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽<EFBFBD><EBB5BD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> ------------------------------------*/
|
/*<2A><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽<EFBFBD><EBB5BD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> ------------------------------------*/
|
||||||
if (work_handler_table[cursor->type](ac) || cursor->abort) {
|
if (work_handler_table[cursor->type](ac) || cursor->abort) {
|
||||||
ac->cfg.lock();
|
ac->cfg.lock();
|
||||||
list_move_tail(&ac->cursor->node, &ac->ls_idle);
|
list_move_tail(&ac->cursor->node, &ac->ls_idle);
|
||||||
ac->cursor = NULL;
|
ac->cursor = NULL;
|
||||||
ac->cfg.unlock();
|
ac->cfg.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
72
at_chat.h
72
at_chat.h
@ -1,16 +1,20 @@
|
|||||||
/******************************************************************************
|
/*******************************************************************************
|
||||||
* @brief AT ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>OS<EFBFBD>汾)
|
* Copyright(C)20 roger.luo
|
||||||
*
|
* All rights reserved.
|
||||||
* Copyright (c) 2019, <master_roger@sina.com>
|
* @file atchat.h
|
||||||
*
|
* @brief AT command communications.
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
*
|
||||||
*
|
* @version 3.0
|
||||||
* Change Logs:
|
* @date 2018-02-11
|
||||||
* Date Author Notes
|
* @author roger.luo
|
||||||
* 2016-01-22 Morro Initial version.
|
*
|
||||||
* 2018-02-11 Morro ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
|
* Change Logs:
|
||||||
* 2020-05-21 Morro ֧<EFBFBD><EFBFBD>at_core<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
* Date Author Notes
|
||||||
******************************************************************************/
|
* 2016-01-22 roger.luo Initial version.
|
||||||
|
* 2017-05-21 roger.luo 1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
* 2018-02-11 roger.luo 3.0
|
||||||
|
* 2020-01-02 roger.luo 4.0 os version
|
||||||
|
*******************************************************************************/
|
||||||
#ifndef _ATCHAT_H_
|
#ifndef _ATCHAT_H_
|
||||||
#define _ATCHAT_H_
|
#define _ATCHAT_H_
|
||||||
|
|
||||||
@ -37,22 +41,22 @@ typedef struct {
|
|||||||
void (*before_at)(void); /*<2A><>ʼִ<CABC><D6B4>AT*/
|
void (*before_at)(void); /*<2A><>ʼִ<CABC><D6B4>AT*/
|
||||||
void (*after_at)(void);
|
void (*after_at)(void);
|
||||||
void (*error)(void);
|
void (*error)(void);
|
||||||
utc_item_t *utc_tbl; /*utc <20><>*/
|
utc_item_t *utc_tbl; /*utc <20><>*/
|
||||||
unsigned char *urc_buf; /*urc<72><63><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
unsigned char *urc_buf; /*urc<72><63><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
unsigned char *rcv_buf;
|
unsigned char *rcv_buf;
|
||||||
unsigned short urc_tbl_count;
|
unsigned short urc_tbl_count;
|
||||||
unsigned short urc_bufsize; /*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
|
unsigned short urc_bufsize; /*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
|
||||||
unsigned short rcv_bufsize; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
unsigned short rcv_bufsize; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
}at_core_conf_t;
|
}at_core_conf_t;
|
||||||
|
|
||||||
/*AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
|
/*AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int i,j,state;
|
int i,j,state;
|
||||||
void *params;
|
void *params;
|
||||||
void (*reset_timer)(struct at_core *ac);
|
void (*reset_timer)(struct at_core *ac);
|
||||||
bool (*is_timeout)(struct at_core *ac, unsigned int ms); /*ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>*/
|
bool (*is_timeout)(struct at_core *ac, unsigned int ms); /*ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>*/
|
||||||
void (*printf)(struct at_core *ac, const char *fmt, ...);
|
void (*printf)(struct at_core *ac, const char *fmt, ...);
|
||||||
char * (*find)(struct at_core *ac, const char *expect);
|
char * (*find)(struct at_core *ac, const char *expect);
|
||||||
char * (*recvbuf)(struct at_core *ac); /*ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
char * (*recvbuf)(struct at_core *ac); /*ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
unsigned int(*recvlen)(struct at_core *ac); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD>*/
|
unsigned int(*recvlen)(struct at_core *ac); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD>*/
|
||||||
void (*recvclr)(struct at_core *ac); /*<2A><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
void (*recvclr)(struct at_core *ac); /*<2A><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
|
||||||
@ -64,14 +68,14 @@ typedef enum {
|
|||||||
AT_RET_OK = 0, /*ִ<>гɹ<D0B3>*/
|
AT_RET_OK = 0, /*ִ<>гɹ<D0B3>*/
|
||||||
AT_RET_ERROR, /*ִ<>д<EFBFBD><D0B4><EFBFBD>*/
|
AT_RET_ERROR, /*ִ<>д<EFBFBD><D0B4><EFBFBD>*/
|
||||||
AT_RET_TIMEOUT, /*<2A><>Ӧ<EFBFBD><D3A6>ʱ*/
|
AT_RET_TIMEOUT, /*<2A><>Ӧ<EFBFBD><D3A6>ʱ*/
|
||||||
AT_RET_ABORT, /*ǿ<><C7BF><EFBFBD><EFBFBD>ֹ*/
|
AT_RET_ABORT, /*ǿ<><C7BF><EFBFBD><EFBFBD>ֹ*/
|
||||||
}at_return;
|
}at_return;
|
||||||
|
|
||||||
/*AT<41><54>Ӧ */
|
/*AT<41><54>Ӧ */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *param;
|
void *param;
|
||||||
char *recvbuf;
|
char *recvbuf;
|
||||||
unsigned short recvcnt;
|
unsigned short recvcnt;
|
||||||
at_return ret;
|
at_return ret;
|
||||||
}at_response_t;
|
}at_response_t;
|
||||||
|
|
||||||
@ -90,23 +94,23 @@ typedef struct {
|
|||||||
unsigned char type : 3;
|
unsigned char type : 3;
|
||||||
unsigned char abort : 1;
|
unsigned char 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<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------------------------------------------------*/
|
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------------------------------------------------*/
|
||||||
typedef struct at_core{
|
typedef struct at_core{
|
||||||
at_core_conf_t cfg;
|
at_core_conf_t cfg;
|
||||||
at_env_t env;
|
at_env_t env;
|
||||||
at_item_t tbl[10];
|
at_item_t tbl[10];
|
||||||
at_item_t *cursor;
|
at_item_t *cursor;
|
||||||
struct list_head ls_ready, ls_idle; /*<2A><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5>*/
|
struct list_head ls_ready, ls_idle; /*<2A><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5>*/
|
||||||
unsigned int resp_timer;
|
unsigned int resp_timer;
|
||||||
unsigned int urc_timer;
|
unsigned int urc_timer;
|
||||||
at_return ret;
|
at_return ret;
|
||||||
//urc<72><63><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
|
//urc<72><63><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
|
||||||
unsigned short urc_cnt, rcv_cnt;
|
unsigned short urc_cnt, rcv_cnt;
|
||||||
unsigned char suspend: 1;
|
unsigned char suspend: 1;
|
||||||
}at_core_t;
|
}at_core_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user