初级会员

- 积分
- 193
- 金钱
- 193
- 注册时间
- 2020-8-16
- 在线时间
- 39 小时
|
5金钱
在进行DMA接收和DMA发送时会出现发送两次的情况,主程序循环用DMA发送收到的数据,没有加延时就会发生发送两次的情况,加入一段时间延时就不会出现,但是开启了DMA的中断服务函数应该是发送完成就会进入中断清零,不明白为什么会发送两次相同的数据
UART_HandleTypeDef g_uart1_handle; /* UART句柄 */
UART_HandleTypeDef g_uart2_handle; /* UART句柄 */
UART_HandleTypeDef g_uart3_handle; /* UART句柄 */
DMA_HandleTypeDef dma1_rx_handle;
DMA_HandleTypeDef dma1_tx_handle;
#if USART1_EN/*如果使能了串口1*/
/* 接收缓冲, 最大USART_REC_LEN个字节. */
uint8_t g_usart1_rx_buf[USART1_REC_LEN];
uint8_t g_usart1_rx_cnt = 0;
void usart1_init(uint32_t baudrate)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_9; /* 串口发送引脚号 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_10; /* 串口RX脚 模式设置 */
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */
/*UART 初始化设置*/
g_uart1_handle.Instance = USART1; /* USART_UX */
g_uart1_handle.Init.BaudRate = baudrate; /* 波特率 */
g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
g_uart1_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
g_uart1_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_uart1_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&g_uart1_handle); /* HAL_UART_Init()会使能UART1 */
#if USART1_EN_RX
__HAL_UART_ENABLE_IT(&g_uart1_handle, UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&g_uart1_handle, UART_IT_RXNE);
HAL_NVIC_EnableIRQ(USART1_IRQn); /* 使能USART1中断通道 */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 1); /* 组2,最低优先级:抢占优先级3,子优先级3 */
#endif
#if USART1_DMA_RX
__HAL_RCC_DMA1_CLK_ENABLE();
dma1_rx_handle.Instance = DMA1_Channel5; //指令基地址
dma1_rx_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
dma1_rx_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//8字节对齐
dma1_rx_handle.Init.MemInc = DMA_MINC_ENABLE;
dma1_rx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//8字节对齐
dma1_rx_handle.Init.PeriphInc = DMA_PINC_DISABLE;
dma1_rx_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
dma1_rx_handle.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&dma1_rx_handle);
__HAL_LINKDMA(&g_uart1_handle,hdmarx,dma1_rx_handle);//在函数中将句柄与dma建立关联
//将uart1_handle的数据保存到串口的缓冲区,串口大小
HAL_UART_Receive_DMA(&g_uart1_handle, g_usart1_rx_buf,USART1_REC_LEN);
#endif
#if USART1_DMA_TX
__HAL_RCC_DMA1_CLK_ENABLE();
dma1_tx_handle.Instance = DMA1_Channel4; /* USART1_TX使用的DMA通道为: DMA1_Channel4 */
dma1_tx_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; /* DIR = 1 , 存储器到外设模式 */
dma1_tx_handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
dma1_tx_handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
dma1_tx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; /* 外设数据长度:8位 */
dma1_tx_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; /* 存储器数据长度:8位 */
dma1_tx_handle.Init.Mode = DMA_NORMAL; /* DMA模式:正常模式 */
dma1_tx_handle.Init.Priority = DMA_PRIORITY_MEDIUM; /* 中等优先级 */
HAL_DMA_Init(&dma1_tx_handle);
__HAL_LINKDMA(&g_uart1_handle,hdmatx,dma1_tx_handle);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn); /* 使能USART1中断通道 */
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 2); /* 组2,最低优先级:抢占优先级3,子优先级3 */
#endif
}
void DMA1_Channel4_IRQHandler(void)
{
if ( __HAL_DMA_GET_FLAG(&dma1_tx_handle, DMA_FLAG_TC4)) /* 等待 DMA1_Channel4 传输完成 */
{
__HAL_DMA_CLEAR_FLAG(&dma1_tx_handle, DMA_FLAG_TC4);
g_usart1_rx_cnt = 0;
HAL_UART_DMAStop(&g_uart1_handle); /* 传输完成以后关闭串口DMA */
HAL_UART_Receive_DMA(&g_uart1_handle,g_usart1_rx_buf,USART1_REC_LEN);
}
}
void USART1_IRQHandler(void)
{
#if SYS_SUPPORT_OS /* 使用OS */
OSIntEnter();
#endif
uint8_t res;
static uint16_t len;
#if USART1_DMA_RX
if ((__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_IDLE) != RESET)) /* 接收到数据 */
{
//清除空闲中断
__HAL_UART_CLEAR_IDLEFLAG(&g_uart1_handle);
//停止DMA传输干扰
HAL_UART_DMAStop(&g_uart1_handle);
//获取接收到的数据长度 当前还有多少个数据没有传输
len = USART1_REC_LEN - __HAL_DMA_GET_COUNTER(&dma1_rx_handle);
//打印接收到的内容
// HAL_UART_Transmit(&g_uart1_handle, g_usart1_rx_buf, len, 1000);
//清空接收缓冲
// memset(g_usart1_rx_buf,0,sizeof(len));
g_usart1_rx_cnt = len;
len = 0;
//重新开启dma传输
//使能串口接收 串口句柄,串口接收的缓冲区,size
HAL_UART_Receive_DMA(&g_uart1_handle,g_usart1_rx_buf,USART1_REC_LEN);
}
#else
if ((__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_RXNE) != RESET)) /* 接收到数据 */
{
HAL_UART_Receive(&g_uart1_handle, &res, 1, 1000);
if (len < USART1_REC_LEN) /* 缓冲区未满 */
{
g_usart1_rx_buf[len] = res; /* 记录接收到的值 */
len++; /* 接收数据增加1 */
}
}
if ((__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_IDLE) != RESET)) /* 接收到数据 */
{
__HAL_UART_CLEAR_IDLEFLAG(&g_uart1_handle); // 清除IDLE中断标志位
HAL_UART_Transmit_DMA(&g_uart1_handle, g_usart1_rx_buf, len);
g_usart1_rx_cnt = len;
len = 0;
}
#endif
#if SYS_SUPPORT_OS /* 使用OS */
OSIntExit();
#endif
}
#endif
主程序就只有while循环发送收到的数据
while(1)
{
HAL_UART_Transmit_DMA(&g_uart1_handle, g_usart1_rx_buf, g_usart1_rx_cnt);
}
|
|