一、簡(jiǎn)介

EC200S-CN 是移遠(yuǎn)通信最近推出的 LTE Cat 1 無線通信模塊,支持最大下行速率 10Mbps 和最大上行速率 5Mbps,具有超高的性價(jià)比;同時(shí)在封裝上兼容移遠(yuǎn)通信多網(wǎng)絡(luò)制式 LTE Standard EC2x(EC25、EC21、EC20 R2.0、EC20 R2.1)和 EC200T/EG25-G/EG21-G 模塊以及 UMTS/HSPA+ UC20/UC200T 模塊,實(shí)現(xiàn)了 3G 網(wǎng)絡(luò)與 4G 網(wǎng)絡(luò)之間的無縫切換。EC200S-CN 還支持標(biāo)準(zhǔn)的 Mini PCIe 封裝,以滿足不同行業(yè)產(chǎn)品應(yīng)用需求。
Quectel EC2x 模塊具有嵌入式 TCP/IP堆棧,使主機(jī)可以通過 AT 命令直接上網(wǎng)??梢詫?shí)現(xiàn)TCP客戶端、UDP客戶端、TCP服務(wù)器和UDP服務(wù)器。
二、AT指令
2.1 AT
測(cè)試AT指令功能是否正常,等待模塊返回 OK。
AT
OK
2.2 AT + CPIN?
查詢 SIM 卡狀態(tài),返回 READY 則表示SIM卡正常,如果 20 秒后還無法識(shí)別 SIM 卡,重新啟動(dòng)模塊。
AT+CPIN?
+CPIN: READY
OK
2.3 AT + CREG?
查詢模組是否注冊(cè)上GSM網(wǎng)絡(luò),如果 90秒后未能在 CS 上注冊(cè)域名服務(wù),重新啟動(dòng)模塊。
如果返回 1 或 5 ,代表 CS 服務(wù)注冊(cè)成功。
+CREG:0,1 表示已注冊(cè)上本地網(wǎng),+CREG:0,5表示注冊(cè)上漫游網(wǎng)。
AT+CREG?
+CREG: 0,1
OK
2.4 AT + CGREG?
查詢模組是否注冊(cè)上GPRS網(wǎng)絡(luò),+CGREG:0,1 表示已注冊(cè)上本地網(wǎng),+CGREG:0,5表示注冊(cè)上漫游網(wǎng)。
AT+CGREG?
+CGREG: 0,1
OK
2.5 AT + QICSGP=1,1,“CMNET”
該命令可用于配置<APN>,<username>,<password>等TCP / IP上下文參數(shù)。QoS設(shè)置可以由AT + CGQMIN,AT + CGEQMIN,AT + CGQREQ和AT + CGEQREQ配置 。
- AT+QICSGP=?:查詢命令參數(shù)。
- AT+QICSGP=<contextID>:查詢 contextID的配置信息。
- AT+QICSGP=<contextID>[,<context_type>,<APN>[,<username>,<password>)[,<authentication>]]]:配置 contextID信息。
- <contextID>:整數(shù)類型。上下文ID。范圍是1-16。
- <context_type>:整數(shù)類型。協(xié)議類型。1(IPV4)、2(IPV4V6)。
- <APN>:字符串類型。接入點(diǎn)名稱。移動(dòng)CMNET,聯(lián)通UNINET
- <username>:字符串類型。用戶名。
- <password>:字符串類型。密碼。
- <authentication>:整數(shù)類型。身份驗(yàn)證方法。0(沒有)、1(PAP)、2(CHAP)、3(PAP或CHAP)。
- 返回信息:OK 或 ERROR。
AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1
OK
2.6 AT + QIDEACT=1
在激活GPRS場(chǎng)景之前先關(guān)閉GPRS場(chǎng)景,確保連接正確
AT+QIDEACT=1
OK
2.7 AT + QIACT=1
激活移動(dòng)場(chǎng)景
AT+QIACT=1
OK
2.8 AT+QIOPEN
該命令用于打開套接字服務(wù)。
- AT+QIOPEN=?:查詢命令參數(shù)。
- AT+QIOPEN=<contextID>,<connectID>,<service_type>,<IP_address>/<domain_name>,<remote_port>[,<local_po CONNECTrt>[,<access_mode>]] :打開 Socket 服務(wù)。
- <contextID> :整數(shù)類型。上下文ID。范圍是1-16。
- <connectID> :整數(shù)類型。套接字服務(wù)索引。范圍是0-11。
- <SERVICE_TYPE>:字符串類型。套接字服務(wù)類型。
- “ TCP ” :作為客戶端啟動(dòng)TCP連接
- “ UDP ”:作為客戶端啟動(dòng)UDP連接
- “TCP LISTENER” :?jiǎn)?dòng)TCP服務(wù)器以偵聽TCP連接
- “UDP SERVICE” :?jiǎn)?dòng)UDP服務(wù)
- <IP_address>:字符串類型。
- 如果<service_type>是TCP或UDP ,則表示遠(yuǎn)程服務(wù)器的IP地址,例如 “220.180.239.212”。
- 如果<service_type>是TCP LISTENER或UDP SERVICE 地址,請(qǐng)輸入“127.0.0.1”。
- <domain_name>:字符串類型。遠(yuǎn)程服務(wù)器的域名地址。
- <remote_port> :遠(yuǎn)程服務(wù)器的端口,僅在<service_type>為“TCP”或“UDP”時(shí)有效。范圍是0-65535。
- <LOCAL_PORT> :本地端口。范圍是0-65535。
- 如果<service_type>是“TCP LISTENER”或“UDP SERVICE”,則此參數(shù)必須指定。
- 如果<service_type>是“TCP”或“UDP”。如果<local_port>為0,那么本地端口將是自動(dòng)分配。否則,將按指定分配本地端口。
- <access_mode> :整數(shù)類型。套接字服務(wù)的數(shù)據(jù)訪問模式。
- 0: 緩沖區(qū)訪問模式
- 1:直推模式
- 2:透明訪問模式
- <err>:整數(shù)類型。操作的錯(cuò)誤代碼。請(qǐng)參閱第4章。
AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",53540,0,1
OK
+QIOPEN: 0,0
Buffer模式,Push模式,透?jìng)髂J?。通過參數(shù)<access_mode>進(jìn)行配置。





2.9 AT + QISEND
如果指定套接字服務(wù)的<access_mode>是緩沖區(qū)訪問模式或直接推送模式,則數(shù)據(jù)可以是通過AT + QISEND發(fā)送。如果數(shù)據(jù)成功發(fā)送到模塊,將返回“ SEND OK ” 。否則它將返回“ SEND FAIL ” 或“ ERROR ” ?!?SEND FAIL ” 表示發(fā)送緩沖區(qū)已滿客戶可以嘗試重新發(fā)送數(shù)據(jù)?!癊RROR”表示在發(fā)送過程中遇到錯(cuò)誤 數(shù)據(jù)??蛻魬?yīng)該延遲一段時(shí)間來發(fā)送數(shù)據(jù)。最大數(shù)據(jù)長(zhǎng)度為1460字?!癝END OK”并不意味著數(shù)據(jù)已成功發(fā)送到服務(wù)器??蛻艨梢圆樵償?shù)據(jù)是否通過AT + QISEND = <connectID>,0命令到達(dá)服務(wù)器。透?jìng)髂J较虏恍枰狝T指令發(fā)送數(shù)據(jù)


三、TCP/IP AT命令撥號(hào)流程

四、程序大致流程
主要開了三個(gè)定時(shí)器
sendCmdTimer:發(fā)送命令定時(shí)器
sendDataTimer:發(fā)送數(shù)據(jù)定時(shí)器(用于建立TCP連接后發(fā)送數(shù)據(jù))
recvCmdTimer:統(tǒng)一接收命令定時(shí)器

五、移植文件
5.1 board_ec200s.c
/*********************************************************************
* INCLUDES
*/
#include "stdlib.h"
#include "string.h"
#include "app_timer.h"
#include "nrf_log.h"
#include "board_uart.h"
#include "board_ec200s.h"
#include "common.h"
static void clearBuffer(void);
static void reset(void);
static void timer_sendCmdCallback(void *arg);
static void timer_sendDataCallback(void *arg);
static void timer_recvCmdCallback(void *arg);
static void timer_resetCallback(void *arg);
static void sendData(char *pCmd);
/*********************************************************************
* GLOBAL VARIABLES
*/
char g_ec200sBuf[MAX_RECV_BUF_SIZE] = {0}; // 接收緩存
uint32_t g_ec200sCnt = 0; // 接收計(jì)數(shù)
uint8_t g_isEc200sInit = 0;
/*********************************************************************
* LOCAL VARIABLES
*/
APP_TIMER_DEF(s_sendCmdTimer); // 發(fā)送命令的定時(shí)器
APP_TIMER_DEF(s_sendDataTimer); // 發(fā)送數(shù)據(jù)的定時(shí)器
APP_TIMER_DEF(s_recvCmdTimer); // 接收命令的定時(shí)器
APP_TIMER_DEF(s_resetTimer); // 重啟的定時(shí)器
static uint8_t s_sendCmdResult = 0; // 發(fā)送命令結(jié)果
static uint32_t s_waitCmdTime = 0; // 等待命令時(shí)間
static uint8_t s_waitCmdNum = 0; // 等待命令次數(shù)
static bool s_sendCmdFlag = false;
static uint8_t s_sendCmdStep = 0;
static char s_waitCmdBuf[30] = {0}; // 等待比較命令
static bool s_sendDataFlag = false;
static uint8_t s_sendDataStep = 0;
static char s_sendDataBuf[MAX_RECV_BUF_SIZE] = {0};
static char s_recvDataBuf[MAX_RECV_BUF_SIZE] = {0};
static uint32_t s_recvDataLen = 0;
static uint8_t s_isReset = 0;
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief 初始化
@param 無
@return 1 - 成功;0 - 失敗
*/
uint8_t EC200S_Init(void)
{
if((s_sendCmdResult == 0) && (s_isReset == 0))
{
NRF_LOG_INFO("EC200S_Init");
s_sendCmdStep = 0;
StartSendCmdTimer();
StartRecvCmdTimer();
s_sendCmdResult = 2;
}
if(s_sendCmdResult == 1)
{
s_sendCmdResult = 0;
return 1;
}
return 0;
}
/**
@brief 引腳配置
@param 無
@return 無
*/
void EC200S_GpioConfig(void)
{
nrf_gpio_cfg_output(EC200S_GPIO_PIN);
nrf_gpio_pin_write(EC200S_GPIO_PIN, 1);
}
/**
@brief 發(fā)送數(shù)據(jù)到TCP服務(wù)器
@param pString -[in] 發(fā)送數(shù)據(jù)
@return 無
*/
void EC200S_Send(char *pString)
{
if(g_isEc200sInit == 1)
{
sprintf(s_sendDataBuf, "%s\x1A", pString);
s_sendDataStep = 0;
NRF_LOG_INFO("%s", pString);
StartSendDataTimer();
StartRecvCmdTimer();
}
}
/**
@brief 從TCP服務(wù)器接收數(shù)據(jù)
@param pRecvDataBuf -[out] 接收數(shù)據(jù)
@return 接收數(shù)據(jù)長(zhǎng)度
*/
uint32_t EC200S_Receive(char *pRecvDataBuf)
{
uint32_t recvDataLen = 0;
if(s_recvDataLen > 0)
{
memcpy(pRecvDataBuf, s_recvDataBuf, s_recvDataLen);
recvDataLen = s_recvDataLen;
memset(s_recvDataBuf, 0, s_recvDataLen);
s_recvDataLen = 0;
}
return recvDataLen;
}
/**
@brief 創(chuàng)建發(fā)送命令的定時(shí)器
@param 無
@return 無
*/
void CreateSendCmdTimer(void)
{
app_timer_create(&s_sendCmdTimer, APP_TIMER_MODE_REPEATED, timer_sendCmdCallback);
}
/**
@brief 開啟發(fā)送命令的定時(shí)器
@param 無
@return 無
*/
void StartSendCmdTimer(void)
{
app_timer_start(s_sendCmdTimer, SEND_CMD_PERIOD, NULL);
}
/**
@brief 關(guān)閉發(fā)送命令的定時(shí)器
@param 無
@return 無
*/
void StopSendCmdTimer(void)
{
app_timer_stop(s_sendCmdTimer);
}
/**
@brief 創(chuàng)建發(fā)送數(shù)據(jù)的定時(shí)器
@param 無
@return 無
*/
void CreateSendDataTimer(void)
{
app_timer_create(&s_sendDataTimer, APP_TIMER_MODE_REPEATED, timer_sendDataCallback);
}
/**
@brief 開啟發(fā)送數(shù)據(jù)的定時(shí)器
@param 無
@return 無
*/
void StartSendDataTimer(void)
{
app_timer_start(s_sendDataTimer, SEND_DATA_PERIOD, NULL);
}
/**
@brief 關(guān)閉發(fā)送數(shù)據(jù)的定時(shí)器
@param 無
@return 無
*/
void StopSendDataTimer(void)
{
app_timer_stop(s_sendDataTimer);
}
/**
@brief 創(chuàng)建接收命令的定時(shí)器
@param 無
@return 無
*/
void CreateRecvCmdTimer(void)
{
app_timer_create(&s_recvCmdTimer, APP_TIMER_MODE_REPEATED, timer_recvCmdCallback);
}
/**
@brief 開啟接收命令的定時(shí)器
@param 無
@return 無
*/
void StartRecvCmdTimer(void)
{
app_timer_start(s_recvCmdTimer, RECV_CMD_PERIOD, NULL);
}
/**
@brief 關(guān)閉接收命令的定時(shí)器
@param 無
@return 無
*/
void StopRecvCmdTimer(void)
{
app_timer_stop(s_recvCmdTimer);
}
/**
@brief 創(chuàng)建重啟的定時(shí)器
@param 無
@return 無
*/
void CreateResetTimer(void)
{
app_timer_create(&s_resetTimer, APP_TIMER_MODE_SINGLE_SHOT, timer_resetCallback);
}
/**
@brief 處理接收命令
@param 無
@return 1 - 成功;0 - 失敗
*/
uint8_t ReceiveCommandHandler(void)
{
if(strstr((const char *)g_ec200sBuf, "SEND OK") != NULL) // 如果檢索到關(guān)鍵詞SEND OK
{
s_sendDataStep++;
s_sendDataFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "+QISEND:") != NULL) // 如果檢索到關(guān)鍵詞+QISEND:
{
s_sendDataStep++;
s_sendDataFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "+CPIN: READY") != NULL) // 如果檢索到關(guān)鍵詞+CPIN: READY
{
s_sendCmdStep++;
s_sendCmdFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "+CREG: 0,1") != NULL) // 如果檢索到關(guān)鍵詞+CREG: 0,1
{
s_sendCmdStep++;
s_sendCmdFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "+CGREG: 0,1") != NULL) // 如果檢索到關(guān)鍵詞+CGREG: 0,1
{
s_sendCmdStep++;
s_sendCmdFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "OK") != NULL) // 如果檢索到關(guān)鍵詞OK
{
s_sendDataStep++;
s_sendDataFlag = false;
s_sendCmdStep++;
s_sendCmdFlag = false;
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "+QIOPEN:") != NULL) // 如果檢索到關(guān)鍵詞+QIOPEN:
{
NRF_LOG_INFO("Connect Success");
s_sendCmdResult = 1;
s_sendCmdStep++;
s_sendCmdFlag = false;
clearBuffer();
StopSendCmdTimer();
StopRecvCmdTimer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "ERROR") != NULL) // 如果檢索到關(guān)鍵詞ERROR
{
NRF_LOG_INFO("connect error\n");
reset();
clearBuffer();
return 1;
}
else if(strstr((const char *)g_ec200sBuf, "POWERED DOWN") != NULL) // 如果檢索到關(guān)鍵詞POWERED DOWN
{
NRF_LOG_INFO("power down\n");
}
return 0;
}
/**
@brief 處理接收數(shù)據(jù)
@param 無
@return 1 - 成功;0 - 失敗
*/
uint8_t ReceiveDataHandler(void)
{
static bool s_isRecvData;
if(strstr((const char *)g_ec200sBuf, "+QIURC: \"recv\",0,") != NULL) // 如果檢索到關(guān)鍵詞+QIURC: \"recv\",0,
{
s_isRecvData = true;
clearBuffer();
return 1;
}
if(s_isRecvData)
{
memcpy(s_recvDataBuf, g_ec200sBuf, g_ec200sCnt);
s_recvDataLen = g_ec200sCnt;
clearBuffer();
s_isRecvData = false;
return 1;
}
return 0;
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 清空緩存
@param 無
@return 無
*/
static void clearBuffer(void)
{
memset(g_ec200sBuf, 0, sizeof(g_ec200sBuf));
memset(s_waitCmdBuf, 0, sizeof(s_waitCmdBuf));
g_ec200sCnt = 0;
}
/**
@brief 重啟模塊
@param 無
@return 無
*/
static void reset(void)
{
NRF_LOG_INFO("reset\n");
s_isReset = 1;
g_isEc200sInit = 0;
s_sendCmdResult = 0;
s_sendCmdFlag = false;
s_sendDataFlag = false;
StopSendCmdTimer();
StopSendDataTimer();
StopRecvCmdTimer();
nrf_gpio_pin_write(EC200S_GPIO_PIN, 0); // 拉低
app_timer_start(s_resetTimer, RESET_PERIOD, NULL); // 等待2s,再拉高
}
/**
@brief 發(fā)送命令定時(shí)器的回調(diào)函數(shù)
@param 無
@return 無
*/
static void timer_sendCmdCallback(void *arg)
{
if(s_sendCmdStep == 0 && s_sendCmdFlag == false) // 測(cè)試AT指令功能是否正常
{
sendData("AT\r\n");
s_waitCmdTime = 10 * 10; // 10秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 1 && s_sendCmdFlag == false) // 查詢SIM卡是否正常,返回ready則表示SIM卡正常
{
sendData("AT+CPIN?\r\n");
s_waitCmdTime = 20 * 10; // 20秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 3 && s_sendCmdFlag == false) // 查詢模組是否注冊(cè)上GSM網(wǎng)絡(luò)
{
sendData("AT+CREG?\r\n");
s_waitCmdTime = 90 * 10; // 90秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 5 && s_sendCmdFlag == false) // 查詢模組是否注冊(cè)上GPRS網(wǎng)絡(luò)
{
sendData("AT+CGREG?\r\n");
s_waitCmdTime = 60 * 10; // 60秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 7 && s_sendCmdFlag == false) // 配置PDP場(chǎng)景
{
sendData("AT+QICSGP=1,1,\"CMNET\",\"\",\"\",1\r\n");
s_waitCmdTime = 40 * 10; // 40秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 8 && s_sendCmdFlag == false) // 在激活GPRS場(chǎng)景之前先關(guān)閉GPRS場(chǎng)景,確保連接正確
{
sendData("AT+QIDEACT=1\r\n");
s_waitCmdTime = 40 * 10; // 40秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 9 && s_sendCmdFlag == false) // 在激活GPRS場(chǎng)景之前先關(guān)閉GPRS場(chǎng)景,確保連接正確
{
sendData("AT+QIACT=1\r\n");
s_waitCmdTime = 150 * 10; // 150秒
s_sendCmdFlag = true;
}
else if(s_sendCmdStep == 10 && s_sendCmdFlag == false) // 連接服務(wù)器
{
sendData("AT+QIOPEN=1,0,\"TCP\",\"180.97.81.180\",59889,0,1\r\n");
s_waitCmdTime = 150 * 10; // 150秒
s_sendCmdFlag = true;
}
if(s_waitCmdTime == 0) // 沒有響應(yīng)重啟模塊
{
reset();
}
}
/**
@brief 發(fā)送數(shù)據(jù)定時(shí)器的回調(diào)函數(shù)
@param 無
@return 無
*/
static void timer_sendDataCallback(void *arg)
{
if(s_sendDataStep == 0) // 發(fā)送長(zhǎng)度可變數(shù)據(jù)格式
{
sendData("AT+QISEND=0\r\n"); // >會(huì)被斷包,這里特殊處理
s_waitCmdTime = 60 * 10; // 60秒
s_sendDataStep++;
}
else if(s_sendDataStep == 1 && s_sendDataFlag == false) // 發(fā)送實(shí)際數(shù)據(jù)
{
sendData(s_sendDataBuf);
memset(s_sendDataBuf, 0, MAX_RECV_BUF_SIZE);
s_waitCmdTime = 60 * 10; // 60秒
s_sendDataFlag = true;
}
else if(s_sendDataStep == 2 && s_sendDataFlag == false) // 查詢數(shù)據(jù)是否達(dá)到服務(wù)器
{
sendData("AT+QISEND=0,0\r\n");
s_waitCmdTime = 5 * 10; // 5秒
s_waitCmdNum = 23;
s_sendDataFlag = true;
}
else if(s_sendDataStep == 4) // 完成發(fā)送
{
StopSendDataTimer();
StopRecvCmdTimer();
}
if(s_waitCmdTime == 0) // 等待60秒,沒有響應(yīng)重啟模塊
{
s_waitCmdNum--;
if(s_waitCmdNum > 0) // 2分鐘后(每5秒查詢一次,共24次),沒有響應(yīng)重啟模塊
{
sendData("AT+QISEND=0,0\r\n");
s_waitCmdTime = 5 * 10;
s_sendDataStep = 2;
s_sendDataFlag = true;
return;
}
reset();
}
}
/**
@brief 接收命令定時(shí)器的回調(diào)函數(shù)
@param 無
@return 無
*/
static void timer_recvCmdCallback(void *arg)
{
if(s_waitCmdTime == 0)
{
StopRecvCmdTimer();
return;
}
s_waitCmdTime--;
}
/**
@brief 重啟定時(shí)器的回調(diào)函數(shù)
@param 無
@return 無
*/
static void timer_resetCallback(void *arg)
{
nrf_gpio_pin_write(EC200S_GPIO_PIN, 1);
s_isReset = 0;
}
/**
@brief 發(fā)送數(shù)據(jù)
@param pCmd -[in] 命令字符串
@return 無
*/
static void sendData(char *pCmd)
{
UART_WriteData((uint8_t *)pCmd, strlen(pCmd));
}
5.2 board_ec200s.h
#ifndef _BOARD_EC200S_H_
#define _BOARD_EC200S_H_
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* DEFINITIONS
*/
#define EC200S_GPIO_PIN 7
#define MAX_RECV_BUF_SIZE 256
#define SEND_CMD_PERIOD APP_TIMER_TICKS(98) // 98ms
#define SEND_DATA_PERIOD APP_TIMER_TICKS(98) // 98ms
#define RECV_CMD_PERIOD APP_TIMER_TICKS(100) // 100ms
#define RESET_PERIOD APP_TIMER_TICKS(3000) // 3s
/*********************************************************************
* GLOBAL VARIABLES
*/
extern char g_ec200sBuf[MAX_RECV_BUF_SIZE]; // 接收緩存
extern uint32_t g_ec200sCnt; // 接收計(jì)數(shù)
extern uint8_t g_isEc200sInit;
/*********************************************************************
* API FUNCTIONS
*/
uint8_t EC200S_Init(void);
void EC200S_GpioConfig(void);
void EC200S_Send(char *pString);
uint32_t EC200S_Receive(char *pRecvDataBuf);
void CreateSendCmdTimer(void);
void StartSendCmdTimer(void);
void StopSendCmdTimer(void);
void CreateSendDataTimer(void);
void StartSendDataTimer(void);
void StopSendDataTimer(void);
void CreateRecvCmdTimer(void);
void StartRecvCmdTimer(void);
void StopRecvCmdTimer(void);
void CreateResetTimer(void);
uint8_t ReceiveCommandHandler(void);
uint8_t ReceiveDataHandler(void);
#endif /* _BOARD_EC200S_H_ */
5.3 board_uart.c
查看 NRF52832學(xué)習(xí)筆記(12)——UART接口使用
/*********************************************************************
* INCLUDES
*/
#include "nrf_uart.h"
#include "app_uart.h"
#include "board_ec200s.h"
#include "board_uart.h"
#include "user_uart.h"
#include "nrf_log.h"
static void uart_handleEvent(app_uart_evt_t *pEvent);
/*********************************************************************
* LOCAL VARIABLES
*/
static uint8_t s_uartReadDataBuffer[UART_RX_BUF_SIZE] = {0};
static uint8_t s_index = 0;
static bool s_begin = false;
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief 串口驅(qū)動(dòng)初始化
@param 無
@return 無
*/
void UART_Init(void)
{
uint32_t errCode;
app_uart_comm_params_t const commParams =
{
.rx_pin_no = BOARD_UART_RX_IO,
.tx_pin_no = BOARD_UART_TX_IO,
.rts_pin_no = BOARD_UART_RTS_IO,
.cts_pin_no = BOARD_UART_CTS_IO,
.flow_control = APP_UART_FLOW_CONTROL_DISABLED, // 關(guān)掉流控
.use_parity = false,
#if defined (UART_PRESENT)
.baud_rate = NRF_UART_BAUDRATE_115200 // 波特率
#else
.baud_rate = NRF_UARTE_BAUDRATE_115200
#endif
};
APP_UART_FIFO_INIT(&commParams, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE,
uart_handleEvent, APP_IRQ_PRIORITY_LOWEST, errCode);
APP_ERROR_CHECK(errCode);
}
/**
@brief 串口寫數(shù)據(jù)函數(shù)
@param pData -[in] 寫入數(shù)據(jù)
@param dataLen -[in] 寫入數(shù)據(jù)長(zhǎng)度
@return 無
*/
void UART_WriteData(uint8_t *pData, uint8_t dataLen)
{
uint8_t i;
for(i = 0; i < dataLen; i++)
{
app_uart_put(pData[i]);
}
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 串口讀取數(shù)據(jù)處理函數(shù)
@param pEvent -[in] 串口事件
@return 無
*/
static void uart_handleEvent(app_uart_evt_t *pEvent)
{
uint8_t dataChar = 0;
switch(pEvent->evt_type)
{
// 已接收到UART數(shù)據(jù)
case APP_UART_DATA_READY:
{
UNUSED_VARIABLE(app_uart_get(&dataChar));
// 不是回車符或換行符則開始
if(dataChar != '\n' && dataChar != '\r')
{
s_begin = true;
}
if(s_begin)
{
s_uartReadDataBuffer[s_index] = dataChar;
s_index++;
}
// 遇到回車符或換行符結(jié)束
if((s_uartReadDataBuffer[s_index - 1] == '\n') ||
(s_uartReadDataBuffer[s_index - 1] == '\r') ||
(s_index >= MAX_RECV_BUF_SIZE))
{
// NRF_LOG_HEXDUMP_INFO(s_uartReadDataBuffer, s_index);
memcpy(g_ec200sBuf, s_uartReadDataBuffer, s_index); // 接收緩存
g_ec200sCnt = s_index; // 接收計(jì)數(shù)
if(!ReceiveCommandHandler())
{
ReceiveDataHandler();
}
memset(s_uartReadDataBuffer, 0, s_index);
s_index = 0;
s_begin = false;
}
} break;
// 接收過程中發(fā)生通信錯(cuò)誤
case APP_UART_COMMUNICATION_ERROR:
APP_ERROR_HANDLER(pEvent->data.error_communication);
break;
// app_uart模塊使用的FIFO模塊中出現(xiàn)錯(cuò)誤
case APP_UART_FIFO_ERROR:
APP_ERROR_HANDLER(pEvent->data.error_code);
break;
default:
break;
}
}
/****************************************************END OF FILE****************************************************/
5.4 board_uart.h
#ifndef _BOARD_UART_H_
#define _BOARD_UART_H_
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* DEFINITIONS
*/
#define UART_TX_BUF_SIZE 256 // UART TX buffer size
#define UART_RX_BUF_SIZE 256 // UART RX buffer size
#define BOARD_UART_TX_IO 6 // 發(fā)送引腳
#define BOARD_UART_RX_IO 8 // 接收引腳
#define BOARD_UART_CTS_IO 7 // 流量控制發(fā)送清除、低有效
#define BOARD_UART_RTS_IO 9 // 流量控制發(fā)送請(qǐng)求、低有效
/*********************************************************************
* API FUNCTIONS
*/
void UART_Init(void);
void UART_WriteData(uint8_t *pData, uint8_t dataLen);
#endif /* _BOARD_UART_H_ */
五、使用方法
#include "board_ec200s.h"
#include "board_uart.h"
int main(void)
{
log_init();
timers_init();
EC200S_GpioConfig(); // 4G模塊PWK引腳初始化
UART_Init(); // 串口驅(qū)動(dòng)初始化
power_management_init();
ble_stack_init(); // 協(xié)議棧初始化
gap_params_init();
gatt_init();
services_init(); // 服務(wù)初始化
advertising_init(); // 廣播初始化
conn_params_init(); // 連接參數(shù)初始化
advertising_start(); // 開啟廣播
application_timers_start(); // 定時(shí)器應(yīng)用開啟
// Enter main loop.
for(;;)
{
idle_state_handle();
}
}
創(chuàng)建一個(gè)定時(shí)器每200毫秒進(jìn)入一次回調(diào)函數(shù)
/**
@brief 檢查網(wǎng)絡(luò)定時(shí)器的回調(diào)函數(shù)
@param 無
@return 無
*/
static void timer_checkNetworkCallback(void *arg)
{
UNUSED_PARAMETER(arg);
if(g_isEc200sInit == 0)
{
g_isEc200sInit = EC200S_Init(); // 初始化4G模塊
if(g_isEc200sInit == 1)
{
EC200S_Send("hello");
}
}
else if(g_isEc200sInit == 1)
{
char recvDataBuf[256] = {0};
int recvDataLen = EC200S_Receive(recvDataBuf); // 接收服務(wù)器數(shù)據(jù)
if(recvDataLen > 0)
{
// 進(jìn)入處理
}
}
}
? 由 Leung 寫于 2020 年 12 月 4 日
? 參考:移遠(yuǎn) EC200S 模組(4G Cat.1 通信模組)AT指令測(cè)試 TCP/UDP 通信過程
移遠(yuǎn)EC20 R2.0 AT指令撥號(hào)流程
Quectel EC20 R2.1 AT指令集(TCP/部分)