打印
[菜农助学交流]

新塘M0使用PDMA传输数据到串口发送出现问题

[复制链接]
4428|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zxs2000|  楼主 | 2012-5-29 15:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
新塘M0使用PDMA传输数据到串口发送,电脑接收到得数据部全对

以下是串口与PDMA的初始化代码:  

unsigned char TxBuffer[16] = {0X00,0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0A,0X0B,0X0C,0X0D,0X0E,0X0F};

SYSCLKs.APBCLK.Bits.UART0_EN = 1;//打开uart0时钟
    SYSCLKs.CLKSEL1.Bits.UART_S = 0;//UART时钟源选择外部4-24M高速晶振
    SYSCLKs.CLKDIV.Bits.UART_N = 0;//UART时钟源的时钟除频数;UART时钟源= UART时钟源/(UART_N+1)
   SYSs.IPRSTC2.Bits.UART0_RST = 1; //复位
   SYSs.IPRSTC2.Bits.UART0_RST = 0;
    SYSs.GPBMFP.Bits.UART0_RX = 1;//管脚复用选择UART功能
    SYSs.GPBMFP.Bits.UART0_TX = 1;  

    UART0s.LCR.Bits.WLS = 3;//字长度选择8位
    UART0s.LCR.Bits.NSB = 0;//停止位数目1位
    UART0s.LCR.Bits.PBE = 0;//无奇偶校验
    UART0s.BAUD.Bits.DIV_X_EN = 1;
    UART0s.BAUD.Bits.DIV_X_ONE = 1;
   UART0s.BAUD.Bits.BRD = 1248;//模式2,波特率9600
   UART0s.FUNSEL.Bits.FUN_SEL = 0;//选择UART模式
    UART0s.FCR.Bits.RFITL = 0;//Rx FIFO中断(INT_RDA)触发级别1字节
    UART0s.FCR.Bits.RFR = 1;//Rx软件复位
    UART0s.FCR.Bits.TFR = 1;//Tx软件复位

    SYSCLKs.AHBCLK.Bits.PDMA_EN = 1;//打开PDMA时钟
   SYSs.IPRSTC1.Bits.PDMA_RST = 1; //DMA复位
   SYSs.IPRSTC1.Bits.PDMA_RST = 0;
  PDMA_GCR->GCRCSR.CLK0_EN = 1;//通道0时钟使能
  PDMA_GCR->GCRCSR.CLK1_EN = 1;//通道1时钟使能
  PDMA_GCR->PDSSR1.UART0_RXSEL = 1;//选择与通道1相连
  PDMA_GCR->PDSSR1.UART0_TXSEL = 0;//选择与通道0相连
   
//UART0的TX使用PDMA0通道传输  
  PDMA0s.SAR.Regs = (uint32_t)TxBuffer;//PDMA传输源地址
  PDMA0s.DAR.Regs = UART0_BASE ;//目的地址寄存器  
  PDMA0s.BCR.Regs = 16;//发送字节计数寄存器
  PDMA0s.CSR.Bits.SW_RST = 1;//软件产生复位
  PDMA0s.CSR.Bits.MODE_SEL = 2;//PDMA模式选择 :存储器到外设
  PDMA0s.CSR.Bits.SAD_SEL = 0;//传输源地址方向选择:源地址增加  
  PDMA0s.CSR.Bits.DAD_SEL = 2;//传输目的地址方向选择:目的地址固定
  PDMA0s.CSR.Bits.APB_TWS = 1;//外设传输宽度选择;8位

//UART0的RX使用PDMA1通道传输  
  PDMA1s.SAR.Regs = UART0_BASE;//PDMA传输源地址
  PDMA1s.DAR.Regs = (uint32_t)RxBuffer;//PDMA传输目的地址
  PDMA1s.BCR.Regs = 16;//发送字节计数寄存器
  PDMA1s.CSR.Bits.SW_RST = 1;//软件产生复位
  PDMA1s.CSR.Bits.MODE_SEL = 1;//PDMA模式选择 :外设到存储器
  PDMA1s.CSR.Bits.SAD_SEL = 2;//传输源地址方向选择:源地址不变
  PDMA1s.CSR.Bits.DAD_SEL = 0;//传输目的地址方向选择:目的地址增加
  PDMA1s.CSR.Bits.APB_TWS = 1;//外设传输宽度选择;8位

  PDMA1s.IER.Bits.BLKD_IE = 1;//Transfer Done中断使能   
  PDMA1s.CSR.Bits.PDMACEN = 1;//PDMA通道使能
  PDMA1s.CSR.Bits.TRIG_EN = 1;//PDMA数据读写传输使能(当PDMA传输完成, 该位自动清除.)  
  
  PDMA0s.IER.Bits.BLKD_IE = 1;//Transfer Done中断使能
  PDMA0s.CSR.Bits.PDMACEN = 1;//PDMA通道使能
  PDMA0s.CSR.Bits.TRIG_EN = 1;//PDMA数据读写传输使能(当PDMA传输完成, 该位自动清除.)
  
  UART0s.IER.Regs |= (1<<UART_IER_DMA_TX_EN)|(1<<UART_IER_DMA_RX_EN);//Tx DMA使能,Rx DMA使能  


运行完后串口软件得到的数据为:00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D

前面多了两个0,不知道怎么出来的。初始化反复查找过没发现哪里有问题,不知道什么情况下会出现这样的问题

相关帖子

沙发
feng89| | 2012-7-17 13:00 | 只看该作者
请教一下楼主,如何触发PDMA传送串口的数据?

使用特权

评论回复
板凳
john_lee| | 2012-7-17 14:54 | 只看该作者
对齐问题,新唐m0的PDMA要求数据是4字节对齐的,如果没有对齐,PDMA将从数据将从上一个对齐地址开始发送。
看样子楼主的数据,是对齐到了2字节,而没有对齐到4字节,PDMA实际的起始地址是TxBuffer - 2,发送个数不变,而 TxBuffer[-2] 和 TxBuffer[-1] 的内容碰巧是 0,所以,发出的数据,头上多了两个 0,而后面又少了两个。

使用特权

评论回复
地板
X-Hawk| | 2012-7-17 15:23 | 只看该作者
什么都难逃李老师的火眼晶晶!

使用特权

评论回复
5
feng89| | 2012-7-18 16:39 | 只看该作者
李老师,怎么触发PDMA的?

PDMA接收正常,就是不知怎么启动发送.

void UART0_INI(void)
   {
                NVIC_DisableIRQ(UART0_IRQn);
                SYS->GPBMFP.UART0_RX=1;
            SYS->GPBMFP.UART0_TX=1;  //GPIO 端口初始化
            SYSCLK->CLKSEL1.UART_S=0;   // 选择外部12M 为UART 时钟源
            SYSCLK->APBCLK.UART0_EN=1;  //使能 UART CLOCK 时钟
            SYSCLK->CLKDIV.UART_N=0;    // UART 时钟源为外部12M
                       
                UART0->FCR.TFR=1;            //Reset TX FIF0
                UART0->FCR.RFR=1;            //Reset Rx FIFO
                UART0->FCR.RFITL=0;         // 接收到1个数据,触发中断(开中断)

            UART0->LCR.PBE=1;           //ENABLE Parity
                        UART0->LCR.EPE=1;                        /* Even parity enable */
            UART0->LCR.WLS=2;           // 7 Data Bits
            UART0->LCR.NSB=0;           //Enable 1 Stop Bit
            
            UART0->BAUD.DIV_X_EN=1;
            UART0->BAUD.DIV_X_ONE=1;
           // UART0->BAUD.DIVIDER_X=2;
                        UART0->BAUD.BRD=12000000/9600-2;
                       
            NVIC_EnableIRQ(UART0_IRQn);
//                        UART0->IER.RDA_IEN=1; //开接收中断
/********************************************/
               
                UART0->IER.DMA_RX_EN         = 1;
               
                NVIC_DisableIRQ(PDMA_IRQn);      
               
                PDMA_GCR->PDSSR1.UART0_RXSEL =0; // ADC_RX选择传至通道1  
               
                PDMA0->CSR.PDMACEN     = 1;      // 使能通道0  
               
                PDMA0->CSR.SAD_SEL =  2; // 源地址设为固定模式  
               
                PDMA0->CSR.DAD_SEL =  0; // 目标地址设为自增模式  
               
                PDMA0->CSR.APB_TWS = 0; // 1,传输单位设为8位 0-32 2-16  
               
                PDMA0->CSR.MODE_SEL = 1; // 传输方向为外设到内存   
               
                PDMA0->SAR = UART0_BASE; // 通道1 PDMA源地址指向ADC0的数据寄存器地址;必须为32位  
               
                PDMA0->DAR = (uint32_t)Dbuf; // 通道1 PDMA目标地址指向ad_x_buf数组首地址;必须为32位  
               
                PDMA0->BCR =1600;  // 8位传输计数寄存器;注意:每传输16位计数一次   
               
                // 第四步 使能中断  
               
                PDMA0->IER.BLKD_IE = 1;  // 使能传输完成中断  
               
                PDMA0->ISR.BLKD_IF = 1; // 清传输完成中断标志
                 
///**********************************************************/
                  
                UART0->IER.DMA_TX_EN         = 1;  //使能发送DMA
               
                NVIC_DisableIRQ(PDMA_IRQn);      
               
                PDMA_GCR->PDSSR1.UART0_TXSEL =2; // UART0 发送选择到第二PDMA2.
               
                PDMA2->CSR.PDMACEN     = 1;      // 使能通道2  
               
                PDMA2->CSR.SAD_SEL =  0;   // 源地址设增加  
               
                PDMA2->CSR.DAD_SEL =  2;  // 目标地址固定
               
                PDMA2->CSR.APB_TWS = 0;   // 1,传输单位设为8位 0-32 2-16  
               
                PDMA2->CSR.MODE_SEL = 2;  // 传输方向为内存到外设   
               
                PDMA2->SAR = UART0_BASE;  // 通道2 PDMA源地址指向ADC0的数据寄存器地址;必须为32位  
               
                PDMA2->DAR = (uint32_t)Dbuf; // 通道1 PDMA目标地址指向ad_x_buf数组首地址;必须为32位  
               
                PDMA2->BCR =200;  // 8位传输计数寄存器;注意:每传输16位计数一次   
               
                // 第四步 使能中断  
               
                PDMA2->IER.BLKD_IE = 1;  // 使能传输完成中断  
               
                PDMA2->ISR.BLKD_IF = 1; // 清传输完成中断标志

/*********************************************************/
          
//        NVIC_EnableIRQ(PDMA_IRQn);              

         // 第五步 通道及触发使能         

         PDMA0->CSR.PDMACEN = 1;  // 使能PDMA核  

         PDMA0->CSR.TRIG_EN = 1;  // 触发使能

                 PDMA2->CSR.PDMACEN = 1;  // 使能PDMA核  

         PDMA2->CSR.TRIG_EN = 1;  // 触发使能

//         NVIC_EnableIRQ(PDMA_IRQn);              
//
//         // 第五步 通道及触发使能         
//
//         PDMA0->CSR.PDMACEN = 1;  // 使能PDMA核  
//
//         PDMA0->CSR.TRIG_EN = 1;  // 触发使能

   }

使用特权

评论回复
6
sharkpepper| | 2012-9-11 13:57 | 只看该作者
我也遇到了类似的问题,不知道LZ最后是怎么解决的?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

34

主题

206

帖子

0

粉丝