LPC1768 串口DMA

2019-07-15 09:10发布

小弟我最近想实现串口用DMA 发送数据 手里只有一分官方DMA 的事例,对于有些地方实在不理解,萌新也没有师傅带,希望论坛大哥多带带
硬件平台 LPC1768
软件平台:keil4

串口0用DMA发送数据
下附部分代码,完整代码在后面
/*-------------------------MAIN FUNCtiON------------------------------*/
/*********************************************************************//**
* @brief                c_entry: Main UART program body
* @param[in]        None
* @Return                 int
**********************************************************************/
int c_entry(void)
{
        uint8_t *rx_char;
        uint32_t idx;
        // UART Configuration structure variable
        UART_CFG_Type UARTConfigStruct;
        // UART FIFO configuration Struct variable
        UART_FIFO_CFG_Type UARTFIFOConfigStruct;
        GPDMA_Channel_CFG_Type GPDMACfg;
        // Pin configuration for UART0
        PINSEL_CFG_Type PinCfg;

        /*
         * Initialize UART0 pin connect
         */
        PinCfg.Funcnum = 1;
        PinCfg.OpenDrain = 0;
        PinCfg.Pinmode = 0;
        PinCfg.Pinnum = 2;
        PinCfg.Portnum = 0;
        PINSEL_ConfigPin(&PinCfg);
        PinCfg.Pinnum = 3;
        PINSEL_ConfigPin(&PinCfg);

        /* Initialize UART Configuration parameter structure to default state:
         * Baudrate = 9600bps
         * 8 data bit
         * 1 Stop bit
         * None parity
         */
        UART_ConfigStructInit(&UARTConfigStruct);

        // Initialize UART0 peripheral with given to corresponding parameter
        UART_Init(LPC_UART0, &UARTConfigStruct);


        /* Initialize FIFOConfigStruct to default state:
         *                                 - FIFO_DMAMode = DISABLE
         *                                 - FIFO_Level = UART_FIFO_TRGLEV0
         *                                 - FIFO_ResetRxBuf = ENABLE
         *                                 - FIFO_ResetTxBuf = ENABLE
         *                                 - FIFO_State = ENABLE
         */
        UART_FIFOConfigStructInit(&UARTFIFOConfigStruct);

        // Enable DMA mode in UART
        UARTFIFOConfigStruct.FIFO_DMAMode = ENABLE;

        // Initialize FIFO for UART0 peripheral
        UART_FIFOConfig(LPC_UART0, &UARTFIFOConfigStruct);

        // Enable UART Transmit
        UART_TxCmd(LPC_UART0, ENABLE);


        /* GPDMA Interrupt configuration section ------------------------------------------------- */

    /* Initialize GPDMA controller */
        GPDMA_Init();


        /* Setting GPDMA interrupt */
    // Disable interrupt for DMA
    NVIC_DisableIRQ (DMA_IRQn);
    /* preemption = 1, sub-priority = 1 */
    NVIC_SetPriority(DMA_IRQn, ((0x01<<3)|0x01));


        // Setup GPDMA channel --------------------------------
        // channel 0
        GPDMACfg.ChannelNum = 0;
        // Source memory
        GPDMACfg.SrcMemAddr = (uint32_t) &menu1;
        // Destination memory - don't care
        GPDMACfg.DstMemAddr = 0;
        // Transfer size
        GPDMACfg.TransferSize = sizeof(menu1);
        // Transfer width - don't care
        GPDMACfg.TransferWidth = 0;
        // Transfer type
        GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
        // Source connection - don't care
        GPDMACfg.SrcConn = 0;
        // Destination connection
        GPDMACfg.DstConn = GPDMA_CONN_UART0_Tx;
        // Linker List Item - unused
        GPDMACfg.DMALLI = 0;
        // Setup channel with given parameter
        GPDMA_Setup(&GPDMACfg);

        // Setup GPDMA channel --------------------------------
        // channel 1
        GPDMACfg.ChannelNum = 1;
        // Source memory - don't care
        GPDMACfg.SrcMemAddr = 0;
        // Destination memory
        GPDMACfg.DstMemAddr = (uint32_t) &rx_buf;
        // Transfer size
        GPDMACfg.TransferSize = sizeof(rx_buf);
        // Transfer width - don't care
        GPDMACfg.TransferWidth = 0;
        // Transfer type
        GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_P2M;
        // Source connection
        GPDMACfg.SrcConn = GPDMA_CONN_UART0_Rx;
        // Destination connection - don't care
        GPDMACfg.DstConn = 0;
        // Linker List Item - unused
        GPDMACfg.DMALLI = 0;
        GPDMA_Setup(&GPDMACfg);

        /* Reset terminal counter */
        Channel0_TC = 0;
        /* Reset Error counter */
        Channel0_Err = 0;

    // Enable interrupt for DMA
    NVIC_EnableIRQ (DMA_IRQn);

        // Enable GPDMA channel 0
        GPDMA_ChannelCmd(0, ENABLE);
        // Make sure GPDMA channel 1 is disabled
        GPDMA_ChannelCmd(1, DISABLE);

//==上面常规串口配置初始化,DMA 配置通道配置初始化都没有问题,都能看懂



        /* Wait for GPDMA on UART0 Tx processing complete */
    while ((Channel0_TC == 0) && (Channel0_Err == 0));
//==注释是等待UART9 TX 处理完成,不是很明白  Channel0_TC 为什么要等于0才是正确处理完成 ,
//==如何多次用串口发送,

    // Main loop - echos back to the terminal
//==后面是很串口0收到的数据回显 也没问题
    while (1)
    {
            /* Reset terminal counter */
            Channel1_TC = 0;
            /* Reset Error counter */
            Channel1_Err = 0;

            // Setup channel with given parameter
            GPDMA_Setup(&GPDMACfg);

            // Enable GPDMA channel 1
            GPDMA_ChannelCmd(1, ENABLE);

            // Clear Rx buffer using DMA
            for (idx = 0; idx < RX_BUF_SIZE; idx++){
                    rx_buf[idx] = 0;
            }

        // now, start receive character using GPDMA
        rx_char = (uint8_t *) &rx_buf;
        while ((Channel1_TC == 0) && (Channel1_Err == 0)){
                        // Check whether if there's any character received, then print it back
                        if (*rx_char != 0)
                        {
                                UART_Send(LPC_UART0, rx_char, 1, BLOCKING);
                                rx_char++;
                        }
        }
    }
}

关于中断找了很多 都没有这方面的资料 主要就是为什么要
Channel0_TC++;
GPDMA_ChannelCmd(0, DISABLE);

如果判断是终端计数器 为要要Channel0_TC++;并且还要关闭DMA 通道

/*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
/*********************************************************************//**
* @brief                GPDMA interrupt handler sub-routine
* @param[in]        None
* @return                 None
**********************************************************************/
void DMA_IRQHandler (void)
{
        uint32_t tmp;
                // Scan interrupt pending
        for (tmp = 0; tmp <= 7; tmp++) {
                if (GPDMA_IntGetStatus(GPDMA_STAT_INT, tmp)){
                        // Check counter terminal status
                        if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, tmp)){
                                // Clear terminate counter Interrupt pending
                                GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, tmp);

                                switch (tmp){
                                        case 0:
                                                Channel0_TC++;
                                                GPDMA_ChannelCmd(0, DISABLE);
                                                break;
                                        case 1:
                                                Channel1_TC++;
                                                GPDMA_ChannelCmd(1, DISABLE);
                                                break;
                                        default:
                                                break;
                                }

                        }
                                // Check error terminal status
                        if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, tmp)){
                                // Clear error counter Interrupt pending
                                GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, tmp);
                                switch (tmp){
                                        case 0:
                                                Channel0_Err++;
                                                GPDMA_ChannelCmd(0, DISABLE);
                                                break;
                                        case 1:
                                                Channel1_Err++;
                                                GPDMA_ChannelCmd(1, DISABLE);
                                                break;
                                        default:
                                                break;
                                }
                        }
                }
        }
}





补充内容 (2017-12-13 20:04):
也没人回答 我后来自己调试出来 中间出个低级错误 C语言基本错误

补充内容 (2017-12-13 20:06):
while ((Channel1_TC == 0) && (Channel1_Err == 0)) 我当时不知道为什么 进入了思维误区  DMA传送完成进入中断 Channel1_TC++,while ((Channel1_TC == 0) && (Channel1_Err == 0)) 是等待传送完成

补充内容 (2017-12-13 20:10):
如果要继续发送数据 因为DMA传输数据长度的寄存器值是更新的,。所以要重新配置 GPDMACfg.TransferSize,并且一定要关闭DMA通道,中断中完成DMA传输后自动关闭中断,所以后面要继续发送数据 先判断是一次是否发送完成 然后 重新给GPDMACfg.TransferSize赋值, GPDMA_Setup(&GPDMACfg);    GPDMA_ChannelCmd(0, ENABLE);
DMA.rar 下载积分: 积分 -1 分
30.58 KB, 下载次数: 30, 下载积分: 积分 -1 分
0条回答

一周热门 更多>