大家好,我的外部flash為W25Q32,采用SPI方式連接,使用普通方式讀取數(shù)據(jù)時(shí)一切正常,但是采用DMA方式則無(wú)法讀取到數(shù)據(jù)。麻煩大家?guī)臀仪魄剖鞘裁丛颍x謝!
一、DMA1的配置初始化函數(shù):
//DMA1的各通道配置
//這里的傳輸形式是固定的,這點(diǎn)要根據(jù)不同的情況來(lái)修改
//從存儲(chǔ)器->外設(shè)模式/8位數(shù)據(jù)寬度/存儲(chǔ)器增量模式
//DMA_CHx:DMA通道CHx? //cpar:外設(shè)地址? //cmar:存儲(chǔ)器地址? ?//cndtr:數(shù)據(jù)傳輸量
void MYDMA_Config2(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u8 cmar,u16 cndtr)//從外設(shè)讀到內(nèi)存
{
? ? RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);? //使能DMA傳輸
? ? DMA_DeInit(DMA_CHx);? ?//將DMA的通道1寄存器重設(shè)為缺省值
? ? DMA1_MEM_LEN=cndtr;
? ? DMA_InitStructure.DMA_PeripheralBaseAddr =? cpar;? //DMA外設(shè)基地址
? ? DMA_InitStructure.DMA_MemoryBaseAddr = cmar;? //DMA內(nèi)存基地址
? ? DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;? //數(shù)據(jù)傳輸方向,從外設(shè)讀到內(nèi)存
? ? DMA_InitStructure.DMA_BufferSize = cndtr;? //DMA通道的DMA緩存的大小
? ? DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;? //外設(shè)地址寄存器不變
? ? DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;? //內(nèi)存地址寄存器遞增
? ? DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;? //數(shù)據(jù)寬度為8位
? ? DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //數(shù)據(jù)寬度為8位
? ? DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;? //工作在正常緩存模式
? ? DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道 x擁有中優(yōu)先級(jí)
? ? DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;? //DMA通道x沒有設(shè)置為內(nèi)存到內(nèi)存?zhèn)鬏?br>? ? DMA_Init(DMA_CHx, &DMA_InitStructure);? //根據(jù)DMA_InitStruct中指定的參數(shù)初始化DMA的通道USART1_Tx_DMA_Channel所標(biāo)識(shí)的寄存器
? ? DMA_Cmd(DMA_CHx, ENABLE);
}
二、SPI DMA方式讀取外部flash
void SPI_Flash_DMA_Read(void)
{
? ? u8 cdArray[360];
? ? u32 Addr=0x9600;
? ? u16 dataSize=360;
? ? //先利用非DMA方式讀取外部flash內(nèi)容驗(yàn)證SPI通信是否正常
? ? SPI_Flash_Read(cdArray, Addr, dataSize);
? ? printf("1--cdArray[]=\r\n");
? ? for (int j=0;j? ? ? ? printf("%.2x ",cdArray[j]);
? ? }
? ? printf("\r\n1--OK!\r\n");
? ? //將cdArray數(shù)組清0,
? ? for (int m=0;m? ? ? ? cdArray[m]=0;
? ? }
? ? //以下為DMA方式從外部flash里讀取數(shù)據(jù)
? ? MYDMA_Config2(DMA1_Channel2, (u32)&SPI1->DATAR, (u32)cdArray, 360); //DMA初始化
? ? Flash_CS_Low;? ?//CS拉低
? ? SPI1_ReadWriteByte(W25X_ReadData);
? ? SPI1_ReadWriteByte((u8)((Addr) >> 16));//發(fā)送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;//恢復(fù)雙工模式
? ? SPI_Init(SPI1, &SPI_InitStructure);
? ? printf("2--cdArray=\r\n");
? ? ? ? for (int q=0;q? ? ? ? ? ? printf("%.2x ",cdArray[q]);
? ? ? ? }
? ? ? ? printf("\r\2--OK!\r\n");
}
三、SPI初始化函數(shù):
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數(shù)據(jù)
void SPI_Flash_Read(u8 *pBuffer, u32 ReadAddr, u16 size)
{
? ? u16 i;
? ? Flash_CS_Low;
? ? SPI1_ReadWriteByte(W25X_ReadData);
? ? SPI1_ReadWriteByte((u8)((ReadAddr) >> 16));//發(fā)送24位地址
? ? SPI1_ReadWriteByte((u8)((ReadAddr) >> 8));
? ? SPI1_ReadWriteByte((u8)ReadAddr);
? ? for(i = 0; i < size; i++){
? ? ? ? pBuffer[i] = SPI1_ReadWriteByte(0Xff);//循環(huán)讀數(shù)? 0xff可以為任何數(shù),只是為了產(chǎn)生時(shí)鐘信號(hào)
? ? }
? ? Flash_CS_Hight;
}
u8 SPI1_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //檢測(cè)TXE是否置位,是,則表示 DR為空,可以寫入數(shù)據(jù)
{
retry++;
if(retry>200)return 0;
}??
SPI_I2S_SendData(SPI1, TxData); //通過(guò)外設(shè)SPIx發(fā)送一個(gè)數(shù)據(jù)
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //檢測(cè)RXE是否置位,是,則表示 DR接收到數(shù)據(jù),即發(fā)送完成
{
retry++;
if(retry>200)return 0;
}? ? ??
return SPI_I2S_ReceiveData(SPI1); //? 接收數(shù)據(jù)
}
熱門產(chǎn)品 :
CH32X035: 32位USB+USB PD單片機(jī)