初级会员
- 积分
- 187
- 金钱
- 187
- 注册时间
- 2017-3-15
- 在线时间
- 42 小时
|
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传输
}
|
|