这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【原创】STM32串口使用和简单使用蓝牙模块-from哲

共1条 1/1 1 跳转至

【原创】STM32串口使用和简单使用蓝牙模块-from哲

工程师
2023-10-19 21:16:37     打赏

STM32串口使用和简单使用蓝牙模块

本次使用的是STM32F103RCT6核心板,来驱动串口1。使用标准库编程

查看原理图可以看到串口1对应引脚为TXD//PA9,RXD//PA10。

第一步就是编写串口初始化函数

1697721219193194.png

serial_Init()

其中第一步是将对应引脚初始化,引脚初始化步骤是开启时钟并配置结构体完成初始化。

当我们在配置结构体中配置引脚输入与输出模式时,可以参考官方文档《8.1.11 外设的GPIO配置》章节,

1697721137939669.png 

我们使用的全双工模式,也就是可以同时收发,所以需要将串口的TX引脚配置为推挽复用输出模式,RX配置为浮空输入,或上拉输入。

完整代码如下:

图片1.png 

串口的配置与引脚配置相似,串口分为异步和同步模式,同步模式需要一根时钟线,异步模式不需要,所以我们选择使用异步模式。查看官方文档发现使用异步模式需要配置串口初始化结构体的这些成员

图片2.png 

所以我们在代码中对其进行配置,完整配置如下

图片3.png 

结构体配置中

波特率我们选择常用的115200,硬件流控制和奇偶校验暂时用不到所以我们选择关闭,停止位选择1位,数据位数选择8位,因为一个字节刚好对应8位,便于传输数据,模式我们选择接收和发送模式,也就是不仅能发,也能收。

由于我们想要实现收发模式,发的时候简单,只要发送出去就可以了,但是接收需要程序去接收,这时我们就要开启接收中断了,因为你不知道什么时候有数据会发送过来,也不能让程序为了接收数据,啥也不干吧,有了中断,就可以定义一个全局数组,接收到的数据放到数据里面,供主函数使用。

具体实现是不要忘记使用NVIC配置中断通道,和中断优先级分组,但分组在整个工程中仅配置一次。

图片4.png 

以上就是初始化函数的配置过程。

接下来我们继续写发送字符串的函数serial_send_String(uint8_t String[]);

因为输出字符串使用的最多,所以这里以输出字符串为例,其他函数读者请自行实现。

从字符串的定义中我们知道,区分字符串是否结束的标志就是’\0’,当程序检测到这个字符时意味着当前字符串已经结束。

所以我们使用串口输出字符串就可以通过程序逐个输出字符数组中的字符,知道字符为’\0’时,停止输出。因为标准库里面有串口输出数据的函数USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

所以让整个事情变得更加简单,并且因为我们之前配置的是一帧接收或发送8位数据,所以这个函数在我们的程序中实际上就是发送一个字节的函数,一个字节刚好就是一个字符,所以接下来的实现过程就变得非常简单啦!但是这里也有需要注意的地方,就是发送数据不能过快,虽然单片机能够很快的将需要发送的数据,移动到串口发送寄存器供串口发送,但是串口发送数据的速度并不能跟上单片机移动数据的速度,所以容易导致数据覆盖问题。怎么解决这个问题呢?答案就是使用标准库中提供的获取标志位函数USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG),获取串口发送寄存器空标志位,并等待该位置位。

下面是实现的代码。

图片5.png 

本着边编程边测试的理念测试了一下,这个是测试的主函数 

下面是测试过程中使用串口助手接收到的数据

图片7.png 

从上面的结果看出达到了预期目的,好了,既然我们实现了发送,那么我们接下来就来实现接受吧!接收使用中断完成的,所以我们的主要任务就是写中断函数,在startup_stm32f10x_hd.s这个文件中找到相对应的中断函数名USART1_IRQHandler

下面就开始写接收函数了。

这里我们在串口文件中定义了两个全局变量

图片7.png 

用于接收数据,和判断是否接受到了数据。

在中断函数中,判断中断源和清除中断标志位的操作就不介绍了,主要需要理解的是如何通过这个函数接收字符串。第一步就是当未接收完成时,继续接受,并且相应的下标也+1,当接收的字符为’\0’时,即字符串到结尾了,此时置相应标志位并且下标回归到0。

可能这个时候就有人问了,为什么接收与接收之间不需要去清除接收数据的数组,不怕两次的数据串到一块儿吗?其实是因为字符串尾部总是有一个’\0’字符,并且接受完一个字符串就将下标移回0,可以让每次接收的字符串隔离开来。这样我们就不用担心数据会混淆了。

当然了当数据接收太快的时候也会导致两次数据出现覆盖的问题,但是一般我们不需要那么高的接受速度,所以暂时不考虑那种情况,完整代码如下:

图片8.png 

测试一下,测试主函数。

图片9.png 

测试结果:

图片10.png 

通过测试结果可以看出接收功能实现正常。

然后我们看一下蓝牙模块的使用,发现蓝牙模块通电之后就自动进入透传模式了,蓝牙模块与单片机的通信方式刚好是串口所以,我们刚刚写的代码,可以几乎原封不动的用于蓝牙模块。我们看一下蓝牙模块的官方文档,上面介绍了蓝牙模块默认波特率是9600,所以我们的程序只要将波特率改为9600,就可以使用蓝牙了。

图片11.png 

试一下 

图片12.png 

完美适配!




关键词: MarsZ的嵌入式    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]