[范例教程]

【M0】 MG32F02A 学习笔记⑦ UART0 DMA 串口接收

[复制链接]
773|0
手机看帖
扫描二维码
随时随地手机跟帖
noctor|  楼主 | 2018-9-27 13:27 | 显示全部楼层 |阅读模式
      上回我们说到了MG32F02A的UART0通过DMA方式进行串口输出。帖子详情:https://bbs.21ic.com/icview-2559020-1-1.html

       串口的通讯是非常常用的,经常被用于蓝牙透传的通道等等那么上次说了串口发送,这次就来说说串口接收了。

       程序如下,这是使用了DMA的方法:


#include "MG32x02z_DRV.H"
#include <stdio.h>

#define URTX URT0
#define MYBINARYIMAGE2_LENGTH 20

uint8_t RcvBuf[MYBINARYIMAGE2_LENGTH]={0};//__attribute__((at(0x20001000)));

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

void CSC_Init (void)
{
        CSC_PLL_TyprDef CSC_PLL_CFG;
   
       
    UnProtectModuleReg(MEMprotect);             // Setting flash wait state
    MEM_SetFlashWaitState(MEM_FWAIT_ONE);        // 50MHz> Sysclk >=25MHz
    ProtectModuleReg(MEMprotect);

    UnProtectModuleReg(CSCprotect);
        CSC_CK_APB_Divider_Select(APB_DIV_1);        // Modify CK_APB divider        APB=CK_MAIN/1
        CSC_CK_AHB_Divider_Select(AHB_DIV_1);        // Modify CK_AHB divider        AHB=APB/1

       
        /* CK_HS selection */
        CSC_IHRCO_Select(IHRCO_12MHz);                        // IHRCO Sel 12MHz
        CSC_IHRCO_Cmd(ENABLE);
        while(CSC_GetSingleFlagStatus(CSC_IHRCOF) == DRV_Normal);
        CSC_ClearFlag(CSC_IHRCOF);
        CSC_CK_HS_Select(HS_CK_IHRCO);                        // CK_HS select IHRCO


        /* PLL */
        /**********************************************************/
        CSC_PLL_CFG.InputDivider=PLLI_DIV_2;        // 12M/2=6M
        CSC_PLL_CFG.Multiplication=PLLIx16;                // 6M*16=96M
        CSC_PLL_CFG.OutputDivider=PLLO_DIV_2;        // PLLO=96M/2=48M
        CSC_PLL_Config(&CSC_PLL_CFG);
        CSC_PLL_Cmd(ENABLE);
        while(CSC_GetSingleFlagStatus(CSC_PLLF) == DRV_Normal);
        CSC_ClearFlag(CSC_PLLF);
        /**********************************************************/

       
        /* CK_MAIN */
        CSC_CK_MAIN_Select(MAIN_CK_HS);       


        /* Configure ICKO function */
               
        /* Configure peripheral clock */
        CSC_PeriphProcessClockSource_Config(CSC_UART0_CKS, CK_APB);
        CSC_PeriphOnModeClock_Config(CSC_ON_UART0,ENABLE);
        CSC_PeriphOnModeClock_Config(CSC_ON_PortB,ENABLE);
        CSC_PeriphOnModeClock_Config(CSC_ON_DMA,ENABLE);

       
    ProtectModuleReg(CSCprotect);
   
}


int fputc(int ch,FILE *f)
{
       
        URT_SetTXData(URTX,1,ch);
        while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
        URT_ClearITFlag(URTX,URT_IT_TC);
       
        return ch;
}

void UartSendByte(int ch)
{
       
        URT_SetTXData(URTX,1,ch);
        while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
        URT_ClearITFlag(URTX,URT_IT_TC);
       
}


void URT0_Init(void)
{
    URT_BRG_TypeDef  URT_BRG;
    URT_Data_TypeDef DataDef;
        PIN_InitTypeDef PINX_InitStruct;
   
        //==Set GPIO init
        //PB8 PPO TX ,PB9 ODO RX
        PINX_InitStruct.PINX_Mode                                 = PINX_Mode_PushPull_O;                  // Pin select Push Pull mode
        PINX_InitStruct.PINX_PUResistant                 = PINX_PUResistant_Enable;          // Enable pull up resistor
        PINX_InitStruct.PINX_Speed                                   = PINX_Speed_Low;                         
        PINX_InitStruct.PINX_OUTDrive                         = PINX_OUTDrive_Level0;                 // Pin output driver full strength.
        PINX_InitStruct.PINX_FilterDivider                   = PINX_FilterDivider_Bypass;        // Pin input deglitch filter clock divider bypass
        PINX_InitStruct.PINX_Inverse                         = PINX_Inverse_Disable;                 // Pin input data not inverse
        PINX_InitStruct.PINX_Alternate_Function  = PB8_AF_URT0_TX;                                // Pin AFS = URT0_TX
        GPIO_PinMode_Config(PINB(8),&PINX_InitStruct);                                                          // TXD at PB8

        PINX_InitStruct.PINX_Mode                                 = PINX_Mode_OpenDrain_O;                 // Pin select Open Drain mode
        PINX_InitStruct.PINX_Alternate_Function  = PB9_AF_URT0_RX;                                // Pin AFS = URT0_RX
        GPIO_PinMode_Config(PINB(9),&PINX_InitStruct);                                                          // RXD at PB9

   
    //=====Set Clock=====//
    //---Set BaudRate---//
    URT_BRG.URT_InteranlClockSource = URT_BDClock_PROC;
    URT_BRG.URT_BaudRateMode = URT_BDMode_Separated;
    URT_BRG.URT_PrescalerCounterReload = 0;                                //Set PSR
    URT_BRG.URT_BaudRateCounterReload = 3;                                //Set RLR
    URT_BaudRateGenerator_Config(URTX, &URT_BRG);                            //BR115200 = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
    URT_BaudRateGenerator_Cmd(URTX, ENABLE);                            //Enable BaudRateGenerator
    //---TX/RX Clock---//
    URT_TXClockSource_Select(URTX, URT_TXClock_Internal);                //URT_TX use BaudRateGenerator
    URT_RXClockSource_Select(URTX, URT_RXClock_Internal);                //URT_RX use BaudRateGenerator
    URT_TXOverSamplingSampleNumber_Select(URTX, 25);                //Set TX OS_NUM
    URT_RXOverSamplingSampleNumber_Select(URTX, 25);                //Set RX OS_NUM
    URT_RXOverSamplingMode_Select(URTX, URT_RXSMP_3TIME);
    URT_TX_Cmd(URTX, ENABLE);                                            //Enable TX
    URT_RX_Cmd(URTX, ENABLE);                                            //Enable RX
   
   

    //=====Set Mode=====//
    //---Set Data character config---//
    DataDef.URT_TX_DataLength  = URT_DataLength_8;
    DataDef.URT_RX_DataLength  = URT_DataLength_8;
    DataDef.URT_TX_DataOrder   = URT_DataTyped_LSB;
    DataDef.URT_RX_DataOrder   = URT_DataTyped_LSB;
    DataDef.URT_TX_Parity      = URT_Parity_No;
    DataDef.URT_RX_Parity      = URT_Parity_No;
    DataDef.URT_TX_StopBits    = URT_StopBits_1_0;
    DataDef.URT_RX_StopBits    = URT_StopBits_1_0;
    DataDef.URT_TX_DataInverse = DISABLE;
    DataDef.URT_RX_DataInverse = DISABLE;
    URT_DataCharacter_Config(URTX, &DataDef);
    //---Set Mode Select---//
    URT_Mode_Select(URTX, URT_URT_mode);
    //---Set DataLine Select---//
    URT_DataLine_Select(URTX, URT_DataLine_2);
   
   
    //=====Set Data Control=====//
    URT_RXShadowBufferThreshold_Select(URTX, URT_RXTH_1BYTE);
    URT_IdlehandleMode_Select(URTX, URT_IDLEMode_No);
    URT_TXGaudTime_Select(URTX, 0);
   
    //=====Enable URT Interrupt=====//
    //URT_IT_Cmd(URTX, URT_IT_RX, ENABLE);
    //URT_ITEA_Cmd(URTX, ENABLE);
    //NVIC_EnableIRQ(URT0_IRQn);

    //=====Enable URT=====//
    URT_Cmd(URTX, ENABLE);
               
        //==See MG32x02z_URT0_IRQ.c when interrupt in
}

void DMA_Init(void)
{
         DMA_BaseInitTypeDef DMATestPattern;

    // ------------------------------------------------------------------------
    // 1.Enable DMA
    DMA_Cmd(ENABLE);
   
    // ------------------------------------------------------------------------
    // 2.Enable Channel0
    DMA_Channel_Cmd(DMAChannel0, ENABLE);
   
    // ------------------------------------------------------------------------
    DMA_BaseInitStructure_Init(&DMATestPattern);
   
    // 3.initial & modify parameter
      
        // DMA channel select
        DMATestPattern.DMAChx = DMAChannel0;
        
        // channel x source/destination auto increase address
        DMATestPattern.SrcSINCSel = DISABLE;
        DMATestPattern.DestDINCSel = ENABLE;
        
        // DMA source peripheral config
        DMATestPattern.SrcSymSel = DMA_URT0_RX;
        
        // DMA destination peripheral config
        DMATestPattern.DestSymSel = DMA_MEM_Write;
        
        // DMA Burst size config
        DMATestPattern.BurstDataSize = DMA_BurstSize_1Byte;
        
        // DMA transfer data count initial number
        DMATestPattern.DMATransferNUM = MYBINARYIMAGE2_LENGTH;
   
        // source/destination config
        DMATestPattern.DMASourceAddr = &URT0->RDAT;
        DMATestPattern.DMADestinationAddr = (uint32_t *)&RcvBuf;

                 URT_RXDMA_Cmd(URT0, ENABLE);
    DMA_Base_Init(&DMATestPattern);
}


int main()
{
        int i;
        CSC_Init();
        URT0_Init();
        printf("Hello!\n");
        DMA_Init();
        DMA_StartRequest(DMAChannel0);
       
                while(1)
        {
                    i++;
            if(i>=100000)
            {
                                i=0;
                                if(RcvBuf[0]!='\0')printf("%s\n",RcvBuf);                       
                                memset(RcvBuf,0,20*sizeof(u8));
                                DMA_Channel_Cmd(DMAChannel0, DISABLE);
                                DMA_SetDestinationAddress(DMAChannel0, RcvBuf);      //重设目标地址以设定好DMA传输目的地的首地址
                                DMA_Channel_Cmd(DMAChannel0, ENABLE);
                                DMA_StartRequest(DMAChannel0);
            }
        }

}


         通过这个程序你会发现,使用DMA进行接收和发送,调用的方法是不一样的,需要区别对待,利用DMA发送需要发送一次就while一次dma传输完成的flag,而接收不需要,但是dma接收上面目前有个不太好的地方,不清楚是自己的程序是否还有点问题,急速dma接收时地址会默认往后增加,因此到了下一次接收时候,可能数据就会跑到接收区数组的后面的元素中去,因此需要接收完成后重新设置目标地址。
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

82

帖子

3

粉丝