分享

【青风带你学stm32f051系列教程】第9课 串口UART | 爱板网

 weikong66 2013-03-28
【青风带你学stm32f051系列教程】第9课 串口UART
2013年01月11日 ? 教程 ? 评论数 2 ? 被围观 926+

串口通信也称为异步串行通信,学过51的同学都会知道串口通信。串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。串口通信的概念非常简单,串口按位(bit)发送和接收字节。

通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。 对于两个进行通信的端口,这些参数必须匹配:

a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,波特率除数(baud-rate divisor)是一个22位数,它由16位整数和6位小数组成。波特率发生器使用这两个值组成的数字来决定位周期。通过带有小数波特率的除法器,在足够高的系统时钟速率下,UART可以产生所有标准的波特率,而误差很小。

波特率除数公式:

BRD = BRDI.BRDF = SystemClock/(16×BaudRate)

其中:

BRD是22位的波特率除数,由16位整数和6位小数组成

BRDI是BRD的整数部分

BRDF是BRD的小数部分

SystemClock是系统时钟(UART模块的时钟直接来自SystemClock)

BaudRate是波特率(9600,38400,115200等)

b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际

的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。

c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位为1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。

下面来看下STM32F051是如何实现串口功能的:

硬件准备:

Stm32f051开发板串口连接入下图所示:

 RXD--PA10 接收数据线    TXD--PA9 发送数据线

软件准备:

软件配置采用直接调用stm库函数,工程配置入下图所示,开发者只需要编写UART.C子驱动函数就可以在main中直接调用了:

串口的库函数stm32f0xx_usart.c文件中,用于配置串口的关键参数被写成一个结构体的形式,如下代码所示:

1
2
3
4
5
6
7
8
9
10
typedef struct
{
 uint32_t USART_BaudRate; //串口波特率
 uint32_t USART_WordLength; //数据位宽
 uint32_t USART_StopBits; //停止位宽
 uint32_t USART_Parity; //效验位宽
 uint32_t USART_Mode; //工作模式
 uint32_t USART_HardwareFlowControl; //流控制
} USART_InitTypeDef;

上面的结构体设置了串口通信的几个数据流参数,包括传输方式:单工,全双工,半双工,下图为8BIT数据位的帧格式:

在uart.c驱动函数中,时钟串口初始化可以按下面来设置,当然在这之前需要设置串口所使用的IO端口,由于IO端口属于复用功能,采用GPIO_PinAFConfig进行复用设置,复用数可以参考stm32f051r8数据手册,如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);//按上表所示,复用功为1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //设置端口复用
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;//设置串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//设置效验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //设置工作模式
USART_Init(USART1, &USART_InitStructure); //配置入结构体
USART_Cmd(USART1, ENABLE);//使能串口1

那么上面的代码就对串口进行了初始化,归纳一下串口初始化的大体步骤,实际上其他的API功能采用库函数的话,都是相同的初始化方式:

1.初始化IO端口,使用外部API功能需要端口复用GPIO_Mode_AF

2.设置AF的数,范围为0—7;

3.设置API的相应参数,比如串口上面提到了参数结构体,ST库函数已经配置好。

初始化后,需要些一些小的功能函数,包括串口直接的发送和接收,代码可以配置

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void UART_send_byte(uint8_t byte) //发送1字节数据
{
 while(!((USART1->ISR)&(1<<7)));//等待发送完
 USART1->TDR=byte; //发送一个字节
}
  
void UART_Send(uint8_t *Buffer, uint32_t Length)
{
 while(Length != 0)
 {
 while(!((USART1->ISR)&(1<<7)));//等待发送完
 USART1->TDR= *Buffer;
 Buffer++;
 Length--;
 }
}
uint8_t UART_Recive(void)
{
 while(!(USART1->ISR & (1<<5)));//等待接收到数据
 return(USART1->RDR); //读出数据
}

由于使用寄存器配置功能函数比较简单,我直接使用寄存器ISR,TDR和RDR进行编写,其中ISP表示串口状态标志位,其中第7位和第5位如下表所示:

TXE表示发送数据是否为空标志位,取0表示数据没有转换到移位寄存器内,取1表示已经转移,为空,此时就可以判断是否发送完成,可以表示为:!((USART1->ISR)&(1<<7))。

RXNE表示接收寄存器是否为空,取0表示没有读取数据,取1表示接收数据,此时可以表示为:!((USART1->ISR)&(1<<7))。

TDR和RDR分别表示接收数据寄存器和发送数据寄存器,分别只取低8位。

那么用户需要编写的串口驱动子函数已经完成,这部分很硬件是密切相关的,我们在写主函数的时候只需要调用上面的驱动就可以进行数据的发送和接收了。下面主函数就演示一个串口发送数据的例子,代码如下:

1
2
3
4
5
6
7
8
9
10
11
int main(void)
{
/* USART1 config 115200 8-N-1 */
 USART_Configuration();//首先配置串口的数据参数,包括工作方式和帧格式,IO端口的复用
while (1)
 {
 UART_Send( Tx_Buffer, countof(Tx_Buffer)-1);//然后发送一个数组
 delay(10000000);
 }
}

实验现象:

1.下载:D:\青风STM32F0\源代码\实验九:usart串口\user代码进入开发板内。

2.打开串口调试助手,设置串口参数。

3.按下开发板的复位键,此时串口就可以接收到CPU发送的数据信息了,如下图所示:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多