STM32两个串口同时工作,一个串口发,另一个串口收。

STM32两个串口同时工作,一个串口发,另一个串口收。

STM32双串口同时工作

由于最近一个国创项目的需要,所以使用STM32两个串口来同时工作。STM32F1一共有5个串口,因为实际电路的原因我这里使用的是串口一与串口三,其中串口三用来接收,串口一用来发送。

两个串口的电路结构

废话少说,直接上原理图。
串口一的引脚
串口三的引脚
由上面两部分原理图可知:串口一的引脚TX为PA9,RX为PA10;串口三的引脚TX为PB10,RX为PB11。
按照以上描述,将串口一与串口三都连接上电脑。

代码

usart.c

#include "sys.h"
#include "usart.h"	  

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif
 
#if EN_USART3_RX   //如果使能了接收
//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart1_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 

}

void uart3_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能USART3,GPIOB时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	//USART3_TX   GPIOB.10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10
   
  //USART3_RX	  GPIOB.11初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PA3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11  

  //Usart3 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级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(USART3, &USART_InitStructure); //初始化串口3
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART3, ENABLE);                    //使能串口3

}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
}
	
void USART3_IRQHandler(void)                	//串口3中断服务程序
	{
	u8 Res;
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART3);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
}
#endif	

usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" 

#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART3_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart1_init(u32 bound);
void uart3_init(u32 bound);

void USART1_IRQHandler(void);
void USART3_IRQHandler(void); 



#endif

mian.c

#include "delay.h"
#include "sys.h"
#include "usart.h"



int main(void)
{
	u8 t,len;
	u16 times=0;
	delay_init(); //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设 置 NVIC 中 断 分 组 2
	uart1_init(9600); //串口初始化波特率为 115200
	uart3_init(9600);
	printf("\r\n111111\r\n\r\n");
	while(1)
	{
		if(USART_RX_STA&0x8000)
		{ 
			//printf("\r\n1\r\n\r\n");
			//USART_SendData(USART3, Txdata[1]);
			len=(USART_RX_STA&0x3f)+1; //得到此次接收到的数据长度
		  //printf("\r\n 您发送的消息为:\r\n\r\n");
		  for(t=0;t<len;t++)
		  { 
				USART_SendData(USART1, USART_RX_BUF[t-1]); //向串口 1 发送数据
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
				//等待发送结束
			}
			if(t==USART_REC_LEN) t=0;
			printf("\r\n\r\n"); //插入换行
			USART_RX_STA=0;
			times++;
			if(times++ ==10)
			{
				times =0;
				LED0=!LED0; //闪烁 LED,提示系统正在运行.
			}
			delay_ms(10);
		  }
   }
}

实现效果

串口三连接com3接收信息
com3连接串口三,负责将信息从电脑传送给STM32。
STM32将串口三接收到的信息通过串口一发送出去
com4连接串口一,负责接收STM32从串口1发送过来的信息。
至此实验结束,如有错误,请大家指出。

  • 50
    点赞
  • 331
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
### 回答1: STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,具有丰富的外设资源,其中包括多个串口模块。在使用STM32F103C8T6实现串口通信时,可以通过一个串口模块送数据,另一个串口模块接数据。 首先,需要配置串口模块的相关寄存器。例如,设置串口模块的波特率、数据位数、停止位等参数。然后,将要送的数据存放在相应的送缓冲区中,通过设置送寄存器,将数据送出去。送完成后,可以通过查询或中断方式判断是否送成功。 接下来,需要配置接串口模块的相关寄存器。例如,设置接串口模块的波特率、数据位数、停止位等参数。然后,通过查询或中断方式监测接缓冲区是否有数据可读,若接缓冲区中有数据,则可以通过读取接寄存器获取接到的数据。 在串口通信过程中,需要保持送和接串口模块的参数一致,否则可能无法正常通信。此外,还需注意适当设置送和接的数据缓冲区大小,以免数据溢出或丢失。 值得注意的是,STM32F103C8T6具有多个串口模块,因此可以同时进行多个串口送和接,具体的实现方法和代码可参考相关的开文档和例程。 ### 回答2: STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器。它广泛用于各种嵌入式应用场景,具有较低的功耗和良好的性能。 串口是一种常见的数据通信方式,可以通过其中一个串口送数据,另一个串口数据。以下是如何实现STM32F103C8T6串口送和接的简要步骤: 1. 配置串口:首先,我们需要配置串口和接串口的相关寄存器。这包括设置波特率、数据位数、校验位和停止位等参数。 2. 送数据:通过写入串口的数据寄存器,我们可以将要送的数据放入缓冲区。 3. 等待送完成:如果送缓冲区空闲,我们需要等待数据送完成。可以通过查询送完成标志位来判断。 4. 接数据:读取接串口的数据寄存器,可以获取接到的数据。 5. 处理接数据:根据需求,可以对接到的数据进行处理,例如解码、校验和存储等操作。 6. 循环操作:如果还有待送的数据或者需要继续接数据,可以将上述操作放入一个循环中,以实现连续的数据送和接。 注意事项: 1. 确保送和接串口的引脚正确连接到外部设备。 2. 根据具体的开板和芯片型号,参考相关的技术手册和文档,了解寄存器的地址和配置方法。 3. 为了保证数据的可靠性,可以添加适当的校验机制,例如奇偶校验或CRC校验等。 总结:通过配置串口并进行数据的送和接,我们可以实现STM32F103C8T6的串口通信功能,从而在嵌入式应用中实现数据的传输和交互。 ### 回答3: STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器。它拥有多个通用输入输出引脚(GPIO),支持串口通信功能。 要实现一个串口送数据给另一串口数据的功能,我们需要完成以下步骤: 1. 配置串口:首先,我们需要初始化串口的引脚和寄存器。通过对相关寄存器的编程,设置波特率、数据位数、校验位、停止位等通信参数。我们也可以选择使能硬件流控制,以防止数据的丢失。 2. 配置接串口:同样地,我们需要初始化接串口的引脚和寄存器。与串口类似,通过设置寄存器的值来配置通信参数。 3. 送数据:使用串口送寄存器,将要送的数据写入其中。我们可以通过查询或中断方式进行送。 4. 接数据:在接端,我们通过查询或中断方式,使用接串口的接寄存器读取接到的数据。可以在接到完整的数据帧后进行处理。 需要注意的是,要保证送和接两个串口之间的通信正常,它们在物理层上需要使用相同的波特率,即每秒钟传输的比特数。还要确保接端使用正确的通信参数来解析接到的数据。 通过以上步骤,我们可以实现STM32F103C8T6上的一个串口送数据给另一个串口数据的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值