(一)、uart / usart 要注意的 API使用方法。
1.__HAL_UART_GET_FLAG 是获取 SR 寄存器标志位状态
2.__HAL_UART_CLEAR_FLAG 是清除 SR 寄存器标志位状态,不同于读改写的清零方式,这是直接清零。
3.__HAL_UART_CLEAR_xxFLAG ,xx为PE FE NE ORE IDLE 共5个, 清除方式都是一样的,要先读取SR,再读取DR才能清除对应的标志位
4.UART_Receive_IT或许有bug,tmp = (uint16_t*) huart->pRxBuffPtr;需要pRxBuffPtr十六位对齐,但是pRxBuffPtr类型是uint8_t *,是不一定对齐的。所以在声明buffer的时候要注意声明称16位以上对齐的数据。
5.SR不能用软件置1,一般都是软件清零,通过读改写方式清零会导致中断请求丢失,推荐软件直接写0清除标志。
6.注意UART_FLAG_xx和UART_IT_xx的区别
7.串口发送只能一次,问题在于没有开启TC中断
(二)串口的框图需要理解透
(三)代码如下
接收不定长的数据
/**
* @brief This function handles UART interrupt request.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void user_Uart1Handler(void)
{
if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_RXNE) != RESET) )//接收数据
{
if (uart1RxCounter < 99)
{
uart1RxBuf[uart1RxCounter] =(char)( huart1.Instance->DR & 0xff);
uart1RxCounter++;
}
__HAL_UART_CLEAR_FLAG (&huart1, UART_FLAG_RXNE);
}
if(__HAL_UART_GET_FLAG (&huart1, UART_FLAG_TXE) != RESET) //可以发送下个字节
{
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
}
if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_IDLE) != RESET) ) //接收完一帧数据,空闲标志
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
rx1_cplt = SET;
huart1.RxState = HAL_UART_STATE_READY;
}
if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_TC) != RESET) ) //发送完一帧数据,TC标志
{
__HAL_UART_CLEAR_PEFLAG (&huart1);
__HAL_UART_CLEAR_PEFLAG (&huart1);
huart1.gState = HAL_UART_STATE_READY;
}
{
uint32_t state;
state = __HAL_UART_GET_FLAG (&huart1, UART_FLAG_PE)| __HAL_UART_GET_FLAG (&huart1, UART_FLAG_FE)\
|__HAL_UART_GET_FLAG (&huart1, UART_FLAG_NE)|__HAL_UART_GET_FLAG (&huart1, UART_FLAG_ORE);
if (state != RESET)
{
__HAL_UART_CLEAR_PEFLAG (&huart1);
}
}
if(huart1.ErrorCode != HAL_UART_ERROR_NONE)
{
Error_Handler();
}
}
printf回调 发送单个字节的程序如下,前提是打开dma和中断:
void Uart_PutChar(UART_HandleTypeDef *huart, char ch)
{
if(__HAL_UART_GET_FLAG (huart, UART_FLAG_TXE) != RESET)
{
huart->Instance->DR = (uint16_t)ch & (uint16_t)0x01FF;//每次写DR会清零TXE
while(__HAL_UART_GET_FLAG(huart,UART_FLAG_TXE) != SET)
{
}
}
}
void putchar_uart1_callback(char ch)
{
Uart_PutChar(&huart1,ch);
}
printf回调 ,发送多个字符串的程序如下,前提是打开dma和中断:
void putstring_uart1_callback(char *data, unsigned int size)
{
HAL_UART_Transmit_DMA(&huart1,(uint8_t *)data,size);
}
还要记得在main循环之前,打开相关中断:
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_ERR);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);