天天看点

stm32串口解析1:什么是串口2:数据传输3:资源介绍4:传输协议介绍

1:什么是串口

UART : Universal Asynchronous Receiver/Transmitter 通用异步收发器

USART : Universal Synchronous Asynchronous Receiver/Transmitter 通用同步/异步收发器

串口简单来说就是一种简单的数据传输协议,其数据的传输只需要两根线即可

2:数据传输

有串口及必定有并口,并口是指把一个数据一次性传输到其他设备,速度快,效率高,但其传输的距离短,成本高故在远距离的传输中并不常用。

串口是指在数据传输过程中把数据一位一位的传输到其他设备,其传输距离远,但其传输的速率较慢,但是用于大多数设备。

3:资源介绍

stm32串口解析1:什么是串口2:数据传输3:资源介绍4:传输协议介绍

在f4系列中具有6个串口,可以独立进行收发

4:传输协议介绍

1:硬件连接方式

将两个设备的TX,RD 端口交叉相连即可

Tx: 发送数据线

Rx: 接收数据线

stm32串口解析1:什么是串口2:数据传输3:资源介绍4:传输协议介绍

2:工作模式介绍

全双工: 两个设备可以同时发送和接收

半双工: 在同一瞬间只能接受或者发送

弹弓模式: 两个设备之间只能接受或者只能发送

串行数据: 发送只一根线,一次只能发送一bit. 一bit接着一bit发送和接收。

模块通信: 上位机 下位机

通信一般需要两个设备,我们把这两个设备,人为叫做上位机, 下位机。

上位机: 把处理性能强的机子,上位机。数据大部分处理都在上位机完成。

下位机: 把数据采集的终端,处理性能单一的机子,下位机。

3:数据传输模式

1:异步通信:不要求两个设备的时钟一致,易于实现但每个字符要附加2·3个位用于校验位,停止位等等

UART protocol 串口协议。

串口发送和接收数据是以帧为单位. Frame

1帧(Frame)= 1 start bit(起始位) + 5-9bits数据位 + 0/1bit 校验位  + stop bits(0.5, 1,1,5,2)

起始位: 一个周期的低电平

数据位: 5-9bits数据位,具体是多少bits,需要双方协商。并且传送是先传送LSB(最低位) … MSB

校验位:

0 bit :没有校验位

1 bit :校验位. “赖子” X

D0 D1 D2 … Dn X

奇校验:要保证传输的1为奇数

偶校验:要保存传输的1为偶数

停止位: 高电平

0.5 个停止位。 半个周期的高电平

1 个停止位

1.5 个停止位

2 个停止位

2:同步通信

要建立发送方的时钟对接收方的时钟严格控制,是数据的传输完全同步,是由多个字符组成的字符串为传输单位来进行数据传送

特点:传输效率高

4:数据传输

1:在串口数据的收发中有一个十分重要的值 波特率,这是保证两个设备之间能狗正常通信的必不可少的数据

Baudrate(波特率): 传输速率。

决定 时间周期。

2:串口的物理层标准

物理层标准  the physical layer standards

TTL level UART : TTL电平串口

RS-232:

RS-422:

RS-485:

TTL level UART:

逻辑低电平(0) 0V

逻辑高电平(1) 5V/3.3V

RS-232: 适合较长距离传输

逻辑低电平(0) +3v~+15V

逻辑高电平(1) -3v~-15v

TTL UART RS-232 RS-422 RS-485

电平 1 3.3V/5V 1 -5V ~ -15V +/- 2v +/- 1.5v

0 0V 0 5V ~ +15V

信号 单端信号   单端信号  差分信号   差分信号

传输长度 < 2m <15m <1200m <1200m

不同标准的串口,引脚也不一样。TX/Rx是一定存在的。

TTL

RX

TX

GND

VCC

代码讲解

在stm32f4串口配置时我们不光要配置其对应的I/O口位复用模式,还需要将其与串口连接起来,然后配置串口传输的相关参数

typedef struct
{
  uint32_t USART_BaudRate;          //波特率设定,寄存器BRR

  uint16_t USART_WordLength;         //字长,CR1寄存器 M位

  uint16_t USART_StopBits;            //停止位 ,CR2寄存器 STOP位

  uint16_t USART_Parity;              //校验控制位,CR1寄存器 PCE,PS位
 
  uint16_t USART_Mode;   //模式选择,CR1寄存器 TE,RE(收数据使能,Receive Enable)位

  uint16_t USART_HardwareFlowControl;//硬件流选择,CR3寄存器 CTSE,RTSE位
} USART_InitTypeDef;
           

这个是串口配置时相对应的结构体

STM32F4xx串口代码流程

(1) GPIO口配置

串口的TX/RX 引脚是由GPIO口来复用的。

a. 使能GPIO分组的时钟与串口分组的时钟

RCC_AHB1PeriphClockCmd

b. 配置GPIO口的功能 GPIO_Init

c. 选择具体的复用功能

GPIO_PinAFConfig

(2) usart配置

a:配置串口传输时的相关配置如波特率,数据位等

b. USART_Init

3) 中断的配置

USART_ITConfig <- 配置串品的中断

在STM32中一个USART只对应一个中断通道,但是引起串口中断的

事件有很多,比如:

TXE -> 发送寄存器为空,可以引起串口中断

TC -> 发送完成,可以引起串口中断

RXNE -> 接收寄存器不为空,可以引起串口中断

USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
 	USART_ITConfig就是用来把一个串口的XX事件,配置成是否引起串口中断的 		
 	在串口中断函数里面,就需要判断是哪个串口事件,引起了中断!!! 		
 	NVIC_Init()
           

(4) 使能串口

USART_Cmd

//串口中断
USART1_IRQHanlder()
 	{
 		if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
 		{
 			//有数据可读啦
 			
 			data = USART_ReceiveData(USART1);  //读取接收到的数据
 		}
 		//清除USART1的中断标志
 		USART_GetITStatus
 	}
 USART_GetITStatus用来获取串口的xx事件标志位
           

发送数据

USART_SendData(USART1, 0x55);
 while (USART_GetFlagStatus(USRAT1, USART_FLAG_TXE)  == RESET); //等待发送结束 
           

代码汇总

#include"stm32f4xx.h"
#include"sys.h"
#include<stdio.h>
static GPIO_InitTypeDef 		GPIO_InitStructure;
static NVIC_InitTypeDef 		NVIC_InitStructure;
static USART_InitTypeDef 		USART_InitStructure;
//标准延时函数
void delay_ms(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; 				// Disable SysTick,关闭系统定时器
		SysTick->LOAD = (168000)-1; 	// 配置计数值(168000)-1 ~ 0
		SysTick->VAL  = 0; 		// Clear current value as well as count flag
		SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; 		// Disable SysTick	

}
void usart1_init(uint32_t baud)
{
	//端口A硬件是能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	//串口硬件是能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	//PF9应交连接到串口
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	//配置串口
	USART_InitStructure.USART_BaudRate = baud;//波特率
    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_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	USART_ClearITPendingBit(USART1,USART_IT_RXNE);	
	//配置终端优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//使能串口工作
	USART_Cmd(USART1, ENABLE);
}

struct __FILE{int handle;};
FILE __stdout;
FILE __stdin;

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	return ch;
}
//printf函数重定向,可以用printf发送数据
int fgetc(FILE *f)
{
		/* 等待串口输入数据 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}
int main(void)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOF,&GPIO_InitStructure);
	PFout(9)=1;
	usart1_init(115200);
	printf("sdfrr\r\n");
	while(1)
	{
	}
	
}

void USART1_IRQHandler(void)
{
	uint8_t temp;
	//判断标志位i
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET)
	{
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
		temp=USART_ReceiveData(USART1);
		USART_SendData(USART1,'G');
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
		
	}
		
		
}