泰凌微(Telink)8258配置串口收发自定义数据

在官网下载SDK后(以Mesh SDK为例)使用Eclipse打开,对应MCU的配置文件在app_config_8258.h,默认的HCI接口是HCI_USE_NONE,如果改成HCI_USE_UART后可以通过串口收发数据,此时默认接收函数处理的是以Telink的协议格式收到的SIG model 命令,函数原型为blc_rx_from_uart(),这个主要用在Gateway工程中。

8258支持一个串口外设,可以不使用HCI_ACCESS宏,自己定义串口相关,以便于连接其他模块等,收发自定义数据。

用户相关的配置可以放在user_app_config.h文件中,比如需要定义一下Tx和Rx引脚。

#define UART_TX_PIN				UART_TX_PB1
#define UART_RX_PIN				UART_RX_PA0

串口可以使用的引脚在硬件设计手册中查找。
在这里插入图片描述
其次是在user_app.h中定义串口需要的相关结构体和宏定义,其中user_uart_data_t结构体为单次DMA接收的数据区内容,dma_len必须是4字节,在收到数据时表示接收到数据的长度;user_uart_que_t为串口数据处理的结构体,采用循环队列控制接收和发送,里面的rx_irq_cnt和tx_irq_cnt只是用来记录进入中断的次数,可以通过BDT工具读取判断是否成功收发数据,无实际意义。

#define USER_UART_DATA_LEN		12
#define USER_UART_DMA_LEN		4typedef struct{unsigned int dma_len;unsigned char data[USER_UART_DATA_LEN];
}user_uart_data_t;typedef struct{unsigned char rx_rear;unsigned char rx_front;unsigned char tx_rear;unsigned char tx_front;u16 rx_irq_cnt;u16 tx_irq_cnt;user_uart_data_t *p_rx_buf;user_uart_data_t *p_tx_buf;
}user_uart_que_t;

另外user_uart_data_t结构体的大小必须是16的整数倍,因为在设置接收缓冲的时候会用接收缓冲区的长度除以16。
在这里插入图片描述
串口的初始化放在Mesh的初始化函数user_init中:
在这里插入图片描述

串口相关变量定义:

user_uart_data_t user_uart_recv_data[USER_MAX_QUE_LEN];
user_uart_data_t user_uart_trans_data[USER_MAX_QUE_LEN];
user_uart_que_t  user_uart_que = {0};
const u16 UART_TX_LEN_MAX = sizeof(user_uart_data_t);

串口的初始化函数原型放在user_app.c中:

void user_uart_drv_init(void)
{user_uart_que_init();uart_recbuff_init( (unsigned char *)&user_uart_recv_data[0], sizeof(user_uart_recv_data), (unsigned char *)&user_uart_trans_data[0]);uart_gpio_set(UART_TX_PIN, UART_RX_PIN);uart_reset();  //will reset uart digital registers from 0x90 ~ 0x9f, so uart setting must set after this reset//baud rate: 115200uart_init(30, 8, PARITY_NONE, STOP_BIT_ONE);uart_dma_enable(1, 1); 	//uart data in hardware buffer moved by dma, so we need enable them firstirq_set_mask(FLD_IRQ_DMA_EN);dma_chn_irq_enable(FLD_DMA_CHN_UART_RX | FLD_DMA_CHN_UART_TX, 1);   	//uart Rx/Tx dma irq enable
}

串口接收处理函数通过判断user_uart_que.rx_rear和user_uart_que.rx_front变量是否相等,来判断接收缓冲队列中是否有未处理的数据,主要更改的是user_uart_que.rx_rear变量,由于是循环队列,中断处理函数在队列已满时也需要改变user_uart_que.rx_rear的值,因此串口接收处理函数中改变user_uart_que.rx_rear的值时需要通过开关中断的方式处理一下。同样串口发送处理函数中是通过user_uart_que.tx_front和user_uart_que.tx_rear的值是否相等来判断是否有待发送的数据,同时也要判断一下串口是否空闲。

int user_rx_from_uart (void)
{u8 curr_p = 0;user_uart_data_t *p_data = NULL;uart_ErrorCLR();if(user_uart_que.rx_front != user_uart_que.rx_rear){u32 r = irq_disable();curr_p = user_uart_que.rx_rear;user_uart_que.rx_rear = (user_uart_que.rx_rear + 1) % USER_MAX_QUE_LEN;irq_restore(r);p_data = &user_uart_recv_data[curr_p];user_recv_data_process(p_data);//对接收到的数据进行处理}return 0;
}int user_tx_to_uart (void)
{if((user_uart_que.tx_front != user_uart_que.tx_rear) && (!uart_tx_is_busy ())){if(uart_Send(user_uart_trans_data[user_uart_que.tx_rear].data, user_uart_trans_data[user_uart_que.tx_rear].dma_len)){user_uart_que.tx_rear = (user_uart_que.tx_rear + 1) % USER_MAX_QUE_LEN;}}return 0;
}

待发送数据入列函数,如果有数据需要发送,可以通过调用user_uart_que_push函数来入列。

void user_uart_que_push(user_uart_data_t *data)
{memcpy((unsigned char *)&user_uart_trans_data[user_uart_que.tx_front],(unsigned char *)data,(data->dma_len + USER_UART_DMA_LEN));user_uart_que.tx_front = (user_uart_que.tx_front + 1) % USER_MAX_QUE_LEN;if(user_uart_que.tx_front == user_uart_que.tx_rear){user_uart_que.tx_rear = (user_uart_que.tx_rear + 1) % USER_MAX_QUE_LEN;}
}

然后在main.c中的irq_uart_handle函数中添加串口的中断处理函数,在收到一帧数据时,需要设置一下串口DMA接收缓冲的地址,指向下一个空闲的数据接收区域,这样的话就不用把接收到的数据拷贝到另外的地方,这也就是为什么需要用队列的方式接收数据。

在串口中断中主要更改的是串口队列中的user_uart_que.rx_front变量,用于指示下一个接收的缓冲区,当user_uart_que.rx_front加1和user_uart_que.rx_rear变量相等时,意味着接收缓冲区满了,接收到的数据一直没有被处理,此时user_uart_que.rx_rear变量也要加1,也就是覆盖掉最早接收到的数据。

_attribute_ram_code_ void user_irq_uart_handle()
{unsigned char irqS = reg_dma_rx_rdy0;if(irqS & FLD_DMA_CHN_UART_RX)	//rx{user_uart_que.rx_irq_cnt++;reg_dma_rx_rdy0 = FLD_DMA_CHN_UART_RX;user_uart_que.rx_front = (user_uart_que.rx_front + 1) % USER_MAX_QUE_LEN;if (user_uart_que.rx_rear == user_uart_que.rx_front){user_uart_que.rx_rear = (user_uart_que.rx_rear + 1) % USER_MAX_QUE_LEN;}user_uart_que.p_rx_buf = &user_uart_recv_data[user_uart_que.rx_front];reg_dma0_addr = (u16)((u32)user_uart_que.p_rx_buf);}if(irqS & FLD_DMA_CHN_UART_TX)	//tx{user_uart_que.tx_irq_cnt++;reg_dma_rx_rdy0 = FLD_DMA_CHN_UART_TX;}
}

然后就是在主函数中循环调用串口收发处理函数:

void user_main_loop(void)
{user_rx_from_uart();user_tx_to_uart();
}

在user_app_config.h中补充CB_USER_MAIN_LOOP()宏定义

#define CB_USER_MAIN_LOOP()		user_main_loop()
#define CB_USER_INIT()			user_app_init()

至此,就可以通过串口收发自定义数据。

如果需要使用串口打印log,可以使用模拟串口,只能发送,打开HCI_LOG_FW_EN宏,同时定义一下串口的引脚:

#define HCI_LOG_FW_EN				1#if HCI_LOG_FW_EN
#define DEBUG_INFO_TX_PIN           		GPIO_PC2
#define PRINT_DEBUG_INFO                    1
#endif

模拟串口的波特率在myprintf.h中设置,默认1000000,如果接收到的数据乱码,可以更换串口或者降低波特率。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/256758.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LNMP网站架构分布式搭建部署(编译安装)

目录 一、数据库编译安装 二、nginx编译安装 三、php编译安装 三、通过nfs将三台不同的主机资源共享 四、基础测试 五、完成WordPress站点部署 六、完成bbs论坛站点部署 一、数据库编译安装 1、先下载安装包到/opt目录中,最好选择mysql-boost-5.7.44.tar.gz版…

【LeetCode:1466. 重新规划路线 | DFS + 图 + 树】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

在JSP项目中编写一个接口返回JSON 供JSP界面异步请求数据

首先 我们要引入json处理的依赖工具 在 pom.xml文件的 dependency 标签中加入如下代码 <dependency><groupId>com.googlecode.json-simple</groupId><artifactId>json-simple</artifactId><version>1.1.1</version> </dependenc…

探索人工智能领域——每日20个名词详解【day11】

目录 前言 正文 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如需转载&#xff0c;请事先与我联系以…

NOIP2014提高组第二轮day1 - T3:飞扬的小鸟

#题目链接 [NOIP2014 提高组] 飞扬的小鸟 题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度&#xff0c;让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话&#xff0c;便宣告失败…

Vue + Element 实现按钮指定间隔时间点击

1、业务需求 需要加一个按钮&#xff0c;调用第三方API&#xff0c;按钮十分钟之内只能点击一次&#xff0c;刷新页面也只能点击一次 2、思路 加一个本地缓存的时间戳&#xff0c;通过时间戳计算指定时间内不能点击按钮 3、实现 1&#xff09;vue页面 <template>&l…

MQTT源码分析

目录 MQTT源码分析 1. MQTT客户端功能 2. 客户端软件如何实现 3. 程序分层 4. 情景分析 4.1 连接服务器 4.2 创建线程 4.3 发布消息 4.4 最复杂&#xff1a;订阅消息 MQTT源码分析 分析源码&#xff1a;mqttclient\test\emqx\test.c 参考资料&#xff1a; kawaii-mqt…

【Docker】从零开始:18.使用Dockerfile构造自己的KingbaseES数据库镜像

【Docker】从零开始&#xff1a;17.使用Dockerfile构造自己的数据库镜像 新建一个自定义目录并创建Dockerfile文件上传需要的文件到自定义目录下注意docker-circle-init.sh文件内容password 内容 开始打包注意打包完成后执行 尝试用工具连接数据库 kingbase.tar.gz 包过大我就上…

Spring Boot HTTP 400 错误的日志信息在哪里查看 ?

HTTP 400 一般来说是入参的某些字段的格式不对 Spring Boot项目启动后默认是不会把相应的日志打印在控制台的 需要在logback.xml里面做相关的配置才会打印出来 具体配置如下 <configuration><appender name"stdout" class"ch.qos.logback.core.Con…

QT----Visual Studio输入中文报错,常量中有换行符

问题描述 在VS中写qt时发现在标题中输入了中文直接把报错无法运行 解决方法1 修改文件的编码方式。在VS菜单栏 工具->自定义-》命令-》选择文件-》添加高级保存选项命令。 双加选中添加中文的文件&#xff0c;文件-》高级保存选项-》修改utf-8就可以运行了 解决方法2…

【webpack】应用篇

基础应用 代码分离常用的代码分离方法方法一&#xff1a;配置入口节点方法二&#xff1a;防止重复方法三&#xff1a;动态导入 缓存原因解决思路 缓存第三方库原因解决思路 将所有js文件单独存放文件夹拆分开发环境和生产环境配置公共路径环境变量和区分环境代码压缩 拆分配置文…

第二十一章总结博客

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission …