当stm32的串口1被使用时,我们可以使用其他串口来使用。
步骤:
首先,我们要将串口3初始化并加上中断:
/**********************************************************************************
*函数名 :USART3_Config
*函数功能 :USART3初始化
*输入 :无
*输出 :无
*******************************************************************************/
void USART3_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO初始化结构体声明
USART_InitTypeDef USART_InitStructure; //串口初始化结构体声明
NVIC_InitTypeDef NVIC_InitStructure; //NVIC初始化结构体声明
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能PB端口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //USART3时钟
//USART3的Tx---GPIO----PA.10----复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//USART3的Rx---GPIO----PA.11----浮空输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //中断通道为USART3_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //设置抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //设置响应优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能
NVIC_Init(&NVIC_InitStructure); //调用NVIC_Init()函数完成端口初始化
USART_InitStructure.USART_BaudRate=9600; //设置波特率为9600
USART_InitStructure.USART_WordLength=USART_WordLength_8b; //数据位8位
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(USART3,&USART_InitStructure); //调用USART_Init()函数完成端口初始化
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //使能接收中断
USART_Cmd(USART3,ENABLE); //使能串口3
}
注意:
上面程序中使能时钟函数要分开,毕竟RCC_APB2Periph_GPIOB与RCC_APB1Periph_USART3是不一样的,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能PB端口时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //USART3时钟
而在串口1使能时钟时,却可以放在一起,比如:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
//使能PA端口时钟、USART1时钟
这个一定要注意,不然程序编译是检测不出的。
接下来,我们就要码串口中断函数了
下面的函数是接收到数据(一个字节),并判断帧头(0xFF)是否正确,再存放在数组data(十六进制)中,继续接收数据(一个字节)存放在数组data中,接收满四个字节就结束,重新循环判断。其中COM3_RecvFin 是接收一帧数据成功的标志,主函数可以用这个来检验是否接收成功,再进行数据处理。
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 shujv;
if(USART_GetFlagStatus(USART3,USART_IT_RXNE) != RESET) //接收到数据
{
shujv=USART_ReceiveData(USART3);
if((shujv == 0xFF) && (h == 0)){h=1; data[0]=shujv; }
else if(h == 1){h=2; data[1]=shujv; }
else if(h == 2){h=3; data[2]=shujv; }
else if(h == 3){ COM3_RecvFin = 1; h=0;data[3]=shujv; }
else h=0;
USART_ClearITPendingBit(USART3,USART_IT_RXNE); //清除接收标志位,每次接收完成都需要清除一下
while(USART_GetFlagStatus(USART3,USART_FLAG_TC) ==RESET); //用于检查串口UART1是否发送完成,完成时,TC中断标志置位,退出轮询等待!
}
}
上面的方法是接收到固定长度的数据,当我们不知道数据有多长,只有帧头0xFF、帧尾0xEE,应该怎么办呢?下面就是另一种方法:
如果检测数据的帧头是0xFF,就将Start_Receiving置1,到后面判断Start_Receiving,再将数据存在数组data中;检测到数据的帧尾是0xEE时就结束并将COM3_RecvFin置1。
这种方法虽然可以接收不定长度的数据,但是我们的数据(不包括帧头、帧尾)出现0xEE时,数据接收就会提前结束。
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET);//接收到数据
{
shujv = USART_ReceiveData(USART3);
if(shujv==0xFF)
{
Start_Receiving=1;
}
else if(shujv == 0xEE)
{
COM3_RecvFin=1;
Start_Receiving=0;
i=0;
}
if(Start_Receiving==1)
{
data[i]=shujv;
i++;
}
USART_ClearITPendingBit(USART3,USART_IT_RXNE); //清除接收标志位,每次接收完成都需要清除一下
while(USART_GetFlagStatus(USART3,USART_FLAG_TC) ==RESET); //用于检查串口UART1是否发送完成,完成时,TC中断标志置位,退出轮询等待!
}
}
有利有弊,两种方法你会选什么呢?
最后,我们来码主函数了
主函数,我这里只是码简单的,易于理解,后期能理解的天才可以添加的其他程序,使之更完美!
int main(void)
{
USART3_Config(); //USART初始化函数
while(1) //死循环,永为真。所以用中断函数来中断
{
if(COM3_RecvFin==1) //判断到COM3_RecvFin标志为1,表示接收成功
{
COM3_RecvFin=0; //COM3_RecvFin标志清零,防止死循环
USART_SendData(USART3,data[1]);//发送数组data的第2个字节,这里简单发送,可以添加自己需要的程序
}
}
}
手痒的,想要试试的,记得开头添加下面的头文件、函数声明、变量定义
/*---------头文件---------*/
#include "stm32f10x.h"
/*---------函数声明---------*/
void USART3_Config(void);
void USART3_IRQHandler(void);
u8 COM3_RecvFin=0;
u8 Start_Receiving=0;
u8 i=0;
unsigned char data[10];
有什么遗漏、错误,请在下面的评论写,一起交流交流。