USART1 TX RX FIFO
/*
*********************************************************************************************************
*
* 模块名称 : 串口驱动模块
* 文件名称 : bsp_uart.c
* 版 本 : V1.0
* 说 明 : 实现printf和scanf函数重定向到串口1,即支持printf信息到USART1
* 实现重定向,只需要添加2个函数:
* int fputc(int ch, FILE *f);
* int fgetc(FILE *f);
* 对于KEIL MDK编译器,编译选项中需要在MicorLib前面打钩,否则不会有数据打印到USART1。
* 修改记录 :
* 版 本 库 : ST固件库V1.0.2版本。
*
*********************************************************************************************************
*/
//#include "stm32f4xx.h"
#include "bspdebug_usartbsp_debug_uart.h"
#include "bsp.h"
#include
#define debug_uart_tx_buf_size 1*1024
#define debug_uart_rx_buf_size 1*1024
static uint8_t g_TxBuf[debug_uart_tx_buf_size]; //发送缓冲区
static uint8_t g_RxBuf[debug_uart_rx_buf_size]; //接受缓冲区
/* 串口设备结构体 */
typedef struct
{
USART_TypeDef *uart; /* STM32内部串口设备指针*/
uint8_t *pTxBuf; /* 发送缓冲区 */
uint8_t *pRxBuf; /* 接收缓冲区 */
uint16_t usTxBufSize; /* 发送缓冲区大小 */
uint16_t usRxBufSize; /* 接收缓冲区大小 */
uint16_t usTxWrite; /* 发送缓冲区写指针 */
uint16_t usTxRead; /* 发送缓冲区读指针 */
uint16_t usTxCount; /* 等待发送的数据个数 */
uint16_t usRxWrite; /* 接收缓冲区写指针 */
uint16_t usRxRead; /* 接收缓冲区读指针 */
uint16_t usRxCount; /* 还未读取的新数据个数 */
void (*SendBefor)(void); /* 开始发送之前的回调函数指针(主要用于RS485切换到发送模式) */
void (*SendOver)(void); /* 发送完毕的回调函数指针(主要用于RS485将发送模式切换为接收模式) */
void (*ReciveNew)(void); /* 串口收到数据的回调函数指针 */
}UART_T;
static UART_T g_tDebugUart;
static void UartVarInit(void)
{
g_tDebugUart.uart=USART1;
g_tDebugUart.pTxBuf = g_TxBuf; /* 发送缓冲区指针 */
g_tDebugUart.pRxBuf = g_RxBuf; /* 接收缓冲区指针 */
g_tDebugUart.usTxBufSize = debug_uart_tx_buf_size; /* 发送缓冲区大小 */
g_tDebugUart.usRxBufSize = debug_uart_rx_buf_size; /* 接收缓冲区大小 */
g_tDebugUart.usTxWrite = 0; /* 发送FIFO写索引 */
g_tDebugUart.usTxRead = 0; /* 发送FIFO读索引 */
g_tDebugUart.usRxWrite = 0; /* 接收FIFO写索引 */
g_tDebugUart.usRxRead = 0; /* 接收FIFO读索引 */
g_tDebugUart.usRxCount = 0; /* 接收到的新数据个数 */
g_tDebugUart.usTxCount = 0; /* 待发送的数据个数 */
g_tDebugUart.SendBefor = 0; /* 发送数据前的回调函数 */
g_tDebugUart.SendOver = 0; /* 发送完毕后的回调函数 */
g_tDebugUart.ReciveNew = 0; /* 接收到新数据后的回调函数 */
}
static void ConfigUartNVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitUart
* 功能说明: 初始化CPU的USART1串口硬件设备。未启用中断。
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitDebugUart(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
UartVarInit();
ConfigUartNVIC();
/* 串口1 TX = PA9 RX = PA10 */
/* 第1步: 配置GPIO */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/* 打开 GPIO 时钟 */
/* 打开 UART 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 将 PA9 映射为 USART1_TX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
/* 将 PA10 映射为 USART1_RX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = 115200; /* 波特率 */
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); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART1, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
}
void comSendChar(int ch)
{
if(g_tDebugUart.SendBefor!=0)//开始回调前调用回调函数
{
g_tDebugUart.SendBefor();
}
while(1)
{
uint16_t usRead;
DISABLE_INT();
usRead = g_tDebugUart.usTxCount;
ENABLE_INT();
if( usRead < g_tDebugUart.usTxBufSize)//如果发送缓冲区域的满则等待
{
break;
}
}
g_tDebugUart.pTxBuf[g_tDebugUart.usTxWrite]= ch;//向发送缓存区写入数值
DISABLE_INT();
if (++g_tDebugUart.usTxWrite >= g_tDebugUart.usTxBufSize)//发送指针加一
{
g_tDebugUart.usTxWrite = 0;
}
g_tDebugUart.usTxCount++;//发送数加一
ENABLE_INT();
USART_ITConfig(g_tDebugUart.uart, USART_IT_TXE, ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名: UartGetChar
* 功能说明: 从串口接收缓冲区读取1字节数据 (用于主程序调用)
* 形 参: _pUart : 串口设备
* _pByte : 存放读取数据的指针
* 返 回 值: 0 表示无数据 1表示读取到数据
*********************************************************************************************************
*/
uint8_t comGetChar( uint8_t *_pByte)
{
uint16_t usCount;
DISABLE_INT();
usCount = g_tDebugUart.usRxCount;
ENABLE_INT();
if(usCount==0)
{
return 0;
}
else
{
*_pByte = g_tDebugUart.pRxBuf[g_tDebugUart.usRxRead]; /* 从串口接收FIFO取1个数据 */
/* 改写FIFO读索引 */
DISABLE_INT();
if (++g_tDebugUart.usRxRead >= g_tDebugUart.usRxBufSize)
{
g_tDebugUart.usRxRead = 0;
}
g_tDebugUart.usRxCount--;
ENABLE_INT();
return 1;
}
}
/*
*********************************************************************************************************
* name: fputc 重定向printf
*********************************************************************************************************
*/
int fputc(int ch, FILE *f)
{
#if 1
comSendChar(ch);
return ch;
#else
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET){};
USART_SendData(USART1, (u16) ch);
return ch;
#endif
}
/*
*********************************************************************************************************
*重定向getc
*********************************************************************************************************
*/
int fgetc(FILE *f)
{
#if 1
uint8_t ucData;
while(comGetChar(&ucData) == 0);
return ucData;
#else
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
#endif
}
void USART1_IRQHandler(void)
{
/* 处理接收中断 */
if (USART_GetITStatus(g_tDebugUart.uart, USART_IT_RXNE) != RESET)
{
g_tDebugUart.pRxBuf[g_tDebugUart.usRxWrite] = USART_ReceiveData(g_tDebugUart.uart); /* 从串口接收数据寄存器读取数据存放到接收FIFO */
if (++g_tDebugUart.usRxWrite >= g_tDebugUart.usRxBufSize)
{
g_tDebugUart.usRxWrite = 0;
}
if (g_tDebugUart.usRxCount < g_tDebugUart.usRxBufSize)
{
g_tDebugUart.usRxCount++;
}
/* 回调函数,通知应用程序收到新数据,一般是发送1个消息或者设置一个标记 */
//if (_pUart->usRxWrite == _pUart->usRxRead)
if (g_tDebugUart.usRxCount == 1)
{
if (g_tDebugUart.ReciveNew)
{
g_tDebugUart.ReciveNew();
}
}
}
/* 处理发送缓冲区空中断 */
if (USART_GetITStatus(g_tDebugUart.uart, USART_IT_TXE) != RESET)
{
//if (_pUart->usTxRead == _pUart->usTxWrite)
if (g_tDebugUart.usTxCount == 0)
{
USART_ITConfig(g_tDebugUart.uart, USART_IT_TXE, DISABLE);/* 发送缓冲区的数据已取完时, 禁止发送缓冲区空中断 (注意:此时最后1个数据还未真正发送完毕)*/
USART_ITConfig(g_tDebugUart.uart, USART_IT_TC, ENABLE);/* 使能数据发送完毕中断 */
}
else
{
USART_SendData(g_tDebugUart.uart, g_tDebugUart.pTxBuf[g_tDebugUart.usTxRead]);/* 从发送FIFO取1个字节写入串口发送数据寄存器 */
if (++g_tDebugUart.usTxRead >= g_tDebugUart.usTxBufSize)
{
g_tDebugUart.usTxRead = 0;
}
g_tDebugUart.usTxCount--;
}
}
else if (USART_GetITStatus(g_tDebugUart.uart, USART_IT_TC) != RESET)/* 数据bit位全部发送完毕的中断 */
{
if (g_tDebugUart.usTxCount == 0)
{
USART_ITConfig(g_tDebugUart.uart, USART_IT_TC, DISABLE);/* 如果发送FIFO的数据全部发送完毕,禁止数据发送完毕中断 */
/* 回调函数, 一般用来处理RS485通信,将RS485芯片设置为接收模式,避免抢占总线 */
if (g_tDebugUart.SendOver)
{
g_tDebugUart.SendOver();
}
}
else
{
/* 正常情况下,不会进入此分支 */
/* 如果发送FIFO的数据还未完毕,则从发送FIFO取1个数据写入发送数据寄存器 */
USART_SendData(g_tDebugUart.uart, g_tDebugUart.pTxBuf[g_tDebugUart.usTxRead]);
if (++g_tDebugUart.usTxRead >= g_tDebugUart.usTxBufSize)
{
g_tDebugUart.usTxRead = 0;
}
g_tDebugUart.usTxCount--;
}
}
}
/***************************** (END OF FILE) *********************************/
上一篇:STM32的USART中RTS、CTS的作用和意义
下一篇:STM32 串口详细讲解
推荐阅读最新更新时间:2024-03-16 16:27