1.无中断版,接收的话有问题,会丢包。
因为不是中断接收,有可能数据在发送过来时程序在执行其他的事情导致无法接收到完整数据。
2.无中断版配置(配置第三步复用时注意不能用"|"合并为一条语句)
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#include "board.h"
void send_data(USART_TypeDef* USARTx,uint8_t data)
{
USART_SendData(USARTx,data);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)!=SET); //等待发送寄存器为空
}
void send_buff(USART_TypeDef* USARTx, uint8_t *s)
{
while(*s && s) //数据为空,或者地址为空跳出
send_data(USARTx,*s++);
}
uint8_t rx_data[10]={0};
uint8_t rx_index=0;
int main(void)
{
board_init();
//1.定义结构体
GPIO_InitTypeDef gpioinit;
//2.开启gpio时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
//3.复用配置(注意此处不可以用 | )
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
//4.配置gpio
gpioinit.GPIO_Mode=GPIO_Mode_AF;
gpioinit.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
gpioinit.GPIO_OType=GPIO_OType_PP;
gpioinit.GPIO_PuPd=GPIO_PuPd_UP;
gpioinit.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&gpioinit);
//5.定义串口结构体
USART_InitTypeDef usart1_init;
//6.开启串口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//7.配置串口
usart1_init.USART_BaudRate=115200U;
usart1_init.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
usart1_init.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
usart1_init.USART_Parity=USART_Parity_No;
usart1_init.USART_StopBits=USART_StopBits_1;
usart1_init.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&usart1_init);
//8.初始化成功清除接收置位
USART_ClearFlag(USART1,USART_FLAG_RXNE);
//9.使能串口
USART_Cmd(USART1,ENABLE);
while(1)
{
//是否接收到数据
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
{
uint8_t i=0;
while(rx_index<10)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
{
USART_ClearFlag(USART1,USART_FLAG_RXNE);
rx_data[rx_index]=USART_ReceiveData(USART1);
rx_index++;
}
}
send_buff(USART1 ,"receive:\r\n");
send_buff(USART1,rx_data);
rx_index=0;
}
//没有接收到内容
else
{
send_buff(USART1,"hello\r\n");
delay_ms(1000);
}
}
}
3、含中断版,推荐
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*/
#include "board.h"
void send_data(USART_TypeDef* USARTx,uint8_t data)
{
USART_SendData(USARTx,data);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)!=SET); //等待发送寄存器为空
}
void send_buff(USART_TypeDef* USARTx, uint8_t *s)
{
while(*s && s) //数据为空,或者地址为空跳出
send_data(USARTx,*s++);
}
uint8_t ItRxFlag=0; //接收中断标志位
uint8_t rx_buff[3]={0};
uint8_t rx_index=0;
int main(void)
{
board_init();
//1.定义结构体
GPIO_InitTypeDef gpioinit;
//2.开启gpio时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
//3.复用配置(注意此处不可以用 | )
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
//4.配置gpio
gpioinit.GPIO_Mode=GPIO_Mode_AF;
gpioinit.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
gpioinit.GPIO_OType=GPIO_OType_PP;
gpioinit.GPIO_PuPd=GPIO_PuPd_UP;
gpioinit.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&gpioinit);
//5.定义串口结构体
USART_InitTypeDef usart1_init;
//6.开启串口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//7.配置串口
usart1_init.USART_BaudRate=115200U;
usart1_init.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
usart1_init.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
usart1_init.USART_Parity=USART_Parity_No;
usart1_init.USART_StopBits=USART_StopBits_1;
usart1_init.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&usart1_init);
//8.初始化成功清除接收置位
USART_ClearFlag(USART1,USART_FLAG_RXNE);
//9.使能串口
USART_Cmd(USART1,ENABLE);
//10.配置中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//11.定义中断结构体
NVIC_InitTypeDef nvic_init;
//12.配置中断
nvic_init.NVIC_IRQChannel=USART1_IRQn;
nvic_init.NVIC_IRQChannelCmd=ENABLE;
nvic_init.NVIC_IRQChannelPreemptionPriority=0x00;
nvic_init.NVIC_IRQChannelSubPriority=0x01;
//13.初始化中断
NVIC_Init(&nvic_init);
while(1)
{
send_buff(USART1,"hello\r\n");
delay_ms(1000);
if(ItRxFlag==1) //接收到三个字节
{
ItRxFlag=0;
send_buff(USART1,rx_buff);
}
}
}
//14.串口1中断服务函数
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
rx_buff[rx_index]=USART_ReceiveData(USART1);
rx_index++;
if(rx_index==3)
{
ItRxFlag=1;
rx_index=0;
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
4.立创给的例子
这个是比较推荐的,因为他定义了很多宏,到时候想要用那个串口,直接修改宏就可以了,但是没有写出中断服务函数需要自己去加入。做了重定向,使用printf函数需要勾选
bsp_uart.c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*
Change Logs:
* Date Author Notes
* 2024-03-07 LCKFB-LP first version
*/
#include "bsp_uart.h"
#include "stdio.h"
void uart1_init(uint32_t __Baud)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(BSP_USART_TX_RCC,ENABLE);
// RCC_AHB1PeriphClockCmd(BSP_USART_RX_RCC,ENABLE);
//IO口用作串口引脚要配置复用模式
GPIO_PinAFConfig(BSP_USART_TX_PORT,BSP_USART_TX_AF_PIN,BSP_USART_AF);
GPIO_PinAFConfig(BSP_USART_RX_PORT,BSP_USART_RX_AF_PIN,BSP_USART_AF);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BSP_USART_TX_PIN; //TX引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //IO口用作串口引脚要配置复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BSP_USART_RX_PIN; //RX引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //IO口用作串口引脚要配置复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;//定义配置串口的结构体变量
RCC_APB2PeriphClockCmd(BSP_USART_RCC, ENABLE);//开启串口1的时钟
USART_DeInit(BSP_USART);//大概意思是解除此串口的其他配置
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = __Baud;//设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字节长度为8bit
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No ;//没有校验位
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//将串口配置为收发模式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不提供流控
USART_Init(BSP_USART,&USART_InitStructure);//将相关参数初始化给串口1
USART_ClearFlag(BSP_USART,USART_FLAG_RXNE);//初始配置时清除接受置位
USART_Cmd(BSP_USART,ENABLE);//开启串口1
USART_ITConfig(BSP_USART, USART_IT_RXNE, ENABLE);//初始配置接受中断
NVIC_InitTypeDef NVIC_InitStructure;//中断控制结构体变量定义
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中断通道指定为USART1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//次优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//确定使能
NVIC_Init(&NVIC_InitStructure);//初始化配置此中断通道
}
void usart_send_data(uint8_t ucch)
{
USART_SendData(BSP_USART, (uint8_t)ucch);
// 等待发送数据缓冲区标志置位
while( RESET == USART_GetFlagStatus(BSP_USART, USART_FLAG_TXE) ){}
}
void usart_send_String(uint8_t *ucstr)
{
while(ucstr && *ucstr) // 地址为空或者值为空跳出
{
usart_send_data(*ucstr++);
}
}
#if !defined(__MICROLIB)
//不使用微库的话就需要添加下面的函数
#if (__ARMCLIB_VERSION <= 6000000)
//如果编译器是AC5 就定义下面这个结构体
struct __FILE
{
int handle;
};
#endif
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
#endif
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
USART_SendData(BSP_USART, (uint8_t)ch);
while( RESET == USART_GetFlagStatus(BSP_USART, USART_FLAG_TXE) ){}
return ch;
}
bsp_uart.h
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*
Change Logs:
* Date Author Notes
* 2024-03-07 LCKFB-LP first version
*/
#ifndef __BSP_UART_H__
#define __BSP_UART_H__
#include "stm32f4xx.h"
#define BSP_USART_RCC RCC_APB2Periph_USART1
#define BSP_USART_TX_RCC RCC_AHB1Periph_GPIOA
#define BSP_USART_RX_RCC RCC_AHB1Periph_GPIOA
#define BSP_USART USART1
#define BSP_USART_TX_PORT GPIOA
#define BSP_USART_TX_PIN GPIO_Pin_9
#define BSP_USART_RX_PORT GPIOA
#define BSP_USART_RX_PIN GPIO_Pin_10
#define BSP_USART_AF GPIO_AF_USART1
#define BSP_USART_TX_AF_PIN GPIO_PinSource9
#define BSP_USART_RX_AF_PIN GPIO_PinSource10
//外部可调用函数的声明
void uart1_init(uint32_t __Baud);
void usart_send_data(uint8_t ucch);
void usart_send_String(uint8_t *ucstr);
#endif