1.串口通信简介:通用异步收发传输器UART(Universal Asynchronous Receiver/Transmitter)是负责处理数据总线和串口之间的串/并通信的设备。UART通信规定了数据帧的格式:起始位、数据位、校验位、停止位等。UART异步通信只需要通信双方设置好数据帧的格式和波特率即可完成通信。因为是异步通信,所以不需要时钟,只需要两根信号线就可以实习数据通信:接受数据RXD、发送数据TXD。
常见的使用了UASR通信协议的接口标准有:RS232、RS485等。
UART是全双工通信:同一时刻两个设备之间可以同时进行发送和接受数据操作。
(补充:单工通信:任何时刻数据只能从一个方向进行通信,一个设备发送,另一个设备接受。
半双工通信:两个设备之间可以收发数据,但是不能在同一个时刻进行,即在同一个时刻,只能一个设备发送,另一个设备接受。)
2.设计思路:本文通过串口中断接受来接受发送到串口的数据。主要步骤是使能串口和引脚的时钟、配置引脚和串口以及中断的信息、写串口中断的回调函数。
配置串口通信,需要了解串口状态寄存器USART_SR和数据寄存器USART_DA。
(1)串口状态寄存器USART_SR:
主要是了解第5位RXNE和第六位TC.
RXNE:为1时,表示数据寄存器中有数据,可以读取数据。为0时表示未接收到数据。当接受到数据时,RXNE由硬件置为1。可以通过对数据寄存器USART_DR执行读操作,将RXNE置为0。或者向此位写入0。
TC:可以通过此位判断数据是否发送完成。可以通过读取USART_SR寄存器,再往USART_DR寄存器写入数据,将TC置为。或者直接往TC位写入0。
(2)串口数据寄存器USART_DR:
如上图所示,USART_DR只有0-8位是有用的。
3.代码:
(1).usart.h:
#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"
#include <stdio.h>
#define RX_LEN 100 //Äܹ»½ÓÊܵÄ×î´ó×Ö½ÚÊý
extern u8 RX_BUF[RX_LEN];
extern int len;
extern u8 RX_FLAG;
void usart_init(int bound);
#endif
(2).usart.c:
#include "USART.h"
int len = 0;
u8 data;
u8 RX_BUF[RX_LEN];
u8 RX_FLAG = 0;
//´®¿Ú³õʼ»¯º¯Êý
void usart_init(int bound)
{
//1.¶¨ÒåÒý½Å¡¢USART¡¢ÖжϽṹÌ壺
GPIO_InitTypeDef GPIO_Initstruct;
USART_InitTypeDef USART_Initstruct;
NVIC_InitTypeDef NVIC_Initstruct;
//2.ʹÄܶ˿ںÍUSARTµÄʱÖÓ£º
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO,ENABLE);
//3.ÅäÖÃÒý½Å£º
//PA9£º
GPIO_Initstruct.GPIO_Pin = GPIO_Pin_9;
GPIO_Initstruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstruct);
//PA10:
GPIO_Initstruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstruct);
//4.ÅäÖÃUSART1:
USART_Initstruct.USART_BaudRate = bound;
USART_Initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Initstruct.USART_Parity = USART_Parity_No;
USART_Initstruct.USART_StopBits = USART_StopBits_1;
USART_Initstruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_Initstruct); //½«Ïà¹ØÊý¾ÝдÈëUSARTµÄ¼Ä´æÆ÷
USART_Cmd(USART1,ENABLE); //ʹÄÜUSART¼Ä´æÆ÷
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //ʹÄܽÓÊÕÖжÏ
//5.ÅäÖÃÖжϣº
NVIC_Initstruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_Initstruct.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_Initstruct);
}
void USART1_IRQHandler(void)
{
//uint16_t x[] = {1,2,3};
//ÅжÏÊÇ·ñ²úÉú´®¿ÚÊý¾Ý½ÓÊÜÖжÏ
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
{
data = USART_ReceiveData(USART1);
RX_BUF[len++] = data;
RX_FLAG = 1;
}
}
//Öض¨Ïòfputcº¯Êý£º
int fputc(int ch,FILE *f)
{
//1.Åжϴ®¿ÚÊÇ·ñ·¢ËÍÍê³É£º
while((USART1->SR & 0x40) == 0);
//2.·¢ËÍÒ»¸ö×Ö½Ú£¬½«Êý¾ÝдÈëµ½¼Ä´æÆ÷£º
USART1->DR = (u8) ch;
return ch;
}
(3).main.c:
#include "stm32f10x.h"
#include "USART.h"
#include <stdio.h>
extern u8 data;
int main(void)
{
int i;
//ÖжÏÓÅÏȼ¶·Ö×飺
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//³õʼ»¯´®¿ÚUSART1:
usart_init(9600);
//char *x = "h";
while(1)
{
if(RX_FLAG)
{
printf("½ÓÊܵ½µÄÊý¾Ý:\r\n");
for(i = 0;i < len;i++)
{
USART_SendData(USART1,RX_BUF[i]);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); //¼ì²éÊÇ·ñ·¢ËÍÍê³É
}
RX_FLAG = 0;
len = 0;
printf("\r\n\r\n");
}
}
}
上图中的注释会出现乱码,将代码复制到keil中就可以正常显示了。
4.运行结果:
5.总结:配置串口通信需要使能引脚、串口时钟,配置rx、tx引脚 ,配置串口寄存器,配置中断。虽然,这些都可以通过STM32提供的库函数完成。但是,我们还是应该是大概的了解一下对应寄存器的功能。比如USART_SR和USART_DR。
使用异步收发传输器UART的通信双方需要设置好数据帧格式、波特率,通过接受数据RXD和发送数据TXD即可完成通信。UART数据通信的方式为全双工。UART具有通信简单,易实习的优点,其缺点是传输速率低、传输距离较短、容易被干扰。
UART与通用同步/异步串行收发器USART(Universal Synchronous/Asynchronous Receiver/Transmitter)的区别在于:UART只有异步通信,而USART有同步和异步通信。
同步和异步最大的区别在于:同步通信中双方需要时钟线进行同步,而异步通信不需要时钟线。