STM32F103串口1和串口2不同波特率之间交换数据问题


前几天写一个东西,要用到STM32F103的串口1和串口2以不同的波特率交换数据,也就是说串口1波特率为9600,串口2波特率为115200,串口1可以把接收到的数据通过串口2发送出去,串口2也可以把接收到的数据通过串口1发送出去。低波特率向高波特率发送数据没问题,高波特率向低波特率发送数据会丢数据,原因是低波特率的串口还没发送完数据高波特率的串口就又发数据过来了,处理不过来。在同事的在帮助下,写出一个先进先出环形队列(FIFO)程序。接收数据用中断,发送数据用在主函数中查询发送完成标志位。希望对大家有点帮助,可能程序不完美,但程序可以用。定义一个fifo.h部件和一个fifo.c文件。其他的都在主函数中调用。
#ifndef _FIFO_H_
#define _FIFO_H_

#include "stm32f10x.h"

#define FIFO_SIZE 256

typedef struct
{
    uint8_t Buf[FIFO_SIZE];	   //定义缓冲区,大小用FIFO_SIZE定义
    volatile uint32_t Read;	   //定义读取指针
    volatile uint32_t Write;   //定义写入指针
}FIFOTypeDef;

extern FIFOTypeDef USART1_fifo;
extern FIFOTypeDef USART2_fifo;

void PutChar(uint8_t c);
uint8_t GetChar(uint8_t *c);
void PutChar1(uint8_t c);
uint8_t GetChar1(uint8_t *c);

#endif
#include "fifo.h"

FIFOTypeDef USART1_fifo;   //定义串口1的队列fifo
FIFOTypeDef USART2_fifo;   //定义串口2的队列fifo

/*******************************************************************************
* Function Name : PutChar
* Description   : put a fifo value into fifo buffer
* Input         : c
* Output        : None
* Return        : None
*******************************************************************************/
void PutChar(uint8_t c)
{
  USART1_fifo.Buf[USART1_fifo.Write] = c;  //写入数据到缓冲区
  
  if(++USART1_fifo.Write >= FIFO_SIZE)	   //写入指针超出缓冲区最大值,返回最初位置
  {
    USART1_fifo.Write = 0;
  }
}

/*******************************************************************************
* Function Name  : GetChar
* Description    : read fifo value from fifo buffer with timeout feature
* Input          : c
* Output         : None
* Return         : 0 
*******************************************************************************/
uint8_t GetChar(uint8_t *c)
{

  if(USART1_fifo.Read == USART1_fifo.Write)	  //如果没有存入数据,则返回0
  {
    return 0;
  }
  else
  {
    *c = USART1_fifo.Buf[USART1_fifo.Read];	 //读取数据,传入到指针c
    
    if (++USART1_fifo.Read >= FIFO_SIZE)	 //读取指针超出缓冲区最大值,返回最初位置
    {
      USART1_fifo.Read = 0;
    }
	
    return 1;								 //成功读取数据返回1
  }
}

/*******************************************************************************
* Function Name : PutChar
* Description   : put a fifo value into fifo buffer
* Input         : c
* Output        : None
* Return        : None
*******************************************************************************/
void PutChar1(uint8_t c)
{
  USART2_fifo.Buf[USART2_fifo.Write] = c;
  
  if(++USART2_fifo.Write >= FIFO_SIZE)
  {
    USART2_fifo.Write = 0;
  }
}

/*******************************************************************************
* Function Name  : GetChar
* Description    : read fifo value from fifo buffer with timeout feature
* Input          : c
* Output         : None
* Return         : 0 
*******************************************************************************/
uint8_t GetChar1(uint8_t *c)
{

	if(USART2_fifo.Read == USART2_fifo.Write)
	{
	return 0;
	}
	else
  {
    *c = USART2_fifo.Buf[USART2_fifo.Read];
    
    if (++USART2_fifo.Read >= FIFO_SIZE)
    {
      USART2_fifo.Read = 0;
    }
	
    return 1;
  }
}



#include "stm32f10x.h"
#include "fifo.h"

/*******************************************************************************
* Function Name : UIF_Init 
* Description   : 初始化串口
* Input         : USARTx = USART1,2,3 
*               : BPS = 1200, 4800,,,
*               : STB = 1,5,2,15
* Return        : None 
*******************************************************************************/
void UIF_Init(USART_TypeDef* USARTx, uint32_t BPS, uint32_t STB)
{
  	uint32_t Dly;
  	USART_InitTypeDef USART_InitStruct;	 //定义串口结构体
	
	NVIC_InitTypeDef NVIC_InitStructure; //定义中断结构体

  
	USART_ClearFlag(USARTx, USART_FLAG_TC);
	USART_DeInit(USARTx);              //复位串口x
	
	USART_InitStruct.USART_BaudRate = BPS;
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;  //8位字节长度数据
	if(STB == 1)
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	else if(STB == 5)
	USART_InitStruct.USART_StopBits = USART_StopBits_0_5;
	else if(STB == 15)
	USART_InitStruct.USART_StopBits = USART_StopBits_1_5;
	else
	USART_InitStruct.USART_StopBits = USART_StopBits_2;
	USART_InitStruct.USART_Parity = USART_Parity_No;         //无奇偶检验位
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收 发送模式
	USART_Init(USARTx, &USART_InitStruct);   //初始化串口x
	

	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口1中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级2级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级2级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
 		
	if(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==SET)
    USART_ClearFlag(USARTx, USART_FLAG_TC);
	USART_Cmd(USARTx, ENABLE);          //使能串口x
	for(Dly = 0; Dly < 0xFFFF; Dly++);
	USART_ClearFlag(USARTx, USART_FLAG_TC); 
	
	USART_ITConfig(USARTx,USART_IT_RXNE,ENABLE);   //开启接收中断
									 
}

/*******************************************************************************
* Function Name : GPIO_Config 
* Description   : 初始化IO
* Input         : None 
* Return        : None 
*******************************************************************************/
void GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
                       | RCC_APB2Periph_GPIOB
                       | RCC_APB2Periph_AFIO
                       | RCC_APB2Periph_USART1, ENABLE);
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 

  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //USART1_TX Output 
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //USART1_RX Input  
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; //USART2_TX Output   
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; //USART2_RX Input    
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStruct);
   
}
/*******************************************************************************
* Function Name : NVIC_Configuration 
* Description   : 设置NVIC中断分组
* Input         : None 
* Return        : None 
*******************************************************************************/
void NVIC_Configuration(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}
/*******************************************************************************
* Function Name : USART_SendByte 
* Description   : 发送一个字节
* Input         : USARTx = USART1,2,3 
 				  Data = 要发送的数据
* Return        : None 
*******************************************************************************/
void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)
{
	USARTx->DR = (Data & (uint16_t)0x01FF);;
	while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) != SET);
}
/*******************************************************************************
* Function Name : main 
* Description   : 主函数
* Input         : None
* Return        : None 
*******************************************************************************/
int main(void)
{
		uint8_t byte;
		GPIO_Config();
		NVIC_Configuration();
		UIF_Init(USART1,115200,1);	 //串口1波特率115200,1位停止位
		UIF_Init(USART2,9600,1);	 //串口2波特主9600,1位停止位																									//使能串口
		while(1)
		{
 
			if(USART1_fifo.Write != USART1_fifo.Read) //如果读取指针不等于写入指针,说明缓冲区有数据
			{
				if(GetChar(&byte))		//如果读取数据成功,返回1
				{
					USART_SendByte(USART2,byte);	//把串口1的缓冲区数据通过串口2发送出去
				}
			}
			if(USART2_fifo.Read!=USART2_fifo.Write)  //如果读取指针不等于写入指针,说明缓冲区有数据
			{
				if(GetChar1(&byte))   //如果读取数据成功,返回1
				{		
			   		USART_SendByte(USART1,byte); //把串口2的缓冲区数据通过串口1发送出去
			   	}
			} 
		}
}

/*******************************************************************************
* Function Name : USART1_IRQHandler 
* Description   : 串口1中断服务程序
* Input         : None
* Return        : None 
*******************************************************************************/
void USART1_IRQHandler(void)
{	
	u8 res; 
 	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //如果接收到数据
	{
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清空接收标志
	 	res = USART_ReceiveData(USART1);
		PutChar(res);	  //压入数据到串口1缓冲区
	}

	//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
	if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)
	{
		USART_ClearFlag(USART1,USART_FLAG_ORE); //读SR其实就是清除标志
		USART_ReceiveData(USART1);    //读DR
	}
}
/*******************************************************************************
* Function Name : USART2_IRQHandler 
* Description   : 串口2中断服务程序
* Input         : None
* Return        : None 
*******************************************************************************/
void USART2_IRQHandler(void)        
{
	u8 Res;

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断
	{
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清空接收标志
		Res =USART_ReceiveData(USART2);//(USART2->DR);	//读取接收到的数据
		PutChar1(Res);	     //压入数据到串口2缓冲区
    }

	//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题
	if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET)
	{
		USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR其实就是清除标志
		USART_ReceiveData(USART2);    //读DR
	}
} 






  • 11
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32F103串口1和串口2可以直接连在一起进行通信。对于串口1,我们需要进行配置以确保其工作在正确的波特率数据位、停止位和校验位。同样,对于串口2也需要进行相同的配置。接下来,我们需要编写代码来实现串口1和串口2之间数据传输。 首先,在代码中需要初始化串口1和串口2,分别设置它们的通信参数。然后,我们可以使用STM32F103提供的串口传输函数,比如HAL_UART_Transmit()和HAL_UART_Receive()来实现数据的发送和接收。 在发送数据时,我们需要将要传输的数据存储在一个缓冲区中,并调用HAL_UART_Transmit()函数将数据发送到串口1。然后,通过串口线将数据发送到串口2。接收数据时,我们可以使用HAL_UART_Receive()函数从串口1接收数据,然后通过串口线将数据传输到串口2。 在代码中,我们还可以使用中断机制来实现串口的接收和发送。通过配置中断优先级和中断处理函数,当有数据到达时,中断处理函数将被触发,并处理接收到的数据。同样,当需要发送数据时,我们可以通过调用中断处理函数来触发数据的发送。 总的来说,通过直接连接串口1和串口2,我们可以在STM32F103上实现串口之间的简单通信。通过正确配置和编写代码,能够实现数据的发送和接收,从而实现数据的传输。 ### 回答2: 当STM32F103串口1直连串口2时,可以实现串口之间数据传输和通信。STM32F103串口功能十分强大,可以作为数据的输入和输出端口,在嵌入式系统中应用广泛。 串口1和串口2之间数据传输需要进行一系列设置和配置。首先,需要配置串口1和串口2的波特率数据位、停止位和校验位,使得两个串口之间的通信参数一致。其次,需要设置串口1和串口2的工作模式,例如全双工模式或半双工模式。然后,通过STM32F103的硬件和寄存器操作,可以将数据串口1发送到串口2,或者从串口2发送到串口1。通过串口的中断机制,可以实现数据的异步传输和接收。 在串口1直连串口2的应用中,可以通过发送和接收数据来实现设备之间的通信。例如,可以通过串口1将传感器的数据发送到串口2,然后由串口2将数据传输到另外一个设备或者计算机上进行处理。另外,也可以通过串口1接收来自串口2的数据,然后进行相应的处理和应答。 总的来说,将STM32F103串口1直连串口2可以实现设备之间数据传输和通信,方便了嵌入式系统的开发和应用。 ### 回答3: 当STM32F103串口1直接连接串口2时,可以实现串口之间数据传输和通信。 首先,需要配置STM32F103串口1和串口2。可以使用STM32F103的库函数来进行配置,包括设置波特率数据位、校验位和停止位等参数。同时,还需要开启串口1和串口2的中断使能,以便能够进行数据的发送和接收。 然后,在主程序中,我们可以通过调用库函数来发送和接收数据。对于串口1,我们可以使用UART_SendData函数将要发送的数据放入发送缓冲区,并通过使能发送中断来触发数据的发送。对于串口2,我们可以使用UART_ReceiveData函数来接收串口1发送的数据,并将接收到的数据存储在接收缓冲区中。同时,也可以通过使能接收中断来实现数据的接收。 在串口1和串口2之间进行数据的发送和接收时,需要注意以下几点: 1. 在发送数据时,需要确保发送缓冲区为空,以免发生数据丢失。 2. 在接收数据时,需要及时读取接收缓冲区中的数据,以免导致接收缓冲区溢出。 3. 在进行数据传输时,可以通过使用互斥信号量等机制,实现对串口的访问控制,避免数据的冲突和混乱。 通过将STM32F103串口1直接连接到串口2,可以方便地实现两个串口之间数据传输和通信。这在许多嵌入式系统和通信场景中都是非常常见和实用的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值