[范例教程] 【M0】 MG32F02A 学习笔记⑥ UART0 DMA 串口发送

[复制链接]
 楼主| noctor 发表于 2018-9-25 13:47 | 显示全部楼层 |阅读模式
     上回我们说到了MG32F02A的UART0进行串口输出。帖子详情:https://bbs.21ic.com/icview-2557938-1-1.html

       由于CPU的资源是非常宝贵的,所以我们希望能够不利用CPU资源就进行数据从UART0输出,这时候就需要使用我们的DMA功能了,虽然从代码上看CPU的事情还是有一些,但是如果作为接收方,那么DMA就会非常方便,当然这都是后话了。

       如下程序中为UART0使用DMA方式进行输出。在该程序中,你会发现笙泉M0的DMA使用起来比较方便,不需要选择方向,直接设置DMA起始方和DMA接收方即可,而且笙泉的DMA通道比较简单,只有3个通道,且通道0是全功能通道,所以,只要设置为通道0,你的DMA就一定能用,不需要到处查手册。另外一点需要注意,从内存发送到外设时每发送完一次都会自动关闭外设的DMA使能以避免DMA疯狂传输,所以需要重新启动一次。
  1. #include "MG32x02z_DRV.H"
  2. #include <stdio.h>

  3. #define URTX URT0

  4. #define URTX URT0
  5. #define MYBINARYIMAGE2_LENGTH 20

  6. uint8_t SendBuf[MYBINARYIMAGE2_LENGTH]={1,2,3,4,5,6,7,8,9};//__attribute__((at(0x20001000)));

  7. typedef uint8_t u8;
  8. typedef uint16_t u16;
  9. typedef uint32_t u32;
  10. typedef uint64_t u64;

  11. void CSC_Init (void)
  12. {
  13.         CSC_PLL_TyprDef CSC_PLL_CFG;
  14.    
  15.         
  16.     UnProtectModuleReg(MEMprotect);             // Setting flash wait state
  17.     MEM_SetFlashWaitState(MEM_FWAIT_ONE);        // 50MHz> Sysclk >=25MHz
  18.     ProtectModuleReg(MEMprotect);

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

  22.         
  23.         /* CK_HS selection */
  24.         CSC_IHRCO_Select(IHRCO_12MHz);                        // IHRCO Sel 12MHz
  25.         CSC_IHRCO_Cmd(ENABLE);
  26.         while(CSC_GetSingleFlagStatus(CSC_IHRCOF) == DRV_Normal);
  27.         CSC_ClearFlag(CSC_IHRCOF);
  28.         CSC_CK_HS_Select(HS_CK_IHRCO);                        // CK_HS select IHRCO


  29.         /* PLL */
  30.         /**********************************************************/
  31.         CSC_PLL_CFG.InputDivider=PLLI_DIV_2;        // 12M/2=6M
  32.         CSC_PLL_CFG.Multiplication=PLLIx16;                // 6M*16=96M
  33.         CSC_PLL_CFG.OutputDivider=PLLO_DIV_2;        // PLLO=96M/2=48M
  34.         CSC_PLL_Config(&CSC_PLL_CFG);
  35.         CSC_PLL_Cmd(ENABLE);
  36.         while(CSC_GetSingleFlagStatus(CSC_PLLF) == DRV_Normal);
  37.         CSC_ClearFlag(CSC_PLLF);
  38.         /**********************************************************/

  39.         
  40.         /* CK_MAIN */
  41.         CSC_CK_MAIN_Select(MAIN_CK_HS);        


  42.         /* Configure ICKO function */
  43.                
  44.         /* Configure peripheral clock */
  45.         CSC_PeriphProcessClockSource_Config(CSC_UART0_CKS, CK_APB);
  46.          CSC_PeriphOnModeClock_Config(CSC_ON_UART0,ENABLE);
  47.          CSC_PeriphOnModeClock_Config(CSC_ON_PortB,ENABLE);
  48.         CSC_PeriphOnModeClock_Config(CSC_ON_DMA,ENABLE);

  49.         
  50.     ProtectModuleReg(CSCprotect);
  51.    
  52. }


  53. int fputc(int ch,FILE *f)
  54. {
  55.         
  56.         URT_SetTXData(URTX,1,ch);
  57.         while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
  58.         URT_ClearITFlag(URTX,URT_IT_TC);
  59.         
  60.         return ch;
  61. }

  62. void UartSendByte(int ch)
  63. {
  64.         
  65.         URT_SetTXData(URTX,1,ch);
  66.         while(URT_GetITSingleFlagStatus(URTX,URT_IT_TC)==DRV_UnHappened);
  67.         URT_ClearITFlag(URTX,URT_IT_TC);
  68.         
  69. }


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

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

  89.    
  90.     //=====Set Clock=====//
  91.     //---Set BaudRate---//
  92.     URT_BRG.URT_InteranlClockSource = URT_BDClock_PROC;
  93.     URT_BRG.URT_BaudRateMode = URT_BDMode_Separated;
  94.     URT_BRG.URT_PrescalerCounterReload = 0;                                //Set PSR
  95.     URT_BRG.URT_BaudRateCounterReload = 3;                                //Set RLR
  96.     URT_BaudRateGenerator_Config(URTX, &URT_BRG);                            //BR115200 = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
  97.     URT_BaudRateGenerator_Cmd(URTX, ENABLE);                            //Enable BaudRateGenerator
  98.     //---TX/RX Clock---//
  99.     URT_TXClockSource_Select(URTX, URT_TXClock_Internal);                //URT_TX use BaudRateGenerator
  100.     URT_RXClockSource_Select(URTX, URT_RXClock_Internal);                //URT_RX use BaudRateGenerator
  101.     URT_TXOverSamplingSampleNumber_Select(URTX, 25);                //Set TX OS_NUM
  102.     URT_RXOverSamplingSampleNumber_Select(URTX, 25);                //Set RX OS_NUM
  103.     URT_RXOverSamplingMode_Select(URTX, URT_RXSMP_3TIME);
  104.     URT_TX_Cmd(URTX, ENABLE);                                            //Enable TX
  105.     URT_RX_Cmd(URTX, ENABLE);                                            //Enable RX
  106.    
  107.    

  108.     //=====Set Mode=====//
  109.     //---Set Data character config---//
  110.     DataDef.URT_TX_DataLength  = URT_DataLength_8;
  111.     DataDef.URT_RX_DataLength  = URT_DataLength_8;
  112.     DataDef.URT_TX_DataOrder   = URT_DataTyped_LSB;
  113.     DataDef.URT_RX_DataOrder   = URT_DataTyped_LSB;
  114.     DataDef.URT_TX_Parity      = URT_Parity_No;
  115.     DataDef.URT_RX_Parity      = URT_Parity_No;
  116.     DataDef.URT_TX_StopBits    = URT_StopBits_1_0;
  117.     DataDef.URT_RX_StopBits    = URT_StopBits_1_0;
  118.     DataDef.URT_TX_DataInverse = DISABLE;
  119.     DataDef.URT_RX_DataInverse = DISABLE;
  120.     URT_DataCharacter_Config(URTX, &DataDef);
  121.     //---Set Mode Select---//
  122.     URT_Mode_Select(URTX, URT_URT_mode);
  123.     //---Set DataLine Select---//
  124.     URT_DataLine_Select(URTX, URT_DataLine_2);
  125.    
  126.    
  127.     //=====Set Data Control=====//
  128.     URT_RXShadowBufferThreshold_Select(URTX, URT_RXTH_1BYTE);
  129.     URT_IdlehandleMode_Select(URTX, URT_IDLEMode_No);
  130.     URT_TXGaudTime_Select(URTX, 0);
  131.    
  132.     //=====Enable URT Interrupt=====//
  133.     //URT_IT_Cmd(URTX, URT_IT_RX, ENABLE);
  134.     //URT_ITEA_Cmd(URTX, ENABLE);
  135.     //NVIC_EnableIRQ(URT0_IRQn);

  136.     //=====Enable URT=====//
  137.     URT_Cmd(URTX, ENABLE);
  138.                
  139.         //==See MG32x02z_URT0_IRQ.c when interrupt in
  140. }

  141. void DMA_Init(void)
  142. {
  143.          DMA_BaseInitTypeDef DMATestPattern;

  144.     // ------------------------------------------------------------------------
  145.     // 1.Enable DMA
  146.     DMA_Cmd(ENABLE);
  147.    
  148.     // ------------------------------------------------------------------------
  149.     // 2.Enable Channel0
  150.     DMA_Channel_Cmd(DMAChannel0, ENABLE);
  151.    
  152.     // ------------------------------------------------------------------------
  153.     DMA_BaseInitStructure_Init(&DMATestPattern);
  154.    
  155.     // 3.initial & modify parameter
  156.       
  157.         // DMA channel select
  158.         DMATestPattern.DMAChx = DMAChannel0;
  159.         
  160.         // channel x source/destination auto increase address
  161.         DMATestPattern.SrcSINCSel = ENABLE;           //内存需要地址自增
  162.         DMATestPattern.DestDINCSel = DISABLE;        //外设不需要地址自增
  163.         
  164.         // DMA source peripheral config
  165.         DMATestPattern.SrcSymSel = DMA_MEM_Read;
  166.         
  167.         // DMA destination peripheral config
  168.         DMATestPattern.DestSymSel = DMA_URT0_TX;
  169.         
  170.         // DMA Burst size config
  171.         DMATestPattern.BurstDataSize = DMA_BurstSize_1Byte;
  172.         
  173.         // DMA transfer data count initial number
  174.         DMATestPattern.DMATransferNUM = MYBINARYIMAGE2_LENGTH;
  175.    
  176.         // source/destination config
  177.         DMATestPattern.DMASourceAddr = (uint8_t *)&SendBuf;
  178.         DMATestPattern.DMADestinationAddr = &URT0->TDAT;

  179.                  URT_TXDMA_Cmd(URT0, ENABLE);
  180.     DMA_Base_Init(&DMATestPattern);
  181. }


  182. int main()
  183. {
  184.         int i;
  185.         CSC_Init();
  186.         URT0_Init();
  187.         printf("Hello!\n");
  188.         DMA_Init();
  189.         
  190.                 while(1)
  191.         {
  192.                     i++;
  193.             if(i>=500000)
  194.             {
  195.                                 i=0;
  196.                 strcpy(SendBuf,"i am source");

  197.     DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
  198.     DMA_StartRequest(DMAChannel0);
  199.       
  200.     while (DMA_GetSingleFlagStatus(DMA, DMA_FLAG_CH0_TCF) == DRV_UnHappened);
  201.     DMA_ClearFlag(DMA, DMA_FLAG_CH0_TCF);
  202.                
  203.                 URT_TXDMA_Cmd(URT0, ENABLE);    //每次发送完需要重新使能
  204.                
  205.                         }
  206.         }

  207. }
       就这样,使能UART0的DMA功能后只要往我设定好的SendBuf中丢数据,数据就会自动搬运到UART的DAT寄存器中并发送出去,以此减小CPU消耗。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

82

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部