STM32F103 串口通信

串口通信

串口通信是嵌入式里非常常见的通信,不论是STM32还是其它的什么单片机或者任何其它支持串口通信的设备通信时只需要把通信一方的RX与通信另一方的TX,以及一方的TX与另一方的RX相连接就可以进行双向通信。

在串口通信里,接好线并配置好串口的初始化之后就可以直接发送数据了,但是为了通信的可靠传输,通信双方往往会采用约定好的通信协议,这个协议可以自定义,也可以直接套用一些经过实践检验的、广为使用的通信协议,比如工业里常用的modbus协议、RS232协议…

本文里就不用那么麻烦了,主要以介绍原理和应用为主。

通信方式

串口通信按照通信模式可以分为:
全双工通信和半双工通信,简单来说就是全双工通信模式的通信双方可以同时收发数据,就好比两个人交流的时候同时说话,同时听到对方的信息;而半双工通信模式就是通信的时候只能有一方发送数据另一方只能就收数据,就好比两个人在交流的时候,一个人在说话的时候另一个人只能听对方说话。

根据时钟信号的不同又可以分为同步通信和异步通信:

  • 在同步串口通信中,数据传输是通过时钟信号进行同步的。发送和接收设备必须使用相同的时钟信号来确保数据的同步传输。这种模式通常用于高速数据传输,因为同步传输可以更有效地利用通信介质的带宽。
  • 在异步串口通信中,数据传输是以固定的数据帧格式进行的,而不需要时钟信号进行同步。每个数据帧通常包括起始位、数据位、校验位和停止位。由于不需要时钟信号进行同步,因此异步串口通信更为简单,适用于较低速的数据传输和对时序要求不太严格的场景。

不过同步通信的用途不多,大多用的还是异步通信。
在我们的STM32F103里,串口1、2、3都支持同步和异步两种通信方式,而串口4、5只支持异步通信方式。
STM32F103 串口通信_第1张图片

波特率

串口通信的双方需要约定好每秒传输数据的数量,一般用bit/s作为单位
比如波特率为9600,表示每秒钟传输9600个bit。
8bit = 1byte = 1B
也就是说9600的波特率数据传输速度为 1200byte/s,也就是大约1.17KB/s。

停止位、数据位、校验位

在串口通信中,数据被组织成帧(frame),每一帧包括数据位(data bits)、停止位(stop bit)和校验位(parity bit)。这些位的组合形成了每个数据帧的结构,以便发送和接收设备能够正确地解释和处理数据。

  • 数据位(Data bits):数据位指定了每个数据字节中包含的位数。通常,数据位的取值为5、6、7或8位,表示每个数据字节包含的位数。常见的配置是使用8位数据位,因为它提供了较大的数据范围和更好的兼容性。

  • 停止位(Stop bit):停止位用于指示一个数据帧的结束。通常情况下,串口通信使用1或2个停止位。在实际应用中,通常使用1个停止位,因为它足以表示数据帧的结束,并且可以节省传输时间。

  • 校验位(Parity bit):校验位是用于检测数据传输中出现的错误的一种机制。校验位可以是奇校验、偶校验、标记校验或空(无校验)。在奇校验中,校验位被设置为确保数据位中的1的总数(包括校验位)为奇数;在偶校验中,校验位被设置为确保数据位中的1的总数为偶数。标记校验将校验位设置为常数1,空校验表示没有校验位。校验位的目的是在传输过程中检测数据传输中的错误。不过人们在进行串口通信的时候打多会使用一些协议来校验通信,所以一般在用的时候大多数人会把这个位设置为None。

STM32F103的串口使用

配置步骤
  • 打开相关时钟
  • 初始化引脚
  • 配置串口通信方式
  • 分配中断
  • 使能相关中断和串口
代码

以串口2为例

void usart2_init(void)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
  	NVIC_InitTypeDef NVIC_InitStructure;

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);   
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    

  	//USART2_TX   GPIOA.2
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  	GPIO_Init(GPIOA, &GPIO_InitStructure);

  	//USART2_RX	  GPIOA.3
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// NVIC中断配置
  	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          
  	NVIC_Init(&NVIC_InitStructure);    

	// 配置串口通信方式
  	USART_InitStructure.USART_BaudRate = 115200; // 波特率 115200
  	USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 八位数据位
  	USART_InitStructure.USART_StopBits = USART_StopBits_1; // 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(USART2, &USART_InitStructure); 
  	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
  	USART_Cmd(USART2, ENABLE);                    
}

其中 PA.2作为TX引脚的功能是发送数据,所以配置为复用推挽输出模式,RX引脚功能即PA.3作为RX引脚的功能是接收数据,所以配置位浮空输入模式。

串口通信控制LED灯的亮灭,同时STM32向对方发送信息
/*发送字节*/
void Usart_SendByte(USART_TypeDef * USARTx, uint16_t ch)
{
	USART_SendData(USARTx,ch);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	
}


/*发送字符串*/
void USART_SendString(USART_TypeDef * USARTx, char *str,u8 length)
{
	unsigned int   k=0;
	while(k<length)
	{
		Usart_SendByte(USARTx, *(str+k));
		while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
		k++;
	}
	while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);   
}

int main(void)
{
	delay_init();
	LED_Init();
	usart2_init();
	while (1)
	{
		USART_SendString(USART2,"你好\r\n",6);
		delay_ms(1000);
	}
}

void USART2_IRQHandler(void)                 
{
  if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) 
  {
		u16 res=USART_ReceiveData(USART2);
		if(res == 'o')
		{
			LED_Set(LED_ON);
		}
		else if(res == 's')
		{
			LED_Set(LED_OFF);
		}
  }
}

视频效果

STM32串口

你可能感兴趣的:(stm32,嵌入式硬件,单片机)