DMA+串口发送接收,接收不成功。已搞定

2019-12-20 21:38发布

本帖最后由 blavy 于 2018-3-26 16:09 编辑

调试DMA加串口的时候,发送数据是成功了,但是接收数据一直都是0,查了初始化与中断,好象都没问题啊。
懂的人解一下惑吧。

/*
        发送的DMA初始化
*/
void MYDMA_TX_Cfg(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
    RCC->AHBENR|=RCC_AHBPeriph_DMA1;    //开启DMA1时钟
    delay_ms(5);                        //等待DMA时钟稳定,必须延时
    DMA_CHx->CPAR=cpar;                 //DMA1 外设地址
    DMA_CHx->CMAR=(u32)cmar;            //DMA1,存储器地址
    DMA_CHx->CNDTR=cndtr;               //DMA1,传输数据量
   
    DMA_CHx->CCR=0;                     //复位
    DMA_CHx->CCR|=(1<<1);               //使能完成中断
    DMA_CHx->CCR|=1<<4;                 //从存储器读
    DMA_CHx->CCR&=~(1<<5);              //普通模式
    DMA_CHx->CCR&=~(1<<6);              //外设地址非增量模式
    DMA_CHx->CCR|=1<<7;                 //存储器增量模式
    DMA_CHx->CCR&=~(1<<8);              //外设数据宽度为8位
    DMA_CHx->CCR&=~(1<<10);             //存储器数据宽度8位
    DMA_CHx->CCR|=1<<12;                //中等优先级
    DMA_CHx->CCR&=~(1<<14);             //非存储器到存储器模式
    MY_NVIC_Init(3,3,DMA1_Channel4_IRQChannel,2);
}

/*
        接收的DMA初始化
*/
void MYDMA_RX_Cfg(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
    RCC->AHBENR|=RCC_AHBPeriph_DMA1;    //开启DMA1时钟
    delay_ms(5);                        //等待DMA时钟稳定,必须延时
    DMA_CHx->CPAR=cpar;                 //DMA1 外设地址
    DMA_CHx->CMAR=(u32)cmar;            //DMA1,存储器地址
    DMA_CHx->CNDTR=cndtr;               //DMA1,传输数据量
   
    DMA_CHx->CCR=0;                     //复位
    DMA_CHx->CCR&=~(1<<4);              //从外设串口读
    DMA_CHx->CCR&=~(1<<5);              //普通模式
    DMA_CHx->CCR&=~(1<<6);              //外设地址非增量模式
    DMA_CHx->CCR|=1<<7;                 //存储器增量模式
    DMA_CHx->CCR&=~(1<<8);              //外设数据宽度为8位
    DMA_CHx->CCR&=~(1<<10);             //存储器数据宽度8位
    DMA_CHx->CCR|=1<<12;                //中等优先级
    DMA_CHx->CCR&=~(1<<14);             //非存储器到存储器模式

    DMA_CHx->CCR|=(1<<0);               //启动DMA

}

/*

*/
void MYDMA_Enable(DMA_Channel_TypeDef *DMA_CHx)
{
    DMA_CHx->CCR&=~(1<<0);            //关闭DMA传输
    DMA_CHx->CNDTR=BUFF_LEN;          //DMA1,传输数据量
    DMA_CHx->CCR|=(1<<0);             //开启DMA传输
}  

/*
    DMA发送完成中断
*/
void DMA1_Channel4_IRQHandler(void)
{
    if(DMA1->ISR&(1<<13))           //等待通道4传输完成 BIT: TCIF
    {
        DMA1->IFCR|=1<<13;          //清除通道4传输完成标志 BIT: CTCIF
//        printf(" SEND!! ");
    }
}

void Usart1_Init(unsigned int pclk2,unsigned int bound)
{           
        float temp;
        unsigned short mantissa;
        unsigned short fraction;          
        //Tx/Rx 波特率=fck/(16*( USARTDIV))
        temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
        mantissa=temp;                                 //得到整数部分 ----无符号整数 与 浮点数的运算
        fraction=(temp-mantissa)*16; //得到小数部分         浮点数 - 无符号整数 = 浮点数
          mantissa<<=4;                                 // USARTDIV的整数部分 ---bit4~bit15
        mantissa+=fraction;                  // USARTDIV的小数部分 ---bit0~bit3
        RCC->APB2ENR |= (RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1);   //使能PORTA口时钟,使能串口时钟  
        GPIOA->CRH &= (GPIO_Crh_P9 & GPIO_Crh_P10);                //IO状态设置 : USART1_TX   PA.9,USART1_RX          PA.10
        GPIOA->CRH |= (GPIO_Mode_IN_PU_PD_P10 | GPIO_Mode_AF_PP_50MHz_P9);        //IO状态设置:TX---复用推挽输出,RX---下拉输入
                  
        RCC->APB2RSTR |= RCC_APB2Periph_USART1;     //复位串口1
        RCC->APB2RSTR &= ~RCC_APB2Periph_USART1;    //停止复位                     
        //波特率设置
        USART1->BRR=mantissa; // 波特率设置         
        USART1->CR1 |= (USART_ENABLE | USART_Mode_Rx | USART_Mode_Tx);  //默认:一个起始位,8个数据位,1位停止,无校验位.
    #if EN_USART1_RX                  //如果使能了接收
        //使能接收中断       
        USART1->CR1|= (USART_PEIE | USART_RXNEIE);      //PE中断使能,接收缓冲区非空中断使能       
        MY_NVIC_Init(3,3,USART1_IRQChannel,2);          //组2(4组抢占(0,1,2,3),4组优先(0,1,2,3)),最低抢占级,最低优先级
    #endif
}

//如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误          
//接收状态
void USART1_IRQHandler(void)
{
    UINT8 cnt=0;
    volatile unsigned char res;
    if(USART1->SR&(1<<4))
    {//空闲中断
        res = USART1->SR;  
        res = USART1->DR;
        DMA1_Channel5->CCR &= ~(1<<0);
        printf(" REVIEVED!!%d",(RCV_LEN-DMA1_Channel5->CNDTR));
        printf(" ");
        for(cnt=0; cnt<RCV_LEN; cnt++)
        {
            printf("%02x ",RcvBuf[cnt]);
        }
        DMA1_Channel5->CNDTR=RCV_LEN;          //DMA1,传输数据量
        DMA1_Channel5->CMAR=(UINT32)RcvBuf;
        DMA1_Channel5->CCR|=(1<<0);             //开启DMA传输
    }
}

主程序main.cj里面f进行初始化调用
        #define BUFF_LEN    30
        #define RCV_LEN    5
        UINT8 SndBuf[BUFF_LEN] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,10};
        UINT8 RcvBuf[RCV_LEN];

    MYDMA_TX_Cfg(DMA1_Channel4,(u32)&USART1->DR,(u32)SndBuf,BUFF_LEN);//DMA1通道4,外设为串口1,存储器为SendBuff,长(TEXT_LENTH+2)*100.
    MYDMA_RX_Cfg(DMA1_Channel5,(u32)&USART1->DR,(u32)RcvBuf,RCV_LEN);//DMA1通道5,外设为串口1,存储器为SendBuff,长(TEXT_LENTH+2)*100.


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
blavy
1楼-- · 2019-12-20 23:31
结贴,已搞定。
XA144F
2楼-- · 2019-12-21 05:03
接收用空闲中断,如果认为不行就在中断里启动定时器,定时器溢出了才表示接收完成。
lusson
3楼-- · 2019-12-21 08:39
 精彩回答 2  元偷偷看……
STM32LOU
4楼-- · 2019-12-21 12:15
是什么原因导致得?
blavy
5楼-- · 2019-12-21 18:09
仔细看了一下,还是没完全搞定。
可以接收到数据(第一次好象接收不到,而且与发送的没法一起使用),但是第一个数据不对,总是上一次的最后一个数据。
lusson
6楼-- · 2019-12-21 20:21
你这样的有问题就来问,自己解决了就闷声不发的,送你一个表情(没找到BS的表情)

一周热门 更多>