ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

串口通信之————USART

2022-01-04 20:02:30  阅读:216  来源: 互联网

标签:USART Receive 通信 ReceiveString InitStructure 串口 GPIO


B站账号:小光学嵌入式


  • ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大二学生。
  • ⏩最近开始系统性补习STM32基础知识,规划有:串口通信,Github,Ucos等等。
  • ⏩今天总结一下串口通信之stm32-USART。

USART

一.原理讲解

请跳转->串口通信————UART、I2C、SPI详解(总结篇

二.USART和UART的区别

UART:universal asynchronous receiver and transmitter通用异步收/发器

USART:universal synchronous asynchronous receiver and transmitter通用同步/异步收/发器
大家能看出来USART和UART相比较,可以实现同步,就是说USART相对UART的区别之一就是能提供主动时钟

三.具体固件库实现

1.USART初始化

在这里插入图片描述
根据USART的外设配置,我们可以得知,全双工模式,发送端设置为复用推挽输出,接收端设置为浮空输入或上拉输入。
初始化步骤:

  1. 使能USART使用引脚时钟
    使能串口使用所在引脚
  2. GPIO初始化
    初始化串口所在IO
  3. 接收中断初始化
    设置中断优先级和通道
  4. 初始化USART
    初始化USART,波特率、数据格式、奇偶校验位、收发模式等等。
  5. 开启中断
    USART_ITConfig();//开启串口接受中断
  6. 使能串口
    USART_Cmd();
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

2.串口收发数据

串口发送一般不会用到中断发送,接收会用到中断接收,因为串口通信在没有用到主动时钟的时候,他是异步通信的。
我们先认识一下固件库中的这几个函数:

void USART_SendData();//发送数据到串口,DR
uint_16_t USART_ReceiveData();//接收数据,从DR读取接收到的数据

FlagStatus USART_GetFlagStatus();//获取状态标志位
void USART_ClearFlag();//清除状态标志位
ITStatus USART_GetITStatus();//获取中断状态标志位
void USART_ClearITPendingBit();//清除中断状态标志位

我们通过上面这些函数就可以完成一次成功的数据发送与接收。
下面是一个例子,完成了两个STM32之间的传输数据:

1.主机发送

发送时我们封装一个函数:
步骤:

  1. USART_ClearFlag()清除标志位
  2. USART_SendData()每次发送一个字符
  3. USART_GetFlagStatus()等待发送完成
  4. USART_ClearFlag()清楚标志位,然后继续发送知道截至标志
//串口发送字符串
void USART_SendString(USART_TypeDef* USARTx, char *DataString)
{
	int i = 0;
	USART_ClearFlag(USARTx,USART_FLAG_TC);										//发送字符前清空标志位(否则缺失字符串的第一个字符)
	while(DataString[i] != '\0')												//字符串结束符
	{
		USART_SendData(USARTx,DataString[i]);									//每次发送字符串的一个字符
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == 0);					//等待数据发送成功
		USART_ClearFlag(USARTx,USART_FLAG_TC);									//发送字符后清空标志位
		i++;
	}
}

2.从机接收数据

在接收的时候,我们使用中断接收,所以我们就要编写中断服务函数:void USARTx_IRQHandler(void)这个名字一定不能变。
接收数据步骤:

  1. USART_GetITStatus()判断是否有数据
  2. USART_ReceiveData()读取寄存器中的数据,存放到我们定义的USART_ReceiveString
  3. if(USART_ReceiveString[Receive_sum-2] == '\r' && USART_ReceiveString[Receive_sum-1] == '\n' )回车换行作为结束标志位,当接收完成后根据接收到的数据USART_ReceiveString直接执行相应的操作。
char USART_ReceiveString[20];													//接收PC端发送过来的字符
int Receive_Flag = 0;															//接收消息标志位
int Receive_sum = 0;															//数组下标
void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == 1)							//USART_FLAG_RXNE判断数据,== 1则有数据
	{
		if(Receive_sum > 49)													//数组能存放50个字节的数据				
		{
			USART_ReceiveString[49] = '\0';										//数据字节超过50位时,将最后一位设置为\0	
			Receive_Flag = 1;													//接收标志位置1,停止接收数据
			Receive_sum = 0;													//数组下标置0
		}
		
		if(Receive_Flag == 0)													//接收标志位等于0,开始接收数据
		{
			USART_ReceiveString[Receive_sum] = USART_ReceiveData(USART1);		//通过USART1串口接收字符
			Receive_sum++;														//数组下标++
		}
		
		if(Receive_sum >= 2)													//数组下标大于2
		{
			if(USART_ReceiveString[Receive_sum-2] == '\r' && USART_ReceiveString[Receive_sum-1] == '\n' )
			{
				USART_ReceiveString[Receive_sum-1] = '\0';						
				USART_ReceiveString[Receive_sum-2] = '\0';
				Receive_Flag = 1;												//接收标志位置1,停止接收数据
				Receive_sum = 0;												//数组下标置0
					

				if(strcmp(USART_ReceiveString,"hello") == 0)
				{
					LED0 = !LED0;
				}
				if(strcmp(USART_ReceiveString,"world") == 0)
				{
					LED1 = !LED1;
				}
			}		
		}
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);							//接收后先清空标志位
	}
}

我们可以通过调整Receive_Flag的值来让它开始或者停止接收。
我用这个做了实验,完成了简单的两个板子之间的通信。

总结

今天复习了串口通信中的USART,把之前串口接收中断没有搞懂的搞懂了,之后还有SPI和I2C通信。都会用代码实现并且实验它。
继续加油!!!

标签:USART,Receive,通信,ReceiveString,InitStructure,串口,GPIO
来源: https://blog.csdn.net/qq_52608074/article/details/122309026

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有