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 串口通讯的更多相关文章

  1. STM32 + RT Thread OS 学习笔记[二]

    串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1.   目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...

  2. STM32 + RT Thread OS 学习笔记[三]

    RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...

  3. STM32 + RT Thread OS 学习笔记[四]

    1.  补注 a)      硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...

  4. STM32调试大法 之 串口通讯

    开发过程经常需要查看某些特定参数.通常的方法可以使用paintf进行打印输出,观察具体的变量值.STM32内部集成有USART的串口功能,可以通过串口直接输出到电脑(上位机).使用非常方便,基本不需要 ...

  5. STM32与PC机串口通讯

    有时要将板子的信息输出到电脑上来调试之类的,或者把传感器收集到的数据显示到电脑. 当然了,这只是最基本的串口通信,简单的说,是有一根USB线连着的. mbed上并没有能显示printf的功能.需要自己 ...

  6. stm32串口通讯问题

    stm32串口通讯问题 在串口试验中,串口通讯不正常,则可能会出现以下问题: 1. 配置完成后,串口没有任何消息打印. 原因:1,端口配置有问题,需要重新检查I/O口的配置 2,接线有问题,检查接线是 ...

  7. STM32—串口通讯详解

    串口通讯目录 物理层 协议层 USART简介 开发板与上位机的连接 代码讲解: 一.初始化结构体 二.NVIC配置中断优先级 三.USART配置函数讲解 四.传输数据的函数: 1.发送一个字节 2.发 ...

  8. C#串口通讯实例

    本文参考<C#网络通信程序设计>(张晓明  编著) 程序界面如下图: 参数设置界面代码如下: using System; using System.Collections.Generic; ...

  9. STM32F10x 学习笔记6(USART实现串口通讯 2)

    这次讲讲利用串口收发中断来进行串口通讯.STM32 上为每个串口分配了一个中断.也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断.程序需在中断处理函数中读取状态寄存器(USART_SR) ...

随机推荐

  1. Android笔记(六) Android中的组件

    一个软件可以吸引到用户,除了优秀的功能可以解决用户的问题之外,良好的用户界面也并不可少.一个软件的功能不管多么优秀,但是没有提供友好的界面来让用户操作,将很难吸引到最终用户. Android提供了大量 ...

  2. Android笔记(四) Activity之间的数据传递

    我们之前使用Intent进行Activity之间的跳转,其实Intent还可以在启动活动的时候传递数据. Intent提供了一系列的putExtra方法以便我们把想要传递的数据暂存在Intent中,待 ...

  3. Linux 磁盘、分区、文件系统、挂载

    磁盘 Linux所有设备都被抽象成为一个文件,保存在/dev目录下. 设备名称一般为hd[a-z]或sd[a-z].如果电脑中有多硬盘,则设备名依次为sda.adb.sdc...以此类推 IDE设备的 ...

  4. 记录java+testng运行selenium(三)---xml、ini、excel、日志等配置

    一: ini文件 ini目前只用处存储浏览类型及需要打开的url,ini文件放在configs文件夹下面. 读取ini代码如下: package toolskit.documents; import ...

  5. [Abp vNext微服务实践] - 框架分析

    一.简介 abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了一番研究.我的体验是,vNext的微服务架构确实比较成熟,但是十分难以上手,对于没有微服务开发经验的.n ...

  6. 分享一个自制的USB转HART模块

    HART协议是一种用于现场智能仪表和控制室设备之间的通讯协议.使用USB转HART模块可以很方便的对HART总线上的数据进行监控,并且可以远程控制.操作和校准HART设备.设计的模块主要采用的是USB ...

  7. LESS简介与使用方法

    less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量.Mixin.函数等特性,使 CSS 更易维护和扩展. 一.传统写法与 less 写法对比 1. 传统 css 写法: .con ...

  8. 实例演示MaxTenuringThreshold参数及阈值动态调整策略

    在上一次[https://www.cnblogs.com/webor2006/p/11031563.html]学习了一个新的JVM对象晋升到老年代的参数“MaxTenuringThreshold”,它 ...

  9. machine learning(9) -- classification:Decision boundary

    machine learning(9) -- classification:Decision boundary 上图的decision boundary是一条直线,是属于预测函数的一个属性(当参数已经 ...

  10. redis危险命令

    KEYS 单行遍历,速度很慢很占执行时间,对单核来说,极有可能导致执行完后处理不过来这段时间堆积的任务量,导致雪崩. FLUSHALL FLUSHDB CONFIG 今晚搜索kombu用的key,用了 ...