串口接收流程:
串口接收的一部分流程与发送时的配置很类似,具体如下所示:
其中第六步使能的是接收器,第七步是接收中断的使能位,接收中断即在接收到数据后通过产生中断来进行相应的处理。
具体配置过程:
首先:调用HAL_UART_Init函数
然后:HAL_UART_Receive_IT函数开启接收中断
当串口接收到数据时:
1.USARTx_ISR的RXNE位置1。表明以为寄存器的内容已经传输到RDR寄存器。已经接收到数据并且等待读取。
2.如果开启了接收数据中断,则会产生中断,程序上会执行中断服务函数。
3.读取USARTx_RDR寄存器的值,该操作会自动将RXNE位清零,等待下次接收后置位。
具体配置过程:
首先:利用HAL_UART_GET_FLAG 标志位或者使用_HAL_UART_GET_IT_SOURCE判断中断标志位。
然后:进入中断服务函数USART_IRQHandler();
最后:利用HAL_UART_Receive函数读取接收数据。
最后,对于配置过程再来一个最后总结,如下图所示:
但在实际应用中,我们通常会在中断服务函数中调用,HAL库中的HAL_UART_IRQHandler即通用中断服务函数来进行操作。然后通用中断服务函数会判断中断的类型从而再次调用不同的函数来处理中断。具体过程如下图所示:
举个具体一点的例子如下图所示:
有一点需要注意,HAL_UART_Receive_IT函数在调用回调函数之前,会把接收中断关闭,如再次需要利用中断,则需要再次调用HAL_UART_Receive_IT函数把中断打开。
下面举一个程序的例子来巩固以上的知识:
u8 rdata[1];
UART_HandleTypeDef usart1_handler; //UART句柄
void uart1_init()
{
usart1_handler.Instance=USART1; //USART1
usart1_handler.Init.BaudRate=115200; //波特率
usart1_handler.Init.WordLength=UART_WORDLENGTH_8B; //字长
usart1_handler.Init.StopBits=UART_STOPBITS_1; //停止位
usart1_handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验
usart1_handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
usart1_handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&usart1_handler); //HAL_UART_Init()会使能UART1
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)//如果是串口1,进行串口1MSP初始化
{
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟
GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速
GPIO_Initure.Alternate=GPIO_AF7_USART1; //复用为USART1
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10
HAL_NVIC_EnableIRQ(USART1_IRQn); //使能中断通道USART1
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //设置优先级
}
}
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&usart1_handler);
while (HAL_UART_GetState(&usart1_handler) != HAL_UART_STATE_READY);//等待就绪
while(HAL_UART_Receive_IT(&usart1_handler, (u8 *)rdata, 1) != HAL_OK);//在HAL_UART_Receive_IT中调用HAL_UART_RxCpltCallback函数之前会关闭中断,需再次调用HAL_UART_Receive_IT打开中断。
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
u8 rec;
if(huart->Instance==USART1)//如果是串口1
{
rec=*(--(huart->pRxBuffPtr));
HAL_UART_Transmit(&usart1_handler,&rec,1,1000);
}
}
int main(void)
{
Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz
delay_init(216);
uart1_init();//初始化串口参数
HAL_UART_Receive_IT(&usart1_handler, (u8 *)rdata, 1);//打开中断并且设置接收缓冲及其接收最大数据量
while(1)
{
}
) { }