STM32 + RT Thread OS 串口通讯
1. 创建项目
a) 禁用Finsh和console
b) 默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1。因此,在运行scons命令生成项目文件之前,修改rtconfig.h,禁用这两项。(下图L65, L70)
c) 生成项目文件
运行scons --target=mdk4 –s
打开生成的项目文件,可以看到,文件组finsh已经不再被包含进来了。
d) 创建echo.c
新建一个C文件echo.c,编写RT_Thread任务入口,COM1侦听,以及初始化函数。示例代码如下:
#include "echo.h" struct rx_msg
{
rt_device_t dev;
rt_size_t size;
}; static struct rt_messagequeue rx_mq;
static char uart_rx_buffer[];
static char msg_pool[]; // 串口侦听回调函数
rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
struct rx_msg msg;
msg.dev = dev;
msg.size = size; // 将接收内容放入消息队列
rt_mq_send(&rx_mq, &msg, sizeof(struct rx_msg)); return RT_EOK;
} // 任务入口函数
void usr_echo_thread_entry(void* parameter)
{
struct rx_msg msg; rt_device_t device;
rt_err_t result = RT_EOK; // 从RT系统中获取串口1设备
device = rt_device_find("uart1");
if (device != RT_NULL)
{
// 指定接收串口内容的回调函数
rt_device_set_rx_indicate(device, uart_input);
// 以读写方式打开设备
rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
} while()
{
// 从消息队列中获取被回调函数放入消息队列中的内容
result = rt_mq_recv(&rx_mq, &msg, sizeof(struct rx_msg), );
if (result == -RT_ETIMEOUT)
{
// timeout, do nothing
} if (result == RT_EOK)
{
rt_uint32_t rx_length; rx_length = (sizeof(uart_rx_buffer) - ) > msg.size ?
msg.size : sizeof(uart_rx_buffer) - ; rx_length = rt_device_read(msg.dev, , &uart_rx_buffer[], rx_length);
uart_rx_buffer[rx_length] = '\0';
// 将内容写回到串口1
rt_device_write(device, , &uart_rx_buffer[], rx_length);
}
}
}
// 串口例程初始化函数
void usr_echo_init()
{
rt_thread_t thread ; rt_err_t result;
// 创建消息队列,分配队列存储空间
result = rt_mq_init(&rx_mq, "mqt", &msg_pool[], - sizeof(void*), sizeof(msg_pool), RT_IPC_FLAG_FIFO); if (result != RT_EOK)
{
rt_kprintf("init message queue failed.\n");
return;
}
// 创建任务线程
thread = rt_thread_create("devt",
usr_echo_thread_entry, RT_NULL,
, , );
// 启动任务线程
if (thread != RT_NULL)
rt_thread_startup(thread);
}
在application.c中加入初始化代码(echo.h略)
L189:usr_echo_init()
在开始编译前,还要修改board.c,注释掉第183行,不然将报错。因为我们禁用了console,所以不需要设置console输出设备。
3. 程序分析
a) 内存分布
查看编译生成的 obj/rtthread-stm32.map文件,可以看到代码及常量,被下载到芯片的0x8000000地址段,最前面的是中断矢量表,第一个中断地址是RESET,矢量表共0x130个字节。
有初始值的变量定义,从地址段0x20000000开始
对应的Stm32内存映射表,代码和常量被下载到Flash,已初始化变量定位到SRAM(可能是下载到Flash,开机初始化后复制到RAM,而不是直接下载到RAM,不然下次运行,初始值可能已被修改)
这是MDK中芯片内存区域的地址分配
这是J-Link对芯片的定义,内存是512K,类型是On-chip Flash,地址空间从0x08000000到0x0807FFFF
b) 程序运行流程
开机后,从Flash 0x080000000处的中断矢量表,取得RESET中断的处理函数入口地址,跳转到入口函数开始执行RESET中断服务,如下图,RESET中断服务函数定义在startup_stm32f10x_hd.s中,先执行了stm32类库中的SystemInit(),再然后转到main()函数。
SystemInit()主要是对芯片的基本设置,如时钟频率。
RT-Thread中,在BSP目录下提供了startup.c,包含了main()函数,它调用了同文件中的rtthread_startup(),再然后rtthread_startup()调用了rt_application_init(),rt_application_init()则在application.c中定义,用户代码就从这里开始。
另外还有一个重要文件是stm32f10x_it.c,这里面定义了中断服务例程,中断矢量表中的地址指向这个文件中相应的服务函数入口地址。比如,我们的串口1收到上位机的消息后,会产生USART1_IRQ,这时芯片就会在0x08000000开始的中断向量表中找到USART1_IRQHandler()的入口地址,跳转后开始执行中断服务函数USART1_IRQHandler()。
当然,要产生中断,需要在初始化代码中开启中断。
<echo.c>
上面贴出了这个文件的源代码,除了uart_input(),其它都比较直观。在RTT系统中,uart_input()只是USART1_IRQHandler()的一部分,在echo.c的初始化代码中,被注册为uart1这个device(RTT封装对象)的回调函数:
L34:rt_device_set_rx_indicate(device, uart_input);
流程参照下图:
STM32 + RT Thread OS 串口通讯的更多相关文章
- STM32 + RT Thread OS 学习笔记[二]
串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1. 目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...
- STM32 + RT Thread OS 学习笔记[三]
RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...
- STM32 + RT Thread OS 学习笔记[四]
1. 补注 a) 硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...
- STM32调试大法 之 串口通讯
开发过程经常需要查看某些特定参数.通常的方法可以使用paintf进行打印输出,观察具体的变量值.STM32内部集成有USART的串口功能,可以通过串口直接输出到电脑(上位机).使用非常方便,基本不需要 ...
- STM32与PC机串口通讯
有时要将板子的信息输出到电脑上来调试之类的,或者把传感器收集到的数据显示到电脑. 当然了,这只是最基本的串口通信,简单的说,是有一根USB线连着的. mbed上并没有能显示printf的功能.需要自己 ...
- stm32串口通讯问题
stm32串口通讯问题 在串口试验中,串口通讯不正常,则可能会出现以下问题: 1. 配置完成后,串口没有任何消息打印. 原因:1,端口配置有问题,需要重新检查I/O口的配置 2,接线有问题,检查接线是 ...
- STM32—串口通讯详解
串口通讯目录 物理层 协议层 USART简介 开发板与上位机的连接 代码讲解: 一.初始化结构体 二.NVIC配置中断优先级 三.USART配置函数讲解 四.传输数据的函数: 1.发送一个字节 2.发 ...
- C#串口通讯实例
本文参考<C#网络通信程序设计>(张晓明 编著) 程序界面如下图: 参数设置界面代码如下: using System; using System.Collections.Generic; ...
- STM32F10x 学习笔记6(USART实现串口通讯 2)
这次讲讲利用串口收发中断来进行串口通讯.STM32 上为每个串口分配了一个中断.也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断.程序需在中断处理函数中读取状态寄存器(USART_SR) ...
随机推荐
- c# 接口使用
- WindowsPE
什么是WindowsPE Windows Preinstallation Environment(Windows PE),Windows预引导环境,是带有有限服务的最小Win32子系统,基于以保护模式 ...
- 运维开发笔记整理-QueryDict对象
运维开发笔记整理-QueryDict对象 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 客户端发送数据请求有很多种,相信运维人员已经很清楚了,如果不太清楚的话可以参考我之前的学习笔 ...
- 使用Wireshark对手机抓包设置说明
一.原因 1.手机目前没有类似的抓包工具可以直接对手机进行抓包 2.一般数据交换的路线是:手机——>运营商——>服务器,可以在手机和运营商中间加一道网卡变成:手机——>PC网卡——& ...
- [课本]JDBC课程6--使用JDBC的DAO模块化--完成数据库的增删查改_工具类JDBCTools四个(Preparedstatement)功能模块的敲定版
(课本P273-任务九) /**DAO: Data Access Object * 为什么用: 实现功能的模块化,更有利于代码的维护和升级 * 是什么: 访问数据信息的类,包含对数据的CRUD(cre ...
- Multiple inheritance in Go
原文:http://golangtutorials.blogspot.com/2011/06/multiple-inheritance-in-go.html --------------------- ...
- DT7.0主动推送当天高质量图片数据到熊掌号展现
<?php /* 百度当天主动推送熊掌功能 作者:68喜科技 用于:DT7.0 功能模块:优质内容推送熊掌*出图内容当天推送 */ //引入全局变量函数 defined('IN_DESTOON' ...
- java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook] with root cause
一.问题描述 使用POI上传excel,本地可正常运行,开发服务器上报错. 二.异常信息如下: 2019-05-05 17:00:22,349 ERROR [http-nio-8080-exec-7] ...
- NO.24两两交换链表中的节点
NO.24两两交换链表中的节点 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例:给定 1->2->3-&g ...
- 073_使用 shell 脚本打印如下图形
#!/bin/bash #打印第一组图片#for(())为类 C 语言的语法格式,也可以使用 for i in;do;done 的格式替换#for((i=1;i<=9;i++))循环会执行 9 ...