DMA接收選用circle模式,如果是normal模式的話,需要每次在中斷里面接收完成后重新開啟DMA接收,circle模式不用每次都開啟dma接收中斷。如圖
#define UART_BUFFER_SIZE 64
typedef struct _uart_rx_struct{
uint8_t rx_flag;
uint8_t rx_size;
uint8_t buffer[UART_BUFFER_SIZE];
}uart_rx_struct;
uart_rx_struct uart1_rx;
uint8_t uart1_rx_buffer[UART_BUFFER_SIZE];
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中斷
HAL_UART_Receive_DMA(&huart1,uart1_rx_buffer,UART_BUFFER_SIZE);//打開DMA接收,數據存入
}
接收中斷里面按如下所示
void USART1_IRQHandler(void)
{
uint32_t temp;
static uint8_t dma_rx_last_pt=0;
uint8_t rx_len=0;
uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //獲取IDLE標志位
if((tmp_flag != RESET))//idle標志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標志位
temp = hdma_usart1_rx.Instance->NDTR;// 獲取DMA中未傳輸的數據個數,NDTR寄存器分析見下面
if(dma_rx_last_pt > temp)
{
rx_len = dma_rx_last_pt - temp;
for(uint8_t i=0;i<rx_len;i++)
uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
uart1_rx.rx_flag = 1;
uart1_rx.rx_size = rx_len;
}
else
{
rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
for(uint8_t i=0;i<dma_rx_last_pt;i++)
uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
uart1_rx.buffer[dma_rx_last_pt+i] = uart1_rx_buffer[i];
uart1_rx.rx_flag = 1;
uart1_rx.rx_size = rx_len;
}
dma_rx_last_pt = temp;
}
tmp_flag =__HAL_UART_GET_FLAG(&huart1,USART_SR_TC);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
huart1.gState = HAL_UART_STATE_READY;
}
}
STM32F767單片機串口中斷
void UART4_IRQHandler(void)
{
uint32_t temp;
static uint8_t dma_rx_last_pt=0;
uint8_t rx_len=0;
uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE); //獲取IDLE標志
if((tmp_flag != RESET))//idle標志被置
{
__HAL_UART_CLEAR_IDLEFLAG(&huart4);//清除標志
temp = hdma_uart4_rx.Instance->NDTR;// 獲取DMA中未傳輸的數據個數,NDTR寄存器分析見下面
if(dma_rx_last_pt > temp)
{
rx_len = dma_rx_last_pt - temp;
for(uint8_t i=0;i<rx_len;i++)
uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
uart4_rx.rx_flag = 1;
uart4_rx.rx_size = rx_len;
}
else
{
rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
for(uint8_t i=0;i<dma_rx_last_pt;i++)
uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
uart4_rx.buffer[dma_rx_last_pt+i] = uart4_rx_buffer[i];
uart4_rx.rx_flag = 1;
uart4_rx.rx_size = rx_len;
}
dma_rx_last_pt = temp;
}
tmp_flag =__HAL_UART_GET_FLAG(&huart4,USART_ISR_TC);
if((tmp_flag != RESET))
{
__HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
huart4.gState = HAL_UART_STATE_READY;
}
}
void user_Uart1Handler()
{
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))
{
if(uart1RxState==UART_RX_STATE_READY) //接收到一幀中的第一個字節
{
uart1RxState=UART_RX_STATE_START;
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); //打開空閑中斷
uart1RxCounter=0; //計數清零
uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
uart1RxCounter++;
}
else if(uart1RxState==UART_RX_STATE_START)
{
uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
uart1RxCounter++;
}
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
}
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)) //進入空閑中斷
{
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE); //關了空閑中斷
__HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE); //關了接收完成中斷
uart1RxState=UART_RX_STATE_DEAL; //狀態表明一幀數據接收完成了,需要處理。處理完以后再把接收中斷打開
}
}