📄 uart_api.c
字号:
USART_TypeDef *uart;
/* 第1步:打开GPIO和USART部件的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步:将USART Rx的GPIO配置为浮空输入模式
由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步已经做了,因此这步可以不做
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第4步:设置串口硬件参数 */
uart = USART2;
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(uart, &USART_InitStructure);
USART_ITConfig(uart, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(uart, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART2, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */
}
/****************************************************************************
* 函数名: InitHardUart3
* 功 能: 配置USART3硬件参数
* 输 入: 无
* 返 回: 无
*/
static void InitHardUart3(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_TypeDef *uart;
/* 第1步:打开GPIO和USART部件的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 第3步:将USART Rx的GPIO配置为浮空输入模式
由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 第3步已经做了,因此这步可以不做
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 第4步:设置串口硬件参数 */
uart = USART3;
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(uart, &USART_InitStructure);
USART_ITConfig(uart, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(uart, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART3, USART_FLAG_TC); /* 清发送外城标志,Transmission Complete flag */
}
/****************************************************************************
* 函数名: RS485SendOver
* 功 能: 向RS485总线发送一帧数据结束后,立即调用本函数.
* 输 入: 无
* 输 出: 无
* 返 回: 无
*/
static void RS485SendOver(void)
{
RS485_TX_Disable(); /* 释放总线 */
}
/****************************************************************************
* 函数名: UartSend
* 功 能: 填写数据到UART发送缓冲区,并启动发送中断。中断处理函数发送完毕后,自动
* 关闭发送中断。
* 输 入: _pUart: 串口结构体指针
* 输 出: 无
* 返 回: 无
*/
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen)
{
uint16_t i;
uint8_t ucNew = 0;
CPU_IntDis();
if (_pUart->usTxWrite == _pUart->usTxRead)
{
ucNew = 1;
}
CPU_IntEn();
for (i = 0; i < _usLen; i++)
{
_pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf[i];
CPU_IntDis();
if (++_pUart->usTxWrite >= _pUart->usTxBufSize)
{
_pUart->usTxWrite = 0;
}
CPU_IntEn();
}
if (ucNew == 1)
{
USART_ITConfig(_pUart->uart, USART_IT_TXE, ENABLE);
}
}
/****************************************************************************
* 函数名: UartIRQ
* 功 能: 供中断服务程序调用,通用串口中断处理函数
* 输 入: _pUart: 串口结构体指针
* 输 出: 无
* 返 回: 无
*/
void UartIRQ(UART_T *_pUart)
{
if (USART_GetITStatus(_pUart->uart, USART_IT_RXNE) != RESET)
{
/* 回调函数,通知应用程序发送完毕,一般是发送1个消息或者设置一个标记 */
if (_pUart->usRxWrite == _pUart->usRxRead)
{
if (_pUart->ReciveNew)
{
_pUart->ReciveNew();
}
}
/* Read one byte from the receive data register */
_pUart->pRxBuf[_pUart->usRxWrite] = USART_ReceiveData(_pUart->uart);
if (++_pUart->usRxWrite >= _pUart->usRxBufSize)
{
_pUart->usRxWrite = 0;
}
}
/* 发送缓冲区空中断 */
if (USART_GetITStatus(_pUart->uart, USART_IT_TXE) != RESET)
{
if (_pUart->usTxRead == _pUart->usTxWrite)
{
/* 禁止发送缓冲区空中断,使能发送完毕中断 */
USART_ITConfig(_pUart->uart, USART_IT_TXE, DISABLE);
USART_ITConfig(_pUart->uart, USART_IT_TC, ENABLE);
}
else
{
/* Write one byte to the transmit data register */
USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize)
{
_pUart->usTxRead = 0;
}
}
}
/* 1个字节发送完毕的中断 */
else if (USART_GetITStatus(_pUart->uart, USART_IT_TC) != RESET)
{
if (_pUart->usTxRead == _pUart->usTxWrite)
{
/* 禁止发送缓冲区空中断,使能发送完毕中断 */
USART_ITConfig(_pUart->uart, USART_IT_TC, DISABLE);
/* 回调函数,通知应用程序发送完毕,一般是发送1个消息或者设置一个标记 */
if (_pUart->SendOver)
{
_pUart->SendOver();
}
}
else
{
/* Write one byte to the transmit data register */
USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize)
{
_pUart->usTxRead = 0;
}
}
}
}
/****************************************************************************
* 函数名: USART1_IRQHandler
* 功 能: USART1中断服务程序.
* 输 入: 无
* 输 出: 无
* 返 回: 无
*/
void USART1_IRQHandler(void)
{
UartIRQ(&g_tUart1);
}
/****************************************************************************
* 函数名: USART2_IRQHandler
* 功 能: USART2中断服务程序.
* 输 入: 无
* 输 出: 无
* 返 回: 无
*/
void USART2_IRQHandler(void)
{
UartIRQ(&g_tUart2);
}
/****************************************************************************
* 函数名: USART3_IRQHandler
* 功 能: UART3中断服务程序.
* 输 入: 无
* 输 出: 无
* 返 回: 无
*/
void USART3_IRQHandler(void)
{
UartIRQ(&g_tUart3);
}
/****************************************************************************
* 函数名: UartGetChar
* 功 能: 从串口接收缓冲区读取n字节数据
* 输 入: _pUart: 串口结构体指针
* 输 出: 无
* 返 回: 1表示正确,0表示无数据
*/
static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte)
{
uint16_t usRxWrite;
CPU_IntDis();
usRxWrite = _pUart->usRxWrite;
CPU_IntEn();
if (_pUart->usRxRead == usRxWrite)
{
return 0;
}
else
{
*_pByte = _pUart->pRxBuf[_pUart->usRxRead];
CPU_IntDis();
if (++_pUart->usRxRead >= _pUart->usRxBufSize)
{
_pUart->usRxRead = 0;
}
CPU_IntEn();
return 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -