以前一直忽视,记录做开发中遇到的问题,决定不再懒了,本文主要是配置STM32F407VET6的串口2,对应PA2,PA3。大家都知道正点原子配置了串口1,之前一直想配置串口3,可惜一直没成功,尝试了串口2,4,5,6的配置,都没有问题,就3不行,我怀疑我的板子有问题,不过先把已解决的问题记录下来,以后解决了,再写。特别注意:printf函数已经在库函数中和usart1配置好了,现在是使用usart2,所以printf不可以在串口2的收发函数里出现,不然串口1会对串口2产生干扰。
目前主要是用库函数,偶尔使用寄存器,还是太懒了,实在是看不进去寄存器手册,言归正传,配置串口的步骤,原子大神已经描述的相当清楚了。
包括以下步骤: 1.配置串口时钟和和GPIO时钟使能。
2.设置引脚复用器映射。
3.GPIO端口模式设置
4.串口参数初始化:设置波特率,字长,奇偶校验等参数
5.初始化NVIC.
6.开启中断
7.使能串口
中断配置: 当接收到从电脑发过来的数据,把接收到的数据保存在 USART2_RX_BUF 中,同时在接收状态寄存器(USART2_RX_STA)中计数接收到的有效数据 个数,当 收到回车(回车的表示由 2个字节组成:0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待 0X0A 的到来,而如果 0X0A 没有来到, 则认为这次接收失败,重新开始下一次接收。如果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该位被其他程序清 除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过USART_REC_LEN的时候,则会丢弃前面的数据,重新接收。

usart2.c usart2.h main.c代码如下:
//---------usart2.c文件-----------------------------------------------------------------------------------------------------------------------------------//
//初始化IO 串口2
#include “delay.h”
#include “usart3.h”
#include “stdarg.h”
#include “stdio.h”
#include “string.h”
//串口发送缓存区
__align(8) u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN字节
#ifdef USART2_RX_EN //如果使能了接收
//串口接收缓存区
u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; //接收缓冲,最大USART2_MAX_RECV_LEN个字节。
u16 USART2_RX_STA = 0;
void USART2_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
res =USART_ReceiveData(USART2);//(USART1-》DR); //读取接收到的数据
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》(USART2_MAX_RECV_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
//bound:波特率
void usart2_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
//1.串口时钟和和GPIO时钟使能。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
//2.设置引脚复用器映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2
//3.GPIO端口模式设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2和GPIOA3初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA2,和GPIOA3
//4.串口参数初始化:设置波特率,字长,奇偶校验等参数
USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
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); //初始化串口2参数
//5.初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//6.开启中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
//7.使能串口
USART_Cmd(USART2, ENABLE); //使能串口
}
//------usart2.h-----------------------------------------------------------------------------------------------------------------------------------------------
#ifndef __USART2_H
#define __USART2_H
#include “sys.h”
#define USART2_MAX_RECV_LEN 400 //最大接收缓存字节数
#define USART2_MAX_SEND_LEN 400 //最大发送缓存字节数
#define USART2_RX_EN 1 //0,不接收;1,接收。
extern u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; //接收缓冲,最大USART2_MAX_RECV_LEN字节
extern u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN字节
extern u16 USART2_RX_STA; //接收数据状态
void usart2_init(u32 bound); //串口2初始化
//void TIM7_Int_Init(u16 arr,u16 psc);
void u2_printf(char* fmt, 。..);
#endif
//----------main.c---------------------------------------------------------------------------------------------------------------------------------------------------------
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
#include “key.h”
#include “sram.h”
#include “malloc.h”
#include “usmart.h”
#include “sdio_sdcard.h”
#include “malloc.h”
#include “w25qxx.h”
#include “ff.h”
#include “exfuns.h”
//串口3头文件
#include “usart3.h”
#include “timer.h”
#include “string.h”
//STM32F407
//FATFS 实验 -库函数版本
/**SD卡管理变量***/
//u8 textFileBuffer[] = “Chinese and English test strings rnChinese and English test strings2”;
//FIL fsrc, fdst; /* file objects */
//char path0[512;
//char buffer[4096]; /* file copy buffer */
/**主函数变量**/
u8 t=0;
/**自定义函数声明**/
void system_init(void);
void SD_TEST(void);
int main(void)
{
u8 t;
u8 len;
u16 times=0;
u8 USART_RX_BUF1[10] = {‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘n’}; //接收缓冲,最大USART_REC_LEN个字节。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //延时初始化
//uart_init(115200); //串口初始化波特率为115200
usart2_init(9600);
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
if(USART2_RX_STA&0x8000)
{
len=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
for(t=0;t《len;t++)
{
USART_SendData(USART2, USART2_RX_BUF[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
USART2_RX_STA=0;
}else
{
times++;
if(times%50==0)
{
for(t=0;t《10;t++)
{
USART_SendData(USART2, USART_RX_BUF1[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
}
if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行。
delay_ms(10);
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------
在主函数main.c里还有部分SD卡实验的头文件和变量声明,不用管,去掉也没关系。
以前一直忽视,记录做开发中遇到的问题,决定不再懒了,本文主要是配置STM32F407VET6的串口2,对应PA2,PA3。大家都知道正点原子配置了串口1,之前一直想配置串口3,可惜一直没成功,尝试了串口2,4,5,6的配置,都没有问题,就3不行,我怀疑我的板子有问题,不过先把已解决的问题记录下来,以后解决了,再写。特别注意:printf函数已经在库函数中和usart1配置好了,现在是使用usart2,所以printf不可以在串口2的收发函数里出现,不然串口1会对串口2产生干扰。
目前主要是用库函数,偶尔使用寄存器,还是太懒了,实在是看不进去寄存器手册,言归正传,配置串口的步骤,原子大神已经描述的相当清楚了。
包括以下步骤: 1.配置串口时钟和和GPIO时钟使能。
2.设置引脚复用器映射。
3.GPIO端口模式设置
4.串口参数初始化:设置波特率,字长,奇偶校验等参数
5.初始化NVIC.
6.开启中断
7.使能串口
中断配置: 当接收到从电脑发过来的数据,把接收到的数据保存在 USART2_RX_BUF 中,同时在接收状态寄存器(USART2_RX_STA)中计数接收到的有效数据 个数,当 收到回车(回车的表示由 2个字节组成:0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待 0X0A 的到来,而如果 0X0A 没有来到, 则认为这次接收失败,重新开始下一次接收。如果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该位被其他程序清 除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过USART_REC_LEN的时候,则会丢弃前面的数据,重新接收。

usart2.c usart2.h main.c代码如下:
//---------usart2.c文件-----------------------------------------------------------------------------------------------------------------------------------//
//初始化IO 串口2
#include “delay.h”
#include “usart3.h”
#include “stdarg.h”
#include “stdio.h”
#include “string.h”
//串口发送缓存区
__align(8) u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN字节
#ifdef USART2_RX_EN //如果使能了接收
//串口接收缓存区
u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; //接收缓冲,最大USART2_MAX_RECV_LEN个字节。
u16 USART2_RX_STA = 0;
void USART2_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
res =USART_ReceiveData(USART2);//(USART1-》DR); //读取接收到的数据
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》(USART2_MAX_RECV_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
//bound:波特率
void usart2_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
//1.串口时钟和和GPIO时钟使能。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
//2.设置引脚复用器映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2
//3.GPIO端口模式设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2和GPIOA3初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA2,和GPIOA3
//4.串口参数初始化:设置波特率,字长,奇偶校验等参数
USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
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); //初始化串口2参数
//5.初始化NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//6.开启中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
//7.使能串口
USART_Cmd(USART2, ENABLE); //使能串口
}
//------usart2.h-----------------------------------------------------------------------------------------------------------------------------------------------
#ifndef __USART2_H
#define __USART2_H
#include “sys.h”
#define USART2_MAX_RECV_LEN 400 //最大接收缓存字节数
#define USART2_MAX_SEND_LEN 400 //最大发送缓存字节数
#define USART2_RX_EN 1 //0,不接收;1,接收。
extern u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; //接收缓冲,最大USART2_MAX_RECV_LEN字节
extern u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN字节
extern u16 USART2_RX_STA; //接收数据状态
void usart2_init(u32 bound); //串口2初始化
//void TIM7_Int_Init(u16 arr,u16 psc);
void u2_printf(char* fmt, 。..);
#endif
//----------main.c---------------------------------------------------------------------------------------------------------------------------------------------------------
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
#include “key.h”
#include “sram.h”
#include “malloc.h”
#include “usmart.h”
#include “sdio_sdcard.h”
#include “malloc.h”
#include “w25qxx.h”
#include “ff.h”
#include “exfuns.h”
//串口3头文件
#include “usart3.h”
#include “timer.h”
#include “string.h”
//STM32F407
//FATFS 实验 -库函数版本
/**SD卡管理变量***/
//u8 textFileBuffer[] = “Chinese and English test strings rnChinese and English test strings2”;
//FIL fsrc, fdst; /* file objects */
//char path0[512;
//char buffer[4096]; /* file copy buffer */
/**主函数变量**/
u8 t=0;
/**自定义函数声明**/
void system_init(void);
void SD_TEST(void);
int main(void)
{
u8 t;
u8 len;
u16 times=0;
u8 USART_RX_BUF1[10] = {‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘n’}; //接收缓冲,最大USART_REC_LEN个字节。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //延时初始化
//uart_init(115200); //串口初始化波特率为115200
usart2_init(9600);
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
if(USART2_RX_STA&0x8000)
{
len=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
for(t=0;t《len;t++)
{
USART_SendData(USART2, USART2_RX_BUF[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
USART2_RX_STA=0;
}else
{
times++;
if(times%50==0)
{
for(t=0;t《10;t++)
{
USART_SendData(USART2, USART_RX_BUF1[t]); //向串口1发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
}
if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行。
delay_ms(10);
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------------
在主函数main.c里还有部分SD卡实验的头文件和变量声明,不用管,去掉也没关系。
举报