Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AT
rtthread的at组件在freeRTOS上的移植与应用
发布于 2022-04-06 10:40:32 浏览:2228
订阅该版
[tocm] ### **at组件介绍** 关于at组件的介绍可移步到rtthread的文档中心 AT命令章节,这里不再赘述 ### **移植到freeRTOS** 项目中只用到的at client的功能,所以这里也只移植了client部分。移植分为两块,一块是将at client中使用的线程创建、信号量创建收发等rtthread系统API替换成freeRTOS的,这部分比较简单;另一块是串口数据收发部分,rtthread是基于自带的UART设备驱动框架来做的,并带有数据缓存功能,移植过来需要将其剥离,然后实现串口数据的发送、接收及接收数据的缓存功能。移植后 - 串口数据发送是采用的轮询发送模式 - 串口数据接收使用的是DMA方式 - 接收数据缓存使用的是**顺序队列** 在移植前先来了解下at client的设计思路,有哪些数据结构以及提供了哪些API,注意这些数据结构跟API是移植调整过后的,跟原有的相差不大 ### **数据结构** **at_response** 结构体用于响应数据的接收,**at_urc_table** 结构体是urc数据注册表,**at_client** 结构体是at client控制句柄 ``` struct at_response { /* response buffer */ char *buf; /* the maximum response buffer size, it set by `at_create_resp()` function */ uint16_t buf_size; /* the length of current response buffer */ uint16_t buf_len; /* the number of setting response lines, it set by `at_create_resp()` function * == 0: the response data will auto return when received 'OK' or 'ERROR' * != 0: the response data will return when received setting lines number data */ uint16_t line_num; /* the count of received response lines */ uint16_t line_counts; /* the maximum response time */ uint32_t timeout; }; typedef struct at_response *at_response_t; struct at_client; /* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */ struct at_urc { const char *cmd_prefix; const char *cmd_suffix; void (*func)(struct at_client *client, const char *data, uint16_t size); }; typedef struct at_urc *at_urc_t; struct at_urc_table { size_t urc_size; const struct at_urc *urc; }; typedef struct at_urc *at_urc_table_t; struct at_client { at_status_t status; char end_sign; /* the current received one line data buffer */ char *recv_line_buf; /* The length of the currently received one line data */ uint16_t recv_line_len; /* The maximum supported receive one line data length */ uint16_t recv_line_size; xSemaphoreHandle rx_notice; xSemaphoreHandle lock; at_response_t resp; xSemaphoreHandle resp_notice; at_resp_status_t resp_status; struct at_urc_table *urc_table; uint16_t urc_table_size; /* uart receive queue */ struct array_queue *recv_q; /* The maximum supported receive data length */ uint16_t recv_queue_size; /* uart receive uart */ UART_INDEX_E uart_index; /* handle task */ TaskHandle_t parser; }; typedef struct at_client *at_client_t; ``` ### **API** ``` /* get AT client object */ at_client_t at_client_get_first(void); /* AT client initialize and start*/ at_client_t at_client_init(UART_INDEX_E uart_index, uint16_t recv_line_size, uint16_t recv_queue_size); /* AT client send or receive data */ int at_client_obj_send(at_client_t client, char *buf, int size); int at_client_obj_recv(at_client_t client, char *buf, int size, uint32_t timeout); /* AT client send commands to AT server and waiter response */ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr, ...); /* set AT client a line end sign */ void at_obj_set_end_sign(at_client_t client, char ch); /* Set URC(Unsolicited Result Code) table */ int at_obj_set_urc_table(at_client_t client, const struct at_urc * table, int size); /* AT response object create and delete */ at_response_t at_create_resp(uint16_t buf_size, uint16_t line_num, uint32_t timeout); void at_delete_resp(at_response_t resp); at_response_t at_resp_set_info(at_response_t resp, int buf_size, int line_num, uint32_t timeout); /* AT response line buffer get and parse response buffer arguments */ //获取指定行号的响应数据 const char *at_resp_get_line(at_response_t resp, int resp_line); //根据关键字获取响应数据 const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword); //根据resp_expr格式使用标准sscanf 解析语法,解析指定行的响应数据 int at_resp_parse_line_args(at_response_t resp, int resp_line, const char *resp_expr, ...); //根据resp_expr格式使用标准sscanf 解析语法,解析指定关键字的响应数据 int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...); ``` ### **at client 流程** 用户线程中调用 at_client_init API时会自动创建 parser 线程,parser线程内部实现了 响应数据的接收、响应数据的解析、URC 数据处理等整个AT 命令数据交互流程。 发送数据时的数据流向为:用户线程调用 at_exec_cmd 发送数据 ---> 串口 ---> at server 接收数据时的数据流向为:at server ---> 串口接收,然后发送 rx_notice 信号量 ---> parser线程解析,然后发送 resp_notice 信号量 ![截图.png](https://oss-club.rt-thread.org/uploads/20220406/2a5e50c274edea47984119a6f4ddaf14.png.webp) **串口数据接收处理** 在创建at client处理线程时,需要注册好**串口数据接收回调函数**,这样当串口接收到数据时,就会调用该回调函数,在该回调函数中,会将接收到的数据存入队列中,然后发送信号量通知at client处理线程进行处理 **串口驱动:** ``` typedef enum { UART1_INDEX, UART2_INDEX, UART3_INDEX, UART_INDEX_ALL }UART_INDEX_E; /* stm32 uart dirver class */ struct stm32_uart { const char *name; USART_TypeDef *Instance; IRQn_Type irq_type; int (*rx_ind)(UART_INDEX_E uart_index, char *recv_data, int recv_len); }; extern struct stm32_uart stm32_uart_handle[UART_INDEX_ALL]; extern void set_uart_rx_indicate(UART_INDEX_E uart_index, int (*set_rx_ind)(UART_INDEX_E uart_index, char *recv_data, int recv_len)); extern void uart_send_data_by_index(UART_INDEX_E index, unsigned char *data, unsigned short len); ``` **串口接收中断:** ``` void USART3_IRQHandler( void ) { uint8_t tmp; uint16_t rxLen = 0; if(LL_USART_IsActiveFlag_IDLE(USART3)) { rxLen = sizeof(uart3_dam_rxbuf) - LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_1); if(stm32_uart_handle[UART3_INDEX].rx_ind) { //调用了注册的数据接收回调函数 stm32_uart_handle[UART3_INDEX].rx_ind(UART3_INDEX, uart3_dam_rxbuf, rxLen); } LL_USART_ClearFlag_IDLE(USART3); LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_1); LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, sizeof(uart3_dam_rxbuf)); //将 EN 位置“1”以启动新传输之前,DMA_LISR 或 DMA_HISR 寄存器中与数据流相对应的事件标志必须清零。 LL_DMA_ClearFlag_TE1(DMA1); LL_DMA_ClearFlag_FE1(DMA1); LL_DMA_ClearFlag_TC1(DMA1); LL_DMA_ClearFlag_HT1(DMA1); LL_DMA_EnableStream (DMA1, LL_DMA_STREAM_1); } ... } ``` **at client处理线程注册的接收回调函数** ``` static int at_client_rx_indicate(UART_INDEX_E uart_index, char *recv_data, int recv_len) { int idx = 0, i = 0, res; BaseType_t xHigherPriorityTaskWoken; for (idx = 0; idx < AT_CLIENT_NUM_MAX; idx++) { if (at_client_table[idx].uart_index == uart_index && at_client_table[idx].status == AT_STATUS_INITIALIZED) { for(i=0; i
size) #define ARRAY_QUEUE_NUM(pqueue) (pqueue->num) #define ARRAY_QUEUE_IS_EMPTY(pqueue) (pqueue->num == 0) #define ARRAY_QUEUE_IS_FULL(pqueue) (pqueue->num == pqueue->size) struct array_queue { int size; /* queue total size */ int num; /* queue used size rang:1-(size-1) */ int head; /* points to the the next dequeue data */ int tail; /* points to the the next enqueue data */ int tpsz; /* data type size */ void *p; /* queue space */ }; extern struct array_queue* array_queue_creat(int size, int tpsz); extern int array_queue_init (struct array_queue *queue, int size, int tpsz); extern int array_queue_empty (struct array_queue *queue); extern int array_queue_clear (struct array_queue *queue); extern int array_queue_destory(struct array_queue *queue); extern int array_queue_enqueue(struct array_queue *queue, void *in_data); extern int array_queue_dequeue(struct array_queue *queue, void *out_data); ``` ### **最后** 本文只讲解了移植部分,完整内容可参考[本人博客](https://blog.csdn.net/m0_37845735/article/details/123979583)
9
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
hurryddddd
这家伙很懒,什么也没写!
文章
2
回答
40
被采纳
0
关注TA
发私信
相关文章
1
rt-thread 2g/3g/4g通信模块的教程有吗?
2
基于AT指令,用esp8266如何连接mqtt?
3
AT组件使用问题
4
官方AT客户端应用笔记的几个小tip
5
RTT的SAL能够判断使用LWIP或者AT?
6
rt_therad AT组件移植不成功(结贴)
7
AT组件在哪个版本的?
8
AT组件 连接 Onenet 连接失败
9
esp8266 AT指令 MQTT连接问题
10
AT组件使用问题之模块主动上报【已解决】
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部