历史上的今天
今天是:2025年04月12日(星期六)
2019年04月12日 | STM32F4 USART1 TX RX FIFO
2019-04-12 来源:eefocus
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) *********************************/
史海拾趣
|
一个女电子工程师的(心/芯/辛)路,即将脱离技术岗位,仅以此文纪念吾之技术生涯 ( 首先我是女性,这个先声名,免得有些网友说俺用此做为噱头。) 同其他大多数女性一样,形象思维要好于逻辑思维。但我又与大多数女性不一样,我有我自己独 ...… 查看全部问答> |
|
测振仪的技术原理及测振仪的技术问题 测振仪的技术原理, 测振仪的技术问题: 现在的测振仪一般都采用压电式的,结构形式大致有二种:① 压缩式;② 剪切式,其原理是利用石英晶体和人工极化陶瓷(PZT)的压电效应设计而成。当石 ...… 查看全部问答> |
|
大家好,有人问到如何实现会唱歌的玩具娃娃,就和市面上的玩具娃娃一样,按一下,会唱首歌,再按一下会笑,再按会说话什么的,因为本人从来不涉及硬件设计知识,所以没办法回答朋友的问题,现在请大家告诉我下这个玩具娃娃是怎么个设计实现原理,谢 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:00 编辑 最近都在找资料,都没有找到关于液体点滴的优秀作品,哪位大侠有,请发我一份!谢谢! … 查看全部问答> |
|
再提供一个小作品:EK-STM3210E大容量仿真学习套件上市啦! 仿真器 - 内嵌ST-LINK II仿真器,支持STM32F10x标准系列和扩展总线系列Cortex-M3 MCU - USB2.0全速,USB供电 - 支持评估系统或用户目标系统仿真 - 下载速度大于5K/秒 - 通过跳线 ...… 查看全部问答> |
|
用的芯片是STM8S103F3.使用串口1,内部时钟,查询发送,中断或者查询接收疑问:STM8的管教复用是不是,你配置了串口,那么相应的两个管脚IO就自动成为RXD和TXD?现在的把收发两个管脚直接短路,程序里面一直在发送,用万用表测试电压为1.8V左右,估 ...… 查看全部问答> |
|
请问,TI的28335DSP. 给GPIO配置为数字IO,且为输入,当给其输入高低电平的时候,为什么在GPxDAT寄存器中看到的状态和输入的状态不同,有时候改变输入电平后,但GPxDAT中的电平还是不变 [ 本帖最后由 kikihi 于 2012-12-15 14:36 编辑 ]… 查看全部问答> |
|
雕刻机买回来一年多了,平时就是用来做一下外壳和五金件的样品加工,但从来没有用来做过PCB电路板,当时买这个机器的时候,同时也考虑做电路板的,所以在精度方面也考虑到了。尽管在机器的控制方面比较熟悉,但是第一次做电路板,尽管在参考了网上 ...… 查看全部问答> |




