【上海航芯 ACM32F070开发板+触控功能评估板】—— UART例程
[复制链接]
1.4. UART例程
UART的通讯方式有LOOP(循环读取UART状态寄存器,并根据状态来读、写数据寄存器)、DMA、INT等方式。并且可以使用ABORT函数来中止传输。
由于开发板上板载的USB转UART功能默认连接的是UART2,因此可以将POLL、DMA两个测试代码修改为UART2,IT方式的例程是UART1、2、3均有,无需修改。
1.4.1. TEST_POLL
采用轮询方式读取UART状态寄存器,然后根据状态(写时数据寄存器空、读时数据寄存器满),进行相应的读写。为方便UART2测试,修改代码如下:
/* 循环模式 */
case TEST_LOOP:
{
for(;;)
{
HAL_UART_Receive(&UART2_Handle, gu8_RxBuffer, sizeof(gu8_RxBuffer), 200);
HAL_UART_Transmit(&UART2_Handle, gu8_RxBuffer, UART2_Handle.lu32_RxCount, 0);
memset(gu8_RxBuffer, 0, sizeof(gu8_RxBuffer));
}
}break;
运行效果如图
在调试界面,可以直接在UART2的寄存器中写入数据,即可看到串口终端显示相应的数据。
1.4.2. TEST_UART2
HAL_UART_Receive_IT函数中,设置各项参数后,调用
/* Enable RX and RTI interrupt */
SET_BIT(huart->Instance->IE,UART_IE_RXI|UART_IE_RTI);
使能UART的接收中断,然后在中断例程中,HAL_UART_IRQHandler完成中断后操作,最终调用HAL_UART_RxCpltCallback,即
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance ==UART1) // receive data by UART1
{
gu32_RxCpltStatus= true;
}
else if(huart->Instance ==UART2) //receive data by UART2
{
gu32_RxCpltStatus2 =true;
}
else if(huart->Instance ==UART3) // receive data by UART3
{
gu32_RxCpltStatus3 =true;
}
}
实现的对标志位的设置,应用程序检测到这个标志位后,进行响应的操作,即:
/* 中断模式 */
case TEST_UART2:
{
while(1)
{
HAL_UART_Receive_IT(&UART2_Handle, gu8_RxBuffer, sizeof(gu8_RxBuffer), UART_RX_FIFO_1_2); // length should <= sizeof(gu8_RxBuffer)
while(1)
{
while (!gu32_RxCpltStatus2);
gu32_RxCpltStatus2=false;
memcpy(gu8_TxBuffer, gu8_RxBuffer, UART2_Handle.lu32_RxCount);
HAL_UART_Transmit_IT(&UART2_Handle, gu8_TxBuffer, UART2_Handle.lu32_RxCount, UART_TX_FIFO_1_2);
while (!gu32_TxCpltStatus2);
gu32_TxCpltStatus2 =false;
break;
}
}
}break;
运行效果如图:
1.4.3. TEST_DMA
UART的DMA模式,相比中断模式,更节省CPU。配置了DMA后,启动DMA传输,DMA自动将数据发送到UART的数据寄存器,当一个UART数据字节发送后,UART自动发送DMA请求到DMA_CH1,DMA控制器根据设置自动递增地址后,获取相应数据并发送到UART,最终完成所有数据发送后,产生一个DMA中断,在DMA中断服务例程中调用UART2_DMA_ITC_Callback函数,该函数设置gu32_DMA_Status标志位,以便下一轮循环。
为调试方便,修改TEST_DMA测试代码为UART2,如下:
/* DMA模式 */
case TEST_DMA:
{
DMA_CH1_Handle.Instance = DMA_Channel0;
DMA_CH1_Handle.Init.Data_Flow = DMA_DATA_FLOW_M2P;
DMA_CH1_Handle.Init.Request_ID = REQ7_UART2_SEND;
DMA_CH1_Handle.Init.Source_Inc = DMA_SOURCE_ADDR_INCREASE_ENABLE;
DMA_CH1_Handle.Init.Desination_Inc = DMA_DST_ADDR_INCREASE_DISABLE;
DMA_CH1_Handle.Init.Source_Width = DMA_SRC_WIDTH_BYTE;
DMA_CH1_Handle.Init.Desination_Width = DMA_DST_WIDTH_BYTE;
DMA_CH1_Handle.DMA_ITC_Callback = UART2_DMA_ITC_Callback;
HAL_DMA_Init(&DMA_CH1_Handle);
__HAL_LINK_DMA(UART2_Handle, HDMA_Tx, DMA_CH1_Handle);
gu32_DMA_Status = true;
for(;;)
{
if (gu32_DMA_Status)
{
gu32_DMA_Status = false;
memset(gu8_RxBuffer, 0, 512);
}
lu8_ret=HAL_UART_Receive(&UART2_Handle, gu8_RxBuffer, sizeof(gu8_RxBuffer), 100);
lu8_ret=HAL_UART_Transmit_DMA(&UART2_Handle, gu8_RxBuffer, UART2_Handle.lu32_RxCount);
}
}break;
运行效果如下:
1.4.4. TEST_ABORT
UART的ABORT函数主要完成对DMA或者INT的取消,对于轮询发送/接收的,则重置其传输计数,并将其busy标志置位为false。代码如下:
/*********************************************************************************
* Function : HAL_UART_Abort
* Description : Abort ongoing transfers(blocking mode)
* Input : UART handle
* Output :
**********************************************************************************/
HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart)
{
#if (USE_FULL_ASSERT == 1)
if (!IS_UART_ALL_INSTANCE(huart->Instance)) return HAL_ERROR;
#endif
/*disble all interrupt*/
huart->Instance->IE =0x00;
/* Disable the UART DMA Tx request if enable */
if(READ_BIT(huart->Instance->DMACR, UART_DMACR_TXDMAE))
{
CLEAR_BIT(huart->Instance->DMACR, UART_DMACR_TXDMAE);
/* Abort the UART Tx Channel */
if(huart->HDMA_Tx)
{
/*Set the UART DMA Abort callback to Null */
huart->HDMA_Tx->DMA_ITC_Callback =NULL;
if(HAL_DMA_Abort(huart->HDMA_Tx)!=HAL_OK)
{
return HAL_TIMEOUT;
}
}
}
/* Disable the UART DMA Rx request if enable */
if(READ_BIT(huart->Instance->DMACR, UART_DMACR_RXDMAE))
{
CLEAR_BIT(huart->Instance->DMACR, UART_DMACR_RXDMAE);
/* Abort the UART Rx Channel */
if(huart->HDMA_Rx)
{
/*Set the UART DMA Abort callback to Null */
huart->HDMA_Rx->DMA_ITC_Callback =NULL;
if(HAL_DMA_Abort(huart->HDMA_Rx)!=HAL_OK)
{
return HAL_TIMEOUT;
}
}
}
/*Reset Tx and Rx Transfer size*/
huart->lu32_TxSize = 0;
huart->lu32_RxSize = 0;
/* Restore huart->lu8_TxBusy and huart->lu8_RxBusy to Ready */
huart->lu8_TxBusy = false;
huart->lu8_RxBusy = false;
return HAL_OK;
}
UART的ABORT函数测试代码和运行效果如下:
对于UART1和UART2,则在板子上用杜邦线连接SWD排针的Target_VCP_RX/Target_VCP_TX到UART1或者UART3的对应的TX/RX引脚(或者用额外的USB转串口模块连接),如图:
对应的运行效果截图:
|