OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4199|回复: 2

STM32F4-SPI-DMA子函数多次调用问题

[复制链接]

3

主题

7

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
7 小时
发表于 2018-6-9 01:02:25 | 显示全部楼层 |阅读模式
1金钱
        问题:用SPI+DMA的方式,单向给外设发送数据,将SPI以及DMA配置初始化完成,编写的发送子函数调用一次,功能正常!多次调用达不到理想的效果(基本就是第一次调用有效,后续调用功能无效)        可能是这里面的标志位啥的没有清除引起的,初始使用这个,对这些搞不太清除,重点是红色那几行代码该怎么优化,还请懂的朋友指点指点,谢谢!

/* 主函数 */

    while(1)
   {
        LED_SPI_DMA_2811_Send(0,255,0,LEDNum); //这一条功能正常
         delay_ms (1000);
         LED_SPI_DMA_2811_Send(255,0,0,LEDNum); //这一条没有效果
        delay_ms (1000);

  }




        SPI+DMA发送子函数:


       void LED_SPI_DMA_2811_Send(u8 r,u8 g,u8 b,u16 LedNum)//点亮LedNum个灯
{
        //**********************************************SPI要发送的数据处理过程************SendBuff[l][k]为SPI-DMA数据内存区**********       
        u16 i;//灯数量
        u8 j=0,k=0,l;//rgb参数
        u8 RGBConver[3][8]={ZEROCODE};
        for (i = 0x80; i >= 0x01; i >>= 1)
    {

                RGBConver[0][j]=(g & i) ? ONECODE : ZEROCODE;//G码转换
                RGBConver[1][j]=(r & i) ? ONECODE : ZEROCODE;//R码转换
                RGBConver[2][j]=(b & i) ? ONECODE : ZEROCODE;//B码转换
                j++;
        }       
                for( l=0;l<LedNum;l++)
        {
               
                for(k=0;k<8;k++)
                {
                        SendBuff[l][k]=RGBConver[0][k];//G码
                }
                for(k=8;k<16;k++)
                {
                        SendBuff[l][k]=RGBConver[1][k-8];//R码
                }
               
                for(k=16;k<24;k++)
                {
                        SendBuff[l][k]=RGBConver[2][k-16];//B码
                }
        }
//**********************************************SPI要发送的数据处理过程完成************SendBuff[l][k]为SPI-DMA数据内存区**********               
        DMA_Cmd(DMA1_Stream4, DISABLE);                      //关闭DMA传输
        while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE){}        //确保DMA可以被设置         
        DMA_SetCurrDataCounter(DMA1_Stream4,LedNum*24);          //数据传输量  
        DMA_Cmd(DMA1_Stream4, ENABLE);            //开启DMA传输
        }




其他DMA  SPI初始化代码见后!


  /* 配置 DMA Stream */
void MyDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
{

        DMA_InitTypeDef  DMA_InitStructure;
       
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
        }
  DMA_DeInit(DMA_Streamx);
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
       

  DMA_InitStructure.DMA_Channel = chx;  //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
  DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
  DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
}


//SPI2配置
void MySPI2_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        SPI_InitTypeDef SPI_InitStruct;
        //DMA初始化
       
        //SPI初始化
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 , ENABLE );//使能SPI2时钟
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能GPIOB时钟
       
        //初始化SPI输出口
        GPIO_InitStruct.GPIO_Pin =GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_13|GPIO_Pin_12;
        GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF ;
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP ;
        //GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_100MHz ;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
       
        //SPI引脚复用
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);//PB15-SPI2_MOSI
        //GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);//PB15-SPI2_MISO
        //GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);//PB15-SPI2_SCK
       
        //SPI初始化
        SPI_InitStruct.SPI_Direction =SPI_Direction_1Line_Tx;//SPI数据传输方向-单向发送
        SPI_InitStruct.SPI_Mode =SPI_Mode_Master;//主站
        SPI_InitStruct.SPI_DataSize =SPI_DataSize_8b;
        SPI_InitStruct.SPI_CPOL =SPI_CPOL_Low;//时钟空闲时为低电平
        SPI_InitStruct.SPI_CPHA=SPI_CPHA_1Edge;//第一个边沿开始
        SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;//软件片选
        SPI_InitStruct.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2;//8分频
        SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB;//高位在前
        SPI_InitStruct.SPI_CRCPolynomial = 7;        //????CRC值计算的多项式
        SPI_Init(SPI2, &SPI_InitStruct);
        SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
    SPI_Cmd(SPI2, ENABLE);       
           
}


LED.PNG

最佳答案

查看完整内容[请看2#楼]

找到主要原因了,是子函数Dma完成标志未清除!不过这里面严谨的代码过程还不是很清楚,虽然程序能够按要求运行,不知会不会出现意想不到的问题,还请大神指点下规范严谨的spi dma代码该如何完善,谢谢
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
7 小时
 楼主| 发表于 2018-6-9 01:02:26 来自手机 | 显示全部楼层
找到主要原因了,是子函数Dma完成标志未清除!不过这里面严谨的代码过程还不是很清楚,虽然程序能够按要求运行,不知会不会出现意想不到的问题,还请大神指点下规范严谨的spi  dma代码该如何完善,谢谢
回复

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
7 小时
 楼主| 发表于 2018-6-9 21:13:40 来自手机 | 显示全部楼层
找到主要原因了,是子函数Dma完成标志未清除!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-29 10:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表