搜索
bottom↓
回复: 11

请教 关于 TK499 UART1 空闲中断 DMA 传输数据问题

[复制链接]

出0入0汤圆

发表于 2021-1-23 15:12:40 | 显示全部楼层 |阅读模式
利用UART1 的空闲中断接收不定长数据包    目前遇到的问题:DMA 能接收到串口的数据,但是无法进入串口的空闲中断。



void Dma_uart_Txinit(void)
{

    DMA_InitTypeDef DMA_InitStructure;

    DMA_Cmd(UART1_Txchannel, DISABLE);                           // 关DMA通道
    DMA_DeInit(UART1_Txchannel);                                 // 恢复缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&UART1->TDR);// 设置串口发送数据寄存器
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)U1_Txbuf;         // 设置发送缓冲区首地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                      // 设置外设位目标,内存缓冲区 -> 外设寄存器
    DMA_InitStructure.DMA_BufferSize = USART1_TX_BSIZE;                     // 需要发送的字节数,这里其实可以设置为0,因为在实际要发送的时候,会重新设置次值
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址不做增加调整,调整不调整是DMA自动实现的
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 // 内存缓冲区地址增加调整
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         // 内存数据宽度8位,1个字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           // 单次传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                 // 优先级设置
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 关闭内存到内存的DMA模式
    DMA_Init(UART1_Txchannel, &DMA_InitStructure);               // 写入配置
    DMA_ClearFlag(UART1_Tx_DMA_FLAG);                                 // 清除DMA所有标志
        DMA_Cmd(UART1_Txchannel, DISABLE); // 关闭DMA
//    DMA_ITConfig(UART1_Txchannel, DMA_IT_TC, ENABLE);            // 开启发送DMA通道中断

}

void Dma_uart_Rxinit(void)
{   
        DMA_InitTypeDef DMA_InitStructure;
    DMA_Cmd(UART1_Rx_DMA_Channel, DISABLE);                           // 关DMA通道
    DMA_DeInit(UART1_Rx_DMA_Channel);                                 // 恢复缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&UART1->RDR);// 设置串口接收数据寄存器
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)U1_Rxbuf;         // 设置接收缓冲区首地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                      // 设置外设为数据源,外设寄存器 -> 内存缓冲区
    DMA_InitStructure.DMA_BufferSize = USART1_RX_BSIZE;                     // 需要最大可能接收到的字节数
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址不做增加调整,调整不调整是DMA自动实现的
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 // 内存缓冲区地址增加调整
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         // 内存数据宽度8位,1个字节
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           // 单次传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                 // 优先级设置
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 关闭内存到内存的DMA模式
    DMA_Init(UART1_Rx_DMA_Channel, &DMA_InitStructure);               // 写入配置
    DMA_ClearFlag(UART1_Rx_DMA_FLAG);                                 // 清除DMA所有标志
    DMA_Cmd(UART1_Rx_DMA_Channel, ENABLE);                            // 开启接收DMA通道,等待接收数据

//    DMA_ITConfig(UART1_Rx_DMA_Channel, DMA_IT_TC, ENABLE);            // 开启接收DMA通道中断


}


void Dma_uart_init(void)
{          
   
    /* DMA clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); // 开启DMA1时钟
   
   Dma_uart_Txinit();
   Dma_uart_Rxinit();
   
   UART_DMACmd(UART1, UART_DMAReq_EN, ENABLE);                                          // 开启串口DMA

}

void UartInit(UART_TypeDef* UARTx,int BaudRate)
{
        UART_InitTypeDef       UART_InitStructure;  
        GPIO_InitTypeDef  GPIO_InitStructure;   

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_9;   //uart1_tx  pa9
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;  //uart1_rx  pa10
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入   

        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_PinAFConfig(GPIOA, GPIO_Pin_9 | GPIO_Pin_10, GPIO_AF_UART_1); //PA9、PA10复用为串口1


        RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);
        UART_InitStructure.UART_BaudRate = BaudRate; //波特率
        UART_InitStructure.UART_WordLength = UART_WordLength_8b;//数据位
        UART_InitStructure.UART_StopBits = UART_StopBits_1;//停止位
        UART_InitStructure.UART_Parity = UART_Parity_No ;
        UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;//输入输出模式
        UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;        
        UART_Init(UARTx, &UART_InitStructure);
       
//        UART_ITConfig(UARTx, UART_IT_RXIEN, ENABLE);//使能接收中断
//        UART_ITConfig(UARTx, UART_IT_TXIEN, ENABLE);//使能接收中断
       

    Dma_uart_init();


        UARTx->IER = 1<<6;   //串口中断
        UARTx->IER |= 1<<1; //帧中断,= 空闲中断?
       
        UART1->ICR|= 0XFF; // 清标志为

        UART_Cmd(UARTx, ENABLE);  //UART 模块使能
       
        NVIC_SetPriority(UART1_IRQn,2);
        NVIC_EnableIRQ(UART1_IRQn);
               
               
//        NVIC_SetPriority(DMA2_Channel3_IRQn,3);
//        NVIC_EnableIRQ(DMA2_Channel3_IRQn);
               
               
        NVIC_SetPriority(DMA2_Channel8_IRQn,3);
        NVIC_EnableIRQ(DMA2_Channel8_IRQn);
               
               
               
               
               
               
//        Dma_uart_init();       
               
               
}

//
void UART1_IRQHandler(void)
{
   if(UART1->ISR & (1<<1))
         {     rxnum++;
//                  UART1->RDR = Uart1_Receive();
              UART1->ICR |= 1<<1;
//                  printf("UART1_RDR = %d\n",UART1->RDR);
         }
//         UART1->ICR = 0XFF;
   if(UART1->ISR & (1<<6))
         {
                 rxnum--;
                 
                Uart1_DMA_Rx_Data();
//                 Dma_uart_Rxinit();
                UART1->ICR=0XFF;

         }
       


       
       
//                LCD_BL(txmod);
//                txmod^=1;

       
}



G0YNUH2I6OI{OE[2K71BD52.png

出0入0汤圆

发表于 2021-1-23 20:05:55 | 显示全部楼层
UART_ITConfig(UARTx, USART_IT_IDLE, ENABLE);中断配置函数中,没有USART_IT_IDLE这个参数吗?
ST的库是有的,您这个我不知道

出0入0汤圆

 楼主| 发表于 2021-1-23 20:12:56 | 显示全部楼层
go2deathward 发表于 2021-1-23 20:05
UART_ITConfig(UARTx, USART_IT_IDLE, ENABLE);中断配置函数中,没有USART_IT_IDLE这个参数吗?
ST的库是有 ...

没有USART_IT_IDLE这个参数

出0入0汤圆

发表于 2021-1-23 22:39:28 | 显示全部楼层
luorenxuan1983 发表于 2021-1-23 20:12
没有USART_IT_IDLE这个参数

你手册截图不全,看那几个标志,都不像是idle中断呢

出0入143汤圆

发表于 2021-1-24 00:44:02 | 显示全部楼层
可以参考一下评估板的资料集里面的第23号例程,在驱动ESP8266  WIFI模块时,工程师用了空闲中断,是用定时器实现的,很简单易懂,你可以打开参考一下:https://www.amobbs.com/forum.php ... ;extra=#pid10937225

出0入0汤圆

 楼主| 发表于 2021-1-24 14:05:34 | 显示全部楼层
go2deathward 发表于 2021-1-23 22:39
你手册截图不全,看那几个标志,都不像是idle中断呢

第6 位 RXRKEN        :UART接收断开帧中断使能位,

我的理解 这个就和 ST 的空闲中断一个意思,不知道对不对

出0入0汤圆

 楼主| 发表于 2021-1-24 14:15:09 | 显示全部楼层
tiky 发表于 2021-1-24 00:44
可以参考一下评估板的资料集里面的第23号例程,在驱动ESP8266  WIFI模块时,工程师用了空闲中断,是用定时 ...

我看过 代码 :
串口 2 接收中断 ,定时器 8 判段 一帧数据接收完成,这样肯定是可以的,以前用51 单片机的时候基本都是用这个思路 做,并且如果波特率变化需要调整定时器参数。
需要多占用一个定时器,我是希望尽量少占用芯片资源。

void UART2_IRQHandler(void)//串口接收中断处理函数,打印出ASCII值
{
        if(UART2->ISR & (1<<1))
        {
                if(Ux_rxdata.Data_count < (Rx_buf_len - 1))
                        Ux_rxdata.Data_rx_buf[Ux_rxdata.Data_count ++] = UART2->RDR;
                uart_time = 0;
                UART2->ICR |= 1<<1;
        }
        TIM_ITConfig(TIM8,TIM_IT_Update,ENABLE ); //使能TIM3中断,允许更新中断
}
void TIM8_IRQHandler(void)
{
        if (TIM_GetITStatus(TIM8, TIM_IT_Update) != RESET)
                {
                        uart_time ++;
                        if(uart_time > 10)
                        {
                                uart_time = 0;
                                Ux_rxdata.Flag = 1;
                                TIM_ITConfig(TIM8,TIM_IT_Update,DISABLE ); //失能TIM3中断,关闭更新中断
                        }
                }
                        TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
}

出0入0汤圆

发表于 2021-1-27 18:11:35 | 显示全部楼层
看硬件有没有提供 idle 的中断了
tk499 的串口 好像是减配的 9位数据都没有
不过内存大 其他功能强啊

出0入0汤圆

发表于 2021-7-16 15:24:59 | 显示全部楼层
我测试dma接收不到数据

出0入0汤圆

发表于 2021-7-16 15:25:37 | 显示全部楼层
yongyelaji 发表于 2021-7-16 15:24
我测试dma接收不到数据

DMA2_Channel3

出0入42汤圆

发表于 2021-7-16 21:22:51 | 显示全部楼层
串口DMA没问题。这片子没有空闲中断,或者种种原因没有开放使用。
总之只能曲线救国了。

出0入0汤圆

发表于 2021-7-19 09:27:14 | 显示全部楼层
jimmy_xt 发表于 2021-7-16 21:22
串口DMA没问题。这片子没有空闲中断,或者种种原因没有开放使用。
总之只能曲线救国了。 ...

老哥可以发一下例程吗
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 09:43

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表