搜索
bottom↓
回复: 14

求助:KL25+UART1+DMA

[复制链接]

出0入0汤圆

发表于 2015-2-11 15:29:23 | 显示全部楼层 |阅读模式
Freesclae KL25黑色的那块开发板
用UART0可以实现DMA方式的发送
但是UART1不行,请问在设置UART0和UART1的时候有什么不同点呢?
下面是代码,请大神帮忙看一下

//====================UART初始化===============================
if (COM1==comX)
        {
#ifndef USE_UART1_DMA_FT
            ASSERT(0);
#endif            
            // Enable Uart1 Clock
            SIM_SCGC4 |= SIM_SCGC4_UART1_MASK;
            SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
            
            if (PTE0 == UART1_TX_PORT)
            {// Enable the UART_TXD function on PTE0
                PORTE_PCR0 = PORT_PCR_MUX(0x3);
            }
            if (PTE1 == UART1_RX_PORT)
            {// Enable the UART_RXD function on PTE1
                PORTE_PCR1 = PORT_PCR_MUX(0x3);
            }
        }
        else
        {
#ifndef USE_UART2_DMA_FT
            ASSERT(0);
#endif            
            // Enable Uart2 Clock
            SIM_SCGC4 |= SIM_SCGC4_UART2_MASK;
            SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
            
            if (PTD3 == UART2_TX_PORT)
            {// Enable the UART_TXD function on PTD3
                PORTD_PCR3 = PORT_PCR_MUX(0x3);
            }
            if (PTD2 == UART2_RX_PORT)
            {// Enable the UART_RXD function on PTD2
                PORTD_PCR2 = PORT_PCR_MUX(0x3);
            }
        }

        // Diable Uart1 Tx Rx
        UART_C2_REG(m_uart_arr[comX]) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK);
        // Configure the uart for 8-bit mode, no parity
        UART_C1_REG(m_uart_arr[comX]) = 0x00;

        // Baundrate setting
        l_sbr = (uint16_t)((periph_clk_khz*1000)/(boundRate * 16));
        l_temp = UART_BDH_REG(m_uart_arr[comX]) & ~(UART_BDH_SBR(0x1F));
        UART_BDH_REG(m_uart_arr[comX]) = l_temp |  UART_BDH_SBR(((l_sbr & 0x1F00) >> 8));
        UART_BDL_REG(m_uart_arr[comX]) = (uint8_t)(l_sbr & UART_BDL_SBR_MASK);
        
        // Enable RX,IDLE Interrupt
        UART_C2_REG(m_uart_arr[comX]) |= UART_C2_ILIE_MASK | UART_C2_RIE_MASK;
        // Enable Uart1 DMA
        UART_C4_REG(m_uart_arr[comX]) |= UART_C4_TDMAS_MASK;
        enable_irq(UART0SE_irq_no+comX);
        // Enable Tx & Rx
        UART_C2_REG(m_uart_arr[comX]) |= (UART_C2_TE_MASK | UART_C2_RE_MASK);
//====================UART初始化===============================

//====================DMA初始化===============================
static void dma_init(Uart_Com_Typedef comX)
{
    ASSERT(IS_UART_COM(comX));

    // Enable dma clock
    SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
    SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;
    // Config DMA Mux for UART operation
    // Disable DMA Mux channel
    DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR, comX) &= ~DMAMUX_CHCFG_ENBL_MASK;
      
    // Clear pending errors and/or the done bit
    if (((DMA_DSR_BCR_REG(DMA_BASE_PTR, comX) & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
       || ((DMA_DSR_BCR_REG(DMA_BASE_PTR, comX) & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
       || ((DMA_DSR_BCR_REG(DMA_BASE_PTR, comX) & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
       || ((DMA_DSR_BCR_REG(DMA_BASE_PTR, comX) & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))
    {
        DMA_DSR_BCR_REG(DMA_BASE_PTR, comX) |= DMA_DSR_BCR_DONE_MASK;
    }

    // Clear Source size and Destination size fields.  
    DMA_DCR_REG(DMA_BASE_PTR,comX) &= ~(DMA_DCR_SSIZE_MASK
                | DMA_DCR_DSIZE_MASK
                );

    // Set DMA as follows:
    //     Source size is byte size
    //     Destination size is byte size
    //     D_REQ cleared automatically by hardware
    //     Destination address will be incremented after each transfer
    //     Cycle Steal mode
    //     External Requests are enabled
    //     Asynchronous DMA requests are enabled.
    //     Enable DMA Interrupt
    DMA_DCR_REG(DMA_BASE_PTR,comX)|= (
                 DMA_DCR_SSIZE(1)
               | DMA_DCR_DSIZE(1)
               | DMA_DCR_SINC_MASK
               | DMA_DCR_CS_MASK
          //     | DMA_DCR_ERQ_MASK
               | DMA_DCR_EINT_MASK
               );
   
    // Set destination Address (this is the UARTx_D register)
    if (COM0==comX)
    {
        DMA_DAR_REG(DMA_BASE_PTR,comX) = UART0_D_ADDRESS;
    }
    else if (COM1==comX)
    {
        DMA_DAR_REG(DMA_BASE_PTR,comX) = UART1_D_ADDRESS;
    }
    else
    {
        DMA_DAR_REG(DMA_BASE_PTR,comX) = UART2_D_ADDRESS;
    }

    // Set source address
    DMA_SAR_REG(DMA_BASE_PTR,comX) = (uint32_t)&(m_uart_tx_buf[comX][0]);

    // Select the DMA Channel Source  
    DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR,comX) = 0x03+2*comX;
    DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR,comX) |= DMAMUX_CHCFG_ENBL_MASK;

    // Enable DMA interrupt
    enable_irq(DMA0_irq_no+comX);
}
//=================DMA初始化==================================

//=================发送==============================
uint8_t uart_send_data(Uart_Com_Typedef comX, uint8_t *pData, uint32_t len)
{
    uint32_t i=0;
   
    ASSERT(IS_UART_COM(comX) && pData && len>0 && len<UART_TXBUF_SIZE);

    m_transmit_complete_flag[comX] = 0;

    // Set BCR to know how many bytes to transfer
    DMA_DSR_BCR(comX) = DMA_DSR_BCR_BCR(len);

    memset(m_uart_tx_buf[comX], 0x00, sizeof(m_uart_tx_buf[comX]));
    memcpy(m_uart_tx_buf[comX], pData, len);

    // Enables the DMA channel
    //DMAMUX_CHCFG_REG(DMAMUX0_BASE_PTR, comX) |= DMAMUX_CHCFG_ENBL_MASK;
    DMA_DCR_REG(DMA_BASE_PTR,comX) |= DMA_DCR_ERQ_MASK;

    while (i++<0xffffff && !m_transmit_complete_flag[comX]);

    if (m_transmit_complete_flag[comX])
    {
        return len;
    }
   
    return 0;
}
//==========================================================

//================DMA中断======================================
void DMA1_IRQHandler(void)
{
    // Clear pending errors or the done bit
    if (((DMA_DSR_BCR1 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
       || ((DMA_DSR_BCR1 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
       || ((DMA_DSR_BCR1 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
       || ((DMA_DSR_BCR1 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))
    {
        // Enable DMA1
        DMA_DCR_REG(DMA_BASE_PTR,COM1) &= ~DMA_DCR_ERQ_MASK;
        // Set source address
        DMA_SAR_REG(DMA_BASE_PTR,COM1) = (uint32_t)&(m_uart_tx_buf[COM1][0]);
        DMA_DSR_BCR1 |= DMA_DSR_BCR_DONE_MASK;
    }
   
    // Set transmit ok flag
    m_transmit_complete_flag[COM1] = 1;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

 楼主| 发表于 2015-2-11 15:55:38 | 显示全部楼层
自己解答了。需要将UART1的发送中断也开启了,详解Uart1_C4寄存器的配置TDMAS的配置。

D7(TDMAS)—发送器DMA选择。如果TIE①被置位,TDMAS将配置发送数据寄存器空标志位(TDRE②)来形成中断或者DMA请求。说明:如果UART_C2[TIE]被清零,那TDRE DMA和TDRE中断信号在TDRE标志置位时无效,并且无视TDMAS的状态。如果TIE和TDMAS同时被置位,然后UART_C2[TCIE]必须被清零。并且UART_D在服务一个DMA请求时不能被写入。TDMAS=0,如果TIE和TDRE标志位被置位,TDRE中断信号触发中断服务例程;TDMAS=1,如果TIE被置位而且TDRE标志位被置位,TDRE DMA请求信号将会请求一个DMA传输器。

出0入0汤圆

发表于 2015-2-11 16:57:08 | 显示全部楼层
Michael_STM 发表于 2015-2-11 15:55
自己解答了。需要将UART1的发送中断也开启了,详解Uart1_C4寄存器的配置TDMAS的配置。

D7(TDMAS)—发送 ...

官方应该有DMA的例程和应用手册

出0入0汤圆

发表于 2015-2-12 07:56:19 | 显示全部楼层
Michael_STM 发表于 2015-2-11 15:55
自己解答了。需要将UART1的发送中断也开启了,详解Uart1_C4寄存器的配置TDMAS的配置。

D7(TDMAS)—发送 ...

按你的说法更改后,程序正常了 ?

出0入0汤圆

发表于 2015-2-12 08:48:08 | 显示全部楼层
Michael_STM 发表于 2015-2-11 15:55
自己解答了。需要将UART1的发送中断也开启了,详解Uart1_C4寄存器的配置TDMAS的配置。

D7(TDMAS)—发送 ...

LZ是不是两个串口都能用, 就是UART1的设置 比起UAR0有个不同?

出0入0汤圆

发表于 2015-2-12 11:14:06 | 显示全部楼层
mcucow 发表于 2015-2-12 08:48
LZ是不是两个串口都能用, 就是UART1的设置 比起UAR0有个不同?

因为UART0和UAR1还是有些区别,包括寄存器的内容,所以在做DMA的时候,需要认真读UART1的寄存器描述。

出0入0汤圆

发表于 2015-2-12 17:15:01 | 显示全部楼层
2人串口还有不同,记下先

出0入0汤圆

 楼主| 发表于 2015-2-13 09:14:22 | 显示全部楼层
holts2 发表于 2015-2-12 07:56
按你的说法更改后,程序正常了 ?

正常了,大家还是要好好参考官方给的参考手册!

出0入0汤圆

 楼主| 发表于 2015-2-13 09:15:48 | 显示全部楼层
mcucow 发表于 2015-2-12 08:48
LZ是不是两个串口都能用, 就是UART1的设置 比起UAR0有个不同?

UART0和UART1都能正常用,UART2没有试过,应该也是可以的,KL25的DMA最多能支持4路

出0入0汤圆

发表于 2015-2-13 12:08:10 | 显示全部楼层
Michael_STM 发表于 2015-2-13 09:14
正常了,大家还是要好好参考官方给的参考手册!

是的,能否上传份正常的代码

出0入0汤圆

发表于 2015-2-13 19:29:53 | 显示全部楼层
难道在DMA期间CPU就可以干别的事了?不是DMA一直在等待么?
还有 像MODBUS 这种 感觉用DMA不太合适。。。

出0入0汤圆

 楼主| 发表于 2015-2-15 11:40:09 | 显示全部楼层
@10楼
在UART1/UART2使用DMA发送初始化的时候加上
// Enable UART TX Interrupt
UART_C2_REG(m_uart_arr[comX]) |= UART_C2_TIE_MASK;
@11楼
MODBUS是一种国际通用的协议,跟不用DMA没啥关系,个人认为串口之使用DMA最常用的情况是数据的频繁交互,用于解放CPU

出0入8汤圆

发表于 2015-2-17 15:19:48 来自手机 | 显示全部楼层
modbus要做就要做通用嘛!用普通的方法最好了,实在是实时性很高的东西,可以用modbus!

出0入8汤圆

发表于 2015-2-17 15:20:57 来自手机 | 显示全部楼层
谁错了,是实时性很高的地方可以用dma

出0入0汤圆

发表于 2015-2-17 15:31:51 | 显示全部楼层
mtswz.213 发表于 2015-2-17 15:20
谁错了,是实时性很高的地方可以用dma

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

本版积分规则

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

GMT+8, 2024-10-2 21:14

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

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