你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32U3评测】SPIDMA接收功能读取SPI FLASH数据

[复制链接]
donatello1996 发布时间:2025-6-16 23:01
       上一帖评测了STM32U385的SPIDMA发送功能用作ST7789液晶屏刷图,这次来评测一下SPIDMA接收实现读取SPI FLASH数据并显示到屏幕上,原理差不多。
       看CubeMX配置:
10.JPG
      
        可以看到,配置跟SPIDMA发送基本大同小异,有不同的地方是,SPIDMA接收是不跟SPIDMA发送用同一个通道的,比如我这里就用新的通道即通道2,然后就是跟SPIDMA发送颠倒过来,是外设到内存,内存地址自增(如果内存地址非自增的话,那就只有内存首地址会收到源源不断的数据)。SPI的接收机制是,主机拉低片选并对从机发送【从机开始接收】指令之后,CLK脚会一直产生脉冲时钟信号给到从机,从机收到脉冲就会源源不断发给主机,只要主机的时钟信号不停就表示主机一直在接收状态,而SPIDMA接收呢则是在此基础上把SPI外设给DMA外设相应通道接管,因此CPU也是需要等待DMA外设完成接收产生中断的,所以代码必须要有中断,并且是DMA通道产生的中断:
  1. HAL_NVIC_SetPriority(GPDMA1_Channel2_IRQn, 0, 0);
  2. HAL_NVIC_EnableIRQ(GPDMA1_Channel2_IRQn);

  3. void GPDMA1_Channel2_IRQHandler(void)
  4. {
  5.   HAL_DMA_IRQHandler(&handle_GPDMA1_Channel2);
  6. }
复制代码

然后是DMA配置函数,跟上文说的一致,外设到内存,内存地址自增:
  1. void SPI1_RX_DMA_Config_PID_MIE_Byte_Normal()
  2. {
  3.     handle_GPDMA1_Channel2.Instance = GPDMA1_Channel2;
  4.     handle_GPDMA1_Channel2.Init.Request = GPDMA1_REQUEST_SPI1_RX;
  5.     handle_GPDMA1_Channel2.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  6.     handle_GPDMA1_Channel2.Init.Direction = DMA_PERIPH_TO_MEMORY;
  7.     handle_GPDMA1_Channel2.Init.SrcInc = DMA_SINC_FIXED;
  8.     handle_GPDMA1_Channel2.Init.DestInc = DMA_DINC_INCREMENTED;
  9.     handle_GPDMA1_Channel2.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
  10.     handle_GPDMA1_Channel2.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
  11.     handle_GPDMA1_Channel2.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
  12.     handle_GPDMA1_Channel2.Init.SrcBurstLength = 1;
  13.     handle_GPDMA1_Channel2.Init.DestBurstLength = 1;
  14.     handle_GPDMA1_Channel2.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0 | DMA_DEST_ALLOCATED_PORT0;
  15.     handle_GPDMA1_Channel2.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  16.     handle_GPDMA1_Channel2.Init.Mode = DMA_NORMAL;
  17.     HAL_DMA_Init(&handle_GPDMA1_Channel2);

  18.     __HAL_LINKDMA(&hspi1 , hdmarx , handle_GPDMA1_Channel2);

  19.     HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel2 , DMA_CHANNEL_NPRIV);
  20. }
复制代码


对于SPI FLASH从机而言,无论主机是否使用DMA接收,都是通过主机的指令行事,因此代码区别只在主机发完【从机开始接收】这个指令给从机之后的接收方式不同而已:
  1. void W25QXX_Read(uint8_t* pBuffer , uint32_t addr , uint16_t num)   
  2. {
  3.      uint16_t i;                                               
  4.     XX25QXX_CS_LOW;
  5.    
  6.     SPI1_PA5_PA6_PA7_Read_Write_Byte(W25X_ReadData);
  7.     if(XX25QXX_TYPE == W25Q256)
  8.     {
  9.         SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>24));   
  10.     }
  11.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>16));
  12.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>8));
  13.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)addr);
  14.    
  15.     for(i = 0 ; i < num ; i ++)
  16.     {
  17.         pBuffer[i]=SPI1_PA5_PA6_PA7_Read_Write_Byte(0xff);
  18.     }
  19.    
  20.     XX25QXX_CS_HIGH;                                
  21. }  

  22. void XX25QXX_Read_DMA(uint8_t* pBuffer , uint32_t addr , uint16_t num)
  23. {
  24.      uint16_t i;                                               
  25.     XX25QXX_CS_LOW;
  26.     SPI1_PA5_PA6_PA7_Read_Write_Byte(W25X_ReadData);
  27.     if(XX25QXX_TYPE == W25Q256)
  28.     {
  29.         SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>24));   
  30.     }
  31.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>16));
  32.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)((addr)>>8));   
  33.     SPI1_PA5_PA6_PA7_Read_Write_Byte((uint8_t)addr);
  34.   
  35.     SPI1_RX_DMA_Config_PID_MIE_Byte_Normal();
  36.     HAL_SPI_Receive_DMA(&hspi1 , pBuffer , num);
  37.     while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_RX);
  38.    
  39.     XX25QXX_CS_HIGH;                                
  40. }  
复制代码

我这里用SPIDMA接收所实现的功能是从SPI FLASH读出图片数据并显示到SPITFTLCD液晶屏上,而MCU的RAM大小以及DMA通道大小是有限制的,所以必须要采用分块读取的方式实现,将320*480分辨率,16位色的屏幕,平均分成6块,每块就是320*480*2/6=51200大小:
  1. uint8_t datatemp[51200];

  2.         for(j = 0 ; j < 6 ; j ++)
  3.         {
  4.             W25QXX_Write((uint8_t*)(gImage_u3_logo + j * 51200 ) , WRITE_READ_ADDR + j * 51200 , 51200);
  5.             XX25QXX_Read_DMA(datatemp , WRITE_READ_ADDR + j * 51200 , 51200);
  6.    
  7.             SPITFTLCD_ST7789_ShowPicture_DMA(0 , j * 80 , SPITFTLCD_ST7789_W , 80 , datatemp);
  8.         }
复制代码

演示效果:
VID_20250616_222131 00_00_00-00_00_30.gif


收藏 评论0 发布时间:2025-6-16 23:01

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版