串口通信——UART

丶灬走出姿态 提交于 2020-01-10 04:52:16

一、总体概况
串口:有UART(通用异步收发器,单/半双/全双工),SPI(串行外设接口,半/全双工),I²C(集成电路总线,半双工)3种通信接口,他们都是串口,

并口:有SDIO(4位并行)用来插SD卡;FSMC(16位并行),控制液晶或显存(SRAM)

比特率·:bit/s

波特率:码元/s

一般的:0V-----0 3.3V-----1,很多时候都是按这个来算码元,所以一个码元就是一个比特。
但是 也有时候是好几个比特表示一个码元:0V----00 2V—01
4V—10 6V—11,此时就是俩个比特一个码元

当然,rbt6中,比特率=波特率

二、USART(通用同步异步收发器)
从框图上看,USART总共需要8根引线,而开发板上只有俩条引脚RX和TX

RX:数据接受
TX:数据发送
SCLK:时钟,在保持同步时使用
nRTS:请求发送(前面n的意思是低电平有效)
nCTS:允许发送
其他俩个引脚基本不用
(开发板上是UART,不是USART,因此不能实现同步通信,所以,SCLK、nRTS、nCTS都是不使用的)
在这里插入图片描述
在这里插入图片描述

根据原理图,我们发现,USB转串口(调试串口)CN2接口连接了芯片FT2232D,芯片FT2232D的引脚有RXD2和TXD2,连接到了PA3和PA2上,在开发板上标注着,这俩个GPIO是UART2。
相应的,UART1的RXD1和TXD1连接到了PA10和PA9,而RXD1和TXD1是芯片ST3232ECTR的引脚,这个芯片连接着RS232接口。
我们在连接电脑时,只连接了USB转串口,因此,使用的是UART2,UART2是挂载在APB1,但他的GPIOA引脚是挂载在APB2

三、实现
串口的初始化结构体:
typedef struct
{
uint32_t USART_BaudRate; //波特率

uint16_t USART_WordLength; //数据位长度

uint16_t USART_StopBits; //停止位长度

uint16_t USART_Parity; //校验位模式

uint16_t USART_Mode; //模式 (发送或接收)
uint16_t USART_HardwareFlowControl; //硬件控制流(指是否使用RTS和CTS)

} USART_InitTypeDef;

一般需要使用的函数有:
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);//uart初始化
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);//中断使能函数
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);//串口使能函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);//数据发送函数
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);//数据接受函数

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);//状态位获取函数
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);//中断状态位获取

**编程的步骤:
在这里插入图片描述

为什么需要配置中断?
在发送数据时,肯定不需要,但在接受数据时,如果使用轮询方式,当电脑发送数据过快,而轮询耗时过长,就会使接收数据寄存器数据溢出,丢失数据。必须使得接收数据寄存器一但满了,就立即读取,所以,需要配置中断。

uart.h

#ifndef	 _UART_H
#define  _UART_H
#include "stm32f10x.h"
#include <stdio.h>
void usrt_init(void);
void NVIC_EXIT_Init(void);
void UART_SendData(USART_TypeDef* USARTx, uint8_t Data);
void UART_SendArray(USART_TypeDef* USARTx, uint8_t* Data);
int fgetc(FILE* f);
int fputc(int ch,FILE* f);
#endif

uart.c

#include "uart.h"

void usrt_init()
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	USART_InitTypeDef UART_InitStruct;
//配置uart的GPIO口	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//配置Rx
	GPIO_InitStruct.GPIO_Pin=  GPIO_Pin_3;
	GPIO_InitStruct.GPIO_Mode= GPIO_Mode_IN_FLOATING;
		//这里应该是计算机传什么电平,就是什么电平,所以应该是浮空输入	
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	//配置Tx
	GPIO_InitStruct.GPIO_Pin=  GPIO_Pin_2;
	GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
//配置usrt
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	UART_InitStruct.USART_BaudRate=  115200;
	UART_InitStruct.USART_WordLength=  USART_WordLength_8b;
	UART_InitStruct.USART_StopBits=  USART_StopBits_1;
	UART_InitStruct.USART_Parity=  USART_Parity_No;
	UART_InitStruct.USART_Mode=  USART_Mode_Rx|USART_Mode_Tx;
	UART_InitStruct.USART_HardwareFlowControl=  USART_HardwareFlowControl_None;
	USART_Init(USART2,&UART_InitStruct);
//配置中断的优先级和EXIT
	NVIC_EXIT_Init();
//串口中断使能(使指定的UART中断事件使能)	
	USART_ITConfig(USART2, USART_IT_RXNE,ENABLE);
	//USART_IT_RXNE:接收数据寄存器不为空时,产生中断
//串口使能
	USART_Cmd(USART2,ENABLE);
}
void NVIC_EXIT_Init()
{
	NVIC_InitTypeDef NVIC_InitStruct;
//配置中断优先级	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//初始化结构体	
	NVIC_InitStruct.NVIC_IRQChannel=USART2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority =3;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

 //至此,初始化的工作就完成了,然后就是想要实现的功能
 //在这里,我们要让开发板和计算机进行通信
void UART_SendByte(USART_TypeDef* USARTx, uint8_t Data)//发送一个字节
{
	USART_SendData(USARTx,Data);//发送一个字节
 	while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
}
void UART_SendArray(USART_TypeDef* USARTx, uint8_t* Data)//发送一个数组
{
	int i=0;
	while(Data[i]!=0)
	{
		USART_SendData(USARTx,Data[i]);//发送一个字节
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
		i++;
	}
 
}
//重定义printf和scanf的调用函数,使	printf和scanf可以用来进行计算机和开发板的数据通信
int fputc(int ch,FILE* f) //printf的调用,用来接受开发板的数据
{
	USART_SendData(USART2,ch);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
	return ch;
}





在stm32f10x.c中加入中断服务函数,并在头文件加上函数声明

void USART2_IRQHandler(void)
{
	uint8_t data;
	if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
	{
		data=USART_ReceiveData(USART2);//接受一个字节
		USART_SendData(USART2,data);   //把接受到的字节重新发送给计算机,确定发送成功
	}
}

main.c

#include "stm32f10x.h"
#include "uart.h"
int main()
{
	uint8_t a[10]={1,2,3,4,5,6,7};
	usrt_init();
	
	//UART_SendByte(USART2,0x12);// 传送一个字节

	//UART_SendArray(USART2,a);  //传送一个数组,一个字节一个字节传
	printf("哈哈哈");
	while(1);
}


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!