OpenEdv-开源电子网

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

STM32H750 SPI+DMA 寄存器操作方式不成功

[复制链接]

9

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2017-3-15
在线时间
42 小时
发表于 2023-11-27 17:50:48 | 显示全部楼层 |阅读模式
50金钱
目前已经排除是MPU 内存保护或者是DMA配置问题,问题锁定在SPI的配置方式上,但是目前看SPI配置DMA也就两个使能,实在看不出有啥问题,关键代码如下:
说明: 数组已经指定到DMA可访问的内存段,并且,使用串口DMA部分程序验证过,证明DMA配置函数以及内存段不会有问题,此外,SPI使用单独的发送接收函数是没有问题的,说明SPI基本收发是正常的,如果正常工作,while(1)那边不应该卡住,这里都通过串口DMA验证过

//以下是SPI模块的初始化代码,配置成主机模式                                                   
//SPI口初始化
//这里针是对SPI2的初始化
void SPI2_Init(void)
{         
        u32 tempreg=0;
        RCC->AHB4ENR|=1<<1;                          //使能PORTB时钟
        RCC->APB1LENR|=1<<14;                  //SPI2时钟使能
        GPIO_Set(GPIOB,7<<13,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_FAST,GPIO_PUPD_PU);        //PB13~15复用功能输出       
        GPIO_Set(GPIOB,PIN12,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_MID,GPIO_PUPD_PU); //PB12设置
       
        GPIO_Pin_Set(GPIOB,PIN12,1);       
       
  GPIO_AF_Set(GPIOB,13,5);        //PB13,AF5
        GPIO_AF_Set(GPIOB,14,5);        //PB14,AF5
        GPIO_AF_Set(GPIOB,15,5);        //PB15,AF5
        //配置SPI的时钟源
        RCC->D2CCIP1R&=~(7<<12);        //SPI1/2/3SEL[2:0]=0,清除原来的设置
        RCC->D2CCIP1R|=0<<12;                //SPI1/2/3SEL[2:0]=1,选择pll1_q_ck作为SPI1/2/3的时钟源,一般为200Mhz
                                                                //即:spi_ker_ck=200Mhz
        //这里只针对SPI口初始化
        RCC->APB1LRSTR|=1<<14;                //复位SPI2
        RCC->APB1LRSTR&=~(1<<14);        //停止复位SPI2

       
        SPI2->CR1|=1<<12;                        //SSI=1,设置内部SS信号为高电平       
        SPI2->CFG1=2<<28;                        //MBR[2:0]=7,设置spi_ker_ck为16分频.
        SPI2->CFG1|=7<<0;                        //DSIZE[4:0]=7,设置SPI帧格式为8位,即字节传输


       
        tempreg=(u32)1<<31;                        //AFCNTR=1,SPI保持对IO口的控制
        tempreg|=0<<29;                                //SSOE=0,禁止硬件NSS输出
        tempreg|=1<<26;                                //SSM=1,软件管理NSS脚
        tempreg|=1<<25;                                //CPOL=1,空闲状态下,SCK为高电平
        tempreg|=1<<24;                                //CPHA=1,数据采样从第2个时间边沿开始
        tempreg|=0<<23;                                //LSBFRST=0,MSB先传输
        tempreg|=1<<22;                                //MASTER=1,主机模式
        tempreg|=0<<19;                                //SP[2:0]=0,摩托罗拉格式
        tempreg|=0<<17;                                //COMM[1:0]=0,全双工通信
        SPI2->CFG2=tempreg;                        //设置CFG2寄存器       
        SPI2->I2SCFGR&=~(1<<0);                //选择SPI模式

MYDMA_Config(DMA1_Stream0,40,(u32)&(SPI2->TXDR),(u32)IMU_DATA,240,SINGLE,OUT);       
  SPI2->CFG1|=3<<14;     //TXDMA RXDMA 使能

        SPI2->CR1|=1<<0;                        //SPE=1,使能SPI1
       
while(1){if(DMA1->LISR&(1<<5)){DMA1->LIFCR|=1<<5;break;}}
MYDMA_Config(DMA1_Stream0,40,(u32)&(SPI2->TXDR),(u32)IMU_DATA,240,SINGLE,OUT);

}



#define CYCLE 0
#define SINGLE 1

#define OUT 0
#define IN 1


//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//chxMA通道选择,范围:1~115(详见<<STM32H7xx参考手册>>16.3.2节,Table 116)
//par:外设地址
//mar:存储器地址
//ndtr:数据传输量  
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr,u8 model,u8 dir)
{
        DMA_TypeDef *DMAx;
        DMAMUX_Channel_TypeDef *DMAMUXx;
        u8 streamx;
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
                DMAx=DMA2;
                RCC->AHB1ENR|=1<<1;                //DMA2时钟使能  
        }else
        {
                DMAx=DMA1;
                RCC->AHB1ENR|=1<<0;                //DMA1时钟使能
        }
        DMA_Streamx->CR&=~(1<<0);         //关闭DMA传输       
        while(DMA_Streamx->CR&0x01);//等待DMA可配置
        streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18;                        //得到stream通道号
        if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16);                //清空之前该stream上的所有中断标志
        else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4);                //清空之前该stream上的所有中断标志
        else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16);        //清空之前该stream上的所有中断标志
        else DMAx->LIFCR|=0X3D<<6*streamx;                                                        //清空之前该stream上的所有中断标志

        if((u32)DMA_Streamx>(u32)DMA2)streamx+=8;                                        //如果是DMA2,通道编号+8
        DMAMUXx=(DMAMUX_Channel_TypeDef *)(DMAMUX1_BASE+streamx*4);        //得到对应的DMAMUX通道控制地址
        DMAMUXx->CCR=chx&0XFF;                //通道选择
       
        DMA_Streamx->AR=par;                //DMA外设地址
        DMA_Streamx->M0AR=mar;                //DMA 存储器0地址
        DMA_Streamx->NDTR=ndtr;                //传输数据长度
        DMA_Streamx->CR=0;                        //先全部复位CR寄存器值
       
        if(dir==1)DMA_Streamx->CR&=~(1<<6); //外设到存储器模式               
        else DMA_Streamx->CR|=1<<6;      //存储器到外设模式   
        if(model==1)DMA_Streamx->CR&=~(1<<8);                //非循环模式(即使用普通模式)
        else DMA_Streamx->CR|=1<<8;         //循环模式
        DMA_Streamx->CR|=0<<9;                //外设非增量模式
        DMA_Streamx->CR|=1<<10;                //存储器增量模式
        DMA_Streamx->CR|=0<<11;                //外设数据长度:8位
        DMA_Streamx->CR|=0<<13;                //存储器数据长度:8位
        DMA_Streamx->CR|=3<<16;                //中等优先级
        DMA_Streamx->CR|=0<<21;                //外设突发单次传输
        DMA_Streamx->CR|=0<<23;                //存储器突发单次传输
         
        //DMA_Streamx->FCR=0X21;        //FIFO控制寄存器
        DMA_Streamx->CR|=1<<0;                //开启DMA传输       
}




最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2017-3-15
在线时间
42 小时
 楼主| 发表于 2023-11-27 17:50:49 | 显示全部楼层
回复

使用道具 举报

9

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2017-3-15
在线时间
42 小时
 楼主| 发表于 2023-11-29 21:09:43 | 显示全部楼层
已解决
回复

使用道具 举报

7

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2015-6-23
在线时间
15 小时
发表于 2024-7-9 17:10:32 | 显示全部楼层
楼主,是怎么解决的?我遇到和你一样的,用SPI由模块搬运数据;
回复

使用道具 举报

9

主题

39

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2017-3-15
在线时间
42 小时
 楼主| 发表于 2024-7-9 21:16:46 | 显示全部楼层
jsxh538 发表于 2024-7-9 17:10
楼主,是怎么解决的?我遇到和你一样的,用SPI由模块搬运数据;

SPI里面有个寄存器位要使能一下,具体细节忘了
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 12:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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