专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
【ALIENTEK 战舰STM32开发板例程系列连载+教学】第九章 串口实验
2019-07-20 22:46
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
9906
9
1776
第九章
串口实验
前面两章介绍了
STM32
的
IO
口操作。这一章我们将学习
STM32
的串口,教大家如何使用
STM32
的串口来发送和接收数据。本章将实现如下功能:
STM32
通过串口和上位机的对话,
STM32
在收到上位机发过来的字符串后,原原本本的返回给上位机。本章分为如下几个小节:
9.1 STM32
串口简介
9.2
硬件设计
9.3
软件设计
9.4
下载验证
9.1 STM32
串口简介
串口作为
MCU
的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的
MCU
都会带有串口,
STM32
自然也不例外。
STM32
的串口资源相当丰富的,功能也相当强劲。
ALIENTEK
战舰
STM32
开发板所使用的
STM32F103ZET6
最多可提供
5
路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持
LIN
、支持调制解调器操作、智能卡协议和
IrDA SIR ENDEC
规范、具有
DMA
等。
5.3
节对串口有过简单的介绍,接下来我们将从寄存器层面,告诉你如何设置串口,以达到我们最基本的通信功能。本章,我们将实现利用串口
1
不停的打印信息到电脑上,同时接收从串口发过来的数据,把发送过来的数据直接送回给电脑。战舰
STM32
开发板板载了
1
个
USB
串口和
1
个
RS232
串口,我们本章介绍的是通过
USB
串口和电脑通信。
串口最基本的设置,就是波特率的设置。
STM32
的串口使用起来还是蛮简单的,只要你开启了串口时钟,并设置相应
IO
口的模式,然后配置一下波特率,数据位长度,奇偶校验位等信息,就可以使用了,详见
5.3.2
节。下面,我们就简单介绍下这几个与串口基本配置直接相关的寄存器。
1
,串口时钟使能。串口作为
STM32
的一个外设,其时钟由外设时钟使能寄存器控制,这里我们使用的串口
1
是在
APB2ENR
寄存器的第
14
位。
APB2ENR
寄存器在之前已经介绍过了,这里不再介绍。只是说明一点,就是除了串口
1
的时钟使能在
APB2ENR
寄存器,其他串口的时钟使能位都在
APB1ENR
寄存器。
2
,串口复位。当外设出现异常的时候可以通过复位寄存器里面的对应位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。串口
1
的复位是通过配置
APB2RSTR
寄存器的第
14
位来实现的。
APB2RSTR
寄存器的各位描述如图
9.1.1
所示:
图
9.1.1 APB2RSTR
寄存器各位描述
从图
9.1.1
可知串口
1
的复位设置位在
APB2RSTR
的第
14
位。通过向该位写
1
复位串口
1
,写
0
结束复位。其他串口的复位位在
APB1RSTR
里面。
3
,串口波特率设置。在
5.3.2
节,我们已经介绍过了,每个串口都有一个自己独立的波特率寄存器
USART_BRR
,通过设置该寄存器就可以达到配置不同波特率的目的。具体实现方法,请参考
5.3.2
节。
4
,串口控制。
STM32
的每个串口都有
3
个控制寄存器
USART_CR1~3
,串口的很多配置都是通过这
3
个寄存器来设置的。这里我们只要用到
USART_CR1
就可以实现我们的功能了,该寄存器的各位描述如图
9.1.2
所示:
图
9.1.2 USART_CR
寄存器各位描述
该寄存器的高
18
位没有用到,低
14
位用于串口的功能设置。
UE
为串口使能位,通过该位置
1
,以使能串口。
M
为字长选择位,当该位为
0
的时候设置串口为
8
个字长外加
n
个停止位,停止位的个数(
n
)是根据
USART_CR2
的
[13:12]
位设置来决定的,默认为
0
。
PCE
为校验使能位,设置为
0
,则禁止校验,否则使能校验。
PS
为校验位选择,设置为
0
则为偶校验,否则为奇校验。
TXIE
为发送缓冲区空中断使能位,设置该位为
1
,当
USART_SR
中的
TXE
位为
1
时,将产生串口中断。
TCIE
为发送完成中断使能位,设置该位为
1
,当
USART_SR
中的
TC
位为
1
时,将产生串口中断。
RXNEIE
为接收缓冲区非空中断使能,设置该位为
1
,当
USART_SR
中的
ORE
或者
RXNE
位为
1
时,将产生串口中断。
TE
为发送使能位,设置为
1
,将开启串口的发送功能。
RE
为接收使能位,用法同
TE
。
其他位的设置,这里就不一一列出来了,大家可以参考《
STM32
参考手册》第
542
页有详细介绍,在这里我们就不列出来了。
5
,数据发送与接收。
STM32
的发送与接收是通过数据寄存器
USART_DR
来实现的,这是一个双寄存器,包含了
TDR
和
RDR
。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。该寄存器的各位描述如图
9.1.3
所示:
图
9.1.3 USART_DR
寄存器各位描述
可以看出,虽然是一个
32
位寄存器,但是只用了低
9
位(
DR[8
:
0]
),其他都是保留。
DR[8
:
0]
为串口数据,包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用
(TDR)
,一个给接收用
(RDR)
,该寄存器兼具读和写的功能。
TDR
寄存器提供了内部总线和输出移位寄存器之间的并行接口。
RDR
寄存器提供了输入移位寄存器和内部总线之间的并行接口。
当使能校验位
(USART_CR1
种
PCE
位被置位
)
进行发送时,写到
MSB
的值
(
根据数据的长度不同,
MSB
是第
7
位或者第
8
位
)
会被后来的校验位该取代。
当使能校验位进行接收时,读到的
MSB
位是接收到的校验位。
6
,串口状态。串口的状态可以通过状态寄存器
USART_SR
读取。
USART_SR
的各位描述如图
9.1.4
所示:
图
9.1.4 USART_SR
寄存器各位描述
这里我们关注一下两个位,第
5
、
6
位
RXNE
和
TC
。
RXNE
(读数据寄存器非空),当该位被置
1
的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候我们要做的就是尽快去读取
USART_DR
,通过读
USART_DR
可以将该位清零,也可以向该位写
0
,直接清除。
TC
(发送完成),当该位被置位的时候,表示
USART_DR
内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式:
1
)读
USART_SR
,写
USART_DR
。
2
)直接向该位写
0
。
通过以上一些寄存器的操作外加一下
IO
口的配置,我们就可以达到串口最基本的配置了,关于串口更详细的介绍,请参考《
STM32
参考手册》第
516
页至
548
页,通用同步异步收发器一章。
9.2
硬件设计
本实验需要用到的硬件资源有:
1)
指示灯
DS0
2)
串口
1
串口
1
之前还没有介绍过,本实验用到的串口
1
与
USB
串口并没有在
PCB
上连接在一起,需要通过跳线帽来连接一下。这里我们把
P6
的
RXD
和
TXD
用跳线帽与
PA9
和
PA10
连接起来。如图
9.2.1
所示:
图
9.2.1
硬件连接图示意图
连接上这里之后,我们在硬件上就设置完成了,可以开始软件设计了。
9.3
软件设计
本章的代码设计,比前两章简单很多,因为我们的串口初始化代码和接收代码就是用我们之前介绍的
SYSTEM
文件夹下的串口部分的内容。这里我们对代码部分稍作讲解。
打开上一章的
TEST
工程,然后在
SYSTEM
组下双击
usart.c
,我们就可以看到该文件里面的代码,先介绍
uart_init
函数,该函数代码如下:
//
初始化
IO
串口
1
//pclk2
CLK2
时钟频率
(Mhz)
//bound:
波特率
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//
得到
USARTDIV
mantissa=temp;
//
得到整数部分
fraction=(temp-mantissa)*16; //
得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2;
//
使能
PORTA
口时钟
RCC->APB2ENR|=1<<14;
//
使能串口时钟
GPIOA->CRH&=0XFFFFF00F;//IO
状态设置
GPIOA->CRH|=0X000008B0;//IO
状态设置
RCC->APB2RSTR|=1<<14;
//
复位串口
1
RCC->APB2RSTR&=~(1<<14);//
停止复位
//
波特率设置
USART1->BRR=mantissa; //
波特率设置
USART1->CR1|=0X200C;
//1
位停止
,
无校验位
.
#if EN_USART1_RX
//
如果使能了接收
//
使能接收中断
USART1->CR1|=1<<8;
//PE
中断使能
USART1->CR1|=1<<5;
//
接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//
组
2
,最低优先级
#endif
}
从该代码可以看出,其初始化串口的过程,和我们前面介绍的一致。先计算得到
USART1->BRR
的内容。然后开始初始化串口引脚,接着把
USART1
复位,然之后设置波特率和奇偶校验等。
这里需要注意一点,因为我们使用到了串口的中断接收,必须在
usart.h
里面设置
EN_USART1_RX
为
1
(默认设置就是
1
的)
。该函数才会配置中断使能,以及开启串口
1
的
NVIC
中断。这里我们把串口
1
中断放在组
2
,优先级设置为组
2
里面的最低。
串口
1
的中断服务函数
USART1_IRQHandler
,在
5.3.1
已经有详细介绍了,这里我们就不再介绍了。
介绍完了这两个函数,我们回到
test.c
,在
test.c
里面编写如下代码:
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
int main(void)
{
u16 t;
u16 len;
u16 times=0;
Stm32_Clock_Init(9);
//
系统时钟设置
uart_init(72,9600);
//
串口初始化为
9600
delay_init(72);
//
延时初始化
LED_Init();
//
初始化与
LED
连接的硬件接口
BEEP_Init();
//
初始化蜂鸣器端口
KEY_Init();
//
初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3FFF;//
得到此次接收到的数据长度
printf("
您发送的消息为
: ");
for(t=0;t<len;t++)
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//
等待发送结束
}
printf(" ");//
插入换行
USART_RX_STA=0;
}else
{
times++;
if(times%5000==0)
{
printf("
战舰
STM32
开发板
串口实验
");
printf("
正点原子
@ALIENTEK ");
}
if(times%200==0)printf("
请输入数据
,
以回车键结束
");
if(times%30==0)LED0=!LED0;//
闪烁
LED,
提示系统正在运行
.
delay_ms(10);
}
}
}
这段代码比较简单,重点看下以下两句:
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//
等待发送结束
第一句,其实就是发送一个字节到串口,通过直接操作寄存器来实现的。第二句呢,就是我们在写了一个字节在
USART1->DR
之后,要检测这个数据是否已经被发送完成了,通过检测
USART1->SR
的第
6
位,是否为
1
来决定是否可以开始第二个字节的发送。
其他的代码比较简单,我们执行编译之后看看有没有错误,没有错误就可以开始仿真与调试了。整个工程的编译结果如图
9.3.1
所示:
图
9.3.1
编译结果
可以看到,编译没有哦任何错误和警告,下面我们可以开始下载验证了。
9.4
下载验证
前面
2
章实例,我们均介绍了软件仿真,仿真的基本技巧也差不多介绍完了,接下来我们将淡化这部分,因为代码都是经过作者检验,并且全部在
ALIENTEK
战舰
STM32
开发板上验证了的,有兴趣的朋友可以自己仿真看看。但是这里要说明几点:
1
,
IO
口复用的,信号在逻辑分析窗口是不能显示出来的(看不到波形),这一点请大家注意。比如串口的输出,
SPI
,
USB
,
CAN
等。你在仿真的时候在该窗口看不到任何信息。遇到这样的情况,你就不得不准备一个逻辑分析仪,外加一个
ULINK
或者
JTAG
来做在线调试。但一般情况,这些都是有现成的例子,不用这几个东西一般也能编出来。
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
9条回答
jidian0177
1楼-- · 2019-07-21 03:50
原子哥,我接上USB转串口的线,PA9 PA10也跳了线,打开串口助手,怎么没有接收呢?
加载中...
正点原子
2楼-- · 2019-07-21 05:09
精彩回答 2 元偷偷看……
加载中...
jidian0177
3楼-- · 2019-07-21 08:05
回复【3楼】正点原子:
---------------------------------
是的,接上这个没数据,我又直接将串口线接到PA9 
A10上,有数据,但是乱码。
加载中...
正点原子
4楼-- · 2019-07-21 08:32
回复【4楼】jidian0177:
---------------------------------
接TTL串口才行,RS232不行。
加载中...
jidian0177
5楼-- · 2019-07-21 09:11
回复【5楼】正点原子:
---------------------------------
恩,换了就好了。 原子哥,为什么用232接PA9 
A10不可以呢?
加载中...
正点原子
6楼-- · 2019-07-21 14:25
回复【6楼】jidian0177:
---------------------------------
因为没连接到RS232上面去。
加载中...
1
2
下一页
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
---------------------------------
是的,接上这个没数据,我又直接将串口线接到PA9 A10上,有数据,但是乱码。
---------------------------------
接TTL串口才行,RS232不行。
---------------------------------
恩,换了就好了。 原子哥,为什么用232接PA9 A10不可以呢?
---------------------------------
因为没连接到RS232上面去。
一周热门 更多>