多串口通信(stm32)

在做项目的过程中我们会同时使用多个串口,如:Esp8266wifl模块,HC-05蓝牙模块,还有串口下载,这些都需要多个串口通信。

STM32 串口简介

串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。

现在基本上所有的 MCU 都会带有串口,STM32 自然也不例外。

STM32 的串口资源相当丰富的,功能也相当强劲。ALIENTEK MiniSTM32 开发板所使用

的 STM32F103RCT6 最多可提供 5 路串口,有分数波特率发生器、支持同步单线通信和半双工

单线通讯、支持 LIN、支持调制解调器操作、智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA

等。

多串口的实现

一,寻找引脚

在stm32F103c8t6引脚定义中可以看到

串口1:

串口2:

二,串口初始化

串口1的初始化,以及串口中断的处理【正点原子例程】

u8 USART_RX_BUF[USART_REC_LEN]; //能够接收的最大字节数

u16 USART_RX_STA=0; //当前接收状态的标记

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_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=1 ;//ÇÀÕ¼ÓÅÏȼ¶3

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //×ÓÓÅÏȼ¶3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ

NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷

//USART 初始化配置

USART_InitStructure.USART_BaudRate = bound;//波特率的设置,一般设置为9600

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

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);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断

USART_Cmd(USART1, ENABLE); //使能串口

}

void USART1_IRQHandler(void) //中断处理

{

u8 Res;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(数据必须为OXod,OXoa结尾)

{

Res =USART_ReceiveData(USART1); //接收一个字节赋值给变量res

if((USART_RX_STA&0x8000)==0)//接收未完成

{

if(USART_RX_STA&0x4000)//接收到了0x0d

{

if(Res!=0x0a)USART_RX_STA=0;//未接收到0Xoa

else USART_RX_STA|=0x8000; //接收完成

}

else //还未收到OXOD

{

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;//长度溢出,数据出错

}

}

}

}

串口2初始化及其中断:

其实就是改变引脚。

代码如下

#include "usart2.h"

#include "sys.h"

u8 USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符

u16 USART2_RX_STA; //接收状态标记

void uart2_init(u32 bound){

//GPIO端口设置

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟

//USART1_TX GPIOA.2

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //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.3初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA10

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入

GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10

//RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2

//RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位

//Usart1 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级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(USART2, &USART_InitStructure); //初始化串口1

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断

USART_Cmd(USART2, ENABLE); //使能串口1

}

void USART2_IRQHandler(void) //串口1中断服务程序

{

u8 Res;

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)

{

Res =USART_ReceiveData(USART2); //读取接收到的数据

if((USART2_RX_STA&0x8000)==0)//接收未完成

{

if(USART2_RX_STA&0x4000)//接收到了0x0d

{

if(Res!=0x0a)USART2_RX_STA=0;//接收错误,重新开始

else USART2_RX_STA|=0x8000; //接收完成了

}

else //还没收到0X0D

{

if(Res==0x0d)USART2_RX_STA|=0x4000;

else

{

USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res;

USART2_RX_STA++;

if(USART2_RX_STA>(USART_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收

}

}

}

}

}

友情链接:
Copyright © 2022 86年世界杯_世界杯预选赛阿根廷 - fjyfzz.com All Rights Reserved.