DMA方式读取外部Flash失败,麻烦帮我看看是什么原因。谢谢
本帖最后由 rookie108 于 2024-6-8 22:31 编辑一、DMA1的配置初始化函数:
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx//cpar:外设地址//cmar:存储器地址 //cndtr:数据传输量
void MYDMA_Config2(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u8 cmar,u16 cndtr)//从外设读到内存
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr =cpar;//DMA外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar;//DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据传输方向,从外设读到内存
DMA_InitStructure.DMA_BufferSize = cndtr;//DMA通道的DMA缓存的大小
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_VeryHigh; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
DMA_Cmd(DMA_CHx, ENABLE);
}
二、SPI DMA方式读取外部flash
void SPI_Flash_DMA_Read(void)
{
u8 cdArray;
u32 Addr=0x9600;
u16 dataSize=360;
//先利用非DMA方式读取外部flash内容验证SPI通信是否正常
SPI_Flash_Read(cdArray, Addr, dataSize);
printf("1--cdArray[]=\r\n");
for (int j=0;j<dataSize;j++){
printf("%.2x ",cdArray);
}
printf("\r\n1--OK!\r\n");
//将cdArray数组清0,
for (int m=0;m<dataSize;m++){
cdArray=0;
}
//以下为DMA方式从外部flash里读取数据
MYDMA_Config2(DMA1_Channel2, (u32)&SPI1->DATAR, (u32)cdArray, 360); //DMA初始化
Flash_CS_Low; //CS拉低
SPI1_ReadWriteByte(W25X_ReadData);
SPI1_ReadWriteByte((u8)((Addr) >> 16));//发送24位地址
SPI1_ReadWriteByte((u8)((Addr) >> 8));
SPI1_ReadWriteByte((u8)Addr);
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;//SPI1配置为只读模式
SPI_Init(SPI1, &SPI_InitStructure);
SPI1_ReadWriteByte(0xff);
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);
while(DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET);//等待通道2传输完成
Flash_CS_Hight;//spi cs拉高
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//恢复双工模式
SPI_Init(SPI1, &SPI_InitStructure);
printf("2--cdArray=\r\n");
for (int q=0;q<dataSize;q++){
printf("%.2x ",cdArray);
}
printf("\r\2--OK!\r\n");
}
三、SPI初始化函数:
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_0);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//双工模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//NSS?????????????
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
// SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1,&SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
四、SPI普通方式读取外部flash数据
void SPI_Flash_Read(u8 *pBuffer, u32 ReadAddr, u16 size)
{
u16 i;
Flash_CS_Low;
SPI1_ReadWriteByte(W25X_ReadData);
SPI1_ReadWriteByte((u8)((ReadAddr) >> 16));//发送24位地址
SPI1_ReadWriteByte((u8)((ReadAddr) >> 8));
SPI1_ReadWriteByte((u8)ReadAddr);
for(i = 0; i < size; i++){
pBuffer = SPI1_ReadWriteByte(0Xff);//循环读数0xff可以为任何数,只是为了产生时钟信号
}
Flash_CS_Hight;
}
u8 SPI1_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检测TXE是否置位,是,则表示 DR为空,可以写入数据
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检测RXE是否置位,是,则表示 DR接收到数据,即发送完成
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1); //接收数据
}
卡在DMA读取FLASH函数中的while(DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET);无法跳出。不知道是哪里的问题。是配置不对还是什么原因? DMA配置问题 软件代码问题 硬件连接问题 Flash设备问题 当使用 DMA 方式读取外部 Flash 时,如果出现问题,可能涉及多个方面,包括 DMA 配置、外部 Flash 配置、和硬件连接等。 DMA配置初始化函数
c
void MYDMA_Config2(DMA_Channel_TypeDef* DMA_CHx, u32 cpar, u8 cmar, u16 cndtr) {
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 使能DMA时钟
DMA_DeInit(DMA_CHx);// 重设DMA通道寄存器
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;// 外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar;// 存储器基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 数据传输方向:从外设到内存
DMA_InitStructure.DMA_BufferSize = cndtr;// 数据传输量
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_VeryHigh;// 高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 非内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);// 初始化DMA通道
DMA_Cmd(DMA_CHx, ENABLE);// 启用DMA通道
}
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值 使用DMA从外部Flash读取数据c
void SPI_Flash_DMA_Read(void) {
u8 cdArray;
u32 Addr = 0x9600;
u16 dataSize = 360;
// 验证SPI通信是否正常
SPI_Flash_Read(cdArray, Addr, dataSize);
printf("1--cdArray[]=\r\n");
for (int j = 0; j < dataSize; j++) {
printf("%.2x ", cdArray);
}
printf("\r\n1--OK!\r\n");
// 清空cdArray
for (int m = 0; m < dataSize; m++) {
cdArray = 0;
}
// DMA方式读取数据
MYDMA_Config2(DMA1_Channel2, (u32)&SPI1->DATAR, (u32)cdArray, 360);
Flash_CS_Low;// CS拉低
SPI1_ReadWriteByte(W25X_ReadData);
SPI1_ReadWriteByte((u8)((Addr) >> 16));
SPI1_ReadWriteByte((u8)((Addr) >> 8));
SPI1_ReadWriteByte((u8)Addr);
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;// 配置为只读模式
SPI_Init(SPI1, &SPI_InitStructure);
SPI1_ReadWriteByte(0xff);// 发送空字节以产生时钟信号
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);// 启用DMA接收
while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET);// 等待传输完成
Flash_CS_Hight;// CS拉高
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;// 恢复双工模式
SPI_Init(SPI1, &SPI_InitStructure);
printf("2--cdArray=\r\n");
for (int q = 0; q < dataSize; q++) {
printf("%.2x ", cdArray);
}
printf("\r\n2--OK!\r\n");
}
通过DMA方式,数据传输效率得以提高,且CPU资源占用减少。在调试过程中,确保SPI通信正常并注意CS信号的控制,以避免数据错误。 请问你的问题解决了吗?我也是有同样的现象
页:
[1]