STM32_H7

问题

DMA is not working on STM32H7 devices
Ethernet not working on STM32H7x3
关于STM32H743 recv()数据错误的问题分析

H7使用DMA注意事项

  1. 注意发送或者接收缓存的字节对齐问题,一般是要求4字节对齐
  2. 注意DMA和外设是否可访问发送或者接收缓存所在SRAM空间
  3. 注意Cache的一致性

MPU

STM32H7的Cache和MPU
STM32H7-MPU的理解和配置
STM32H7系列MCU的MPU和Cache功能介绍
http://news.eeworld.com.cn/mcu/ic472514.html
STM32_H7_第1张图片
STM32_H7_第2张图片
STM32_H7_第3张图片

STM32_H7_第4张图片

FMC

FMC-LCD

如果程序和MX的配置都没问题显示还不正常那就先考虑读时序里的data setup time 时间拉长
【经验分享】STM32CubeMX之FMC驱动TFT-LCD屏
TFTLCD之FSMC详解述
TFTLCD之FSMC详解_超级霸霸强的博客-程序员秘

FMC-SDRAM

STM32H7的FMC总线应用之SDRAM
STM32F429驱动外部SDRAM
STM32CubeMX配置SDRAM
注意时钟线,控制线,地址线上的电阻,特别是地址线上的电阻焊接的是不是一样的,如果焊接错误,会导致数据出现错乱。
【STM32H7教程】第25章 STM32H7的TCM,SRAM等五块内存基础知识

STM32H7:解决DMA传输无效的问题

cache

Data alignment(数据、内存对齐)漫谈
M7内核的cache line 是 8字=32字节
在这里插入图片描述

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
                /*
                the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
                adjust the address and the D-Cache size to invalidate accordingly.
                */
                alignedAddr = (uint32_t)buff & ~0x1F;
                SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
#endif
/**
  
  \brief   D-Cache Invalidate by address
  \details Invalidates D-Cache for the given address
  \param[in]   addr    address (aligned to 32-byte boundary)
  \param[in]   dsize   size of memory block (in number of bytes)
*/
__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
  #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
     int32_t op_size = dsize;
    uint32_t op_addr = (uint32_t)addr;
     int32_t linesize = 32;                /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */

    __DSB();

    while (op_size > 0) {
      SCB->DCIMVAC = op_addr;
      op_addr += (uint32_t)linesize;
      op_size -=           linesize;
    }

    __DSB();
    __ISB();
  #endif
}

STM32_H7_第5张图片
STM32_H7_第6张图片
STM32_H7_第7张图片

ADC

#define OVERSAMPLING_RATIO              1023                               /* 1024-oversampling */                                      
#define RIGHTBITSHIFT                   ADC_RIGHTBITSHIFT_6                /* 6-bit right shift of the oversampled summation */          
#define TRIGGEREDMODE                   ADC_TRIGGEREDMODE_SINGLE_TRIGGER   /* A single trigger for all channel oversampled conversions */
#define OVERSAMPLINGSTOPRESET           ADC_REGOVERSAMPLING_CONTINUED_MODE /* Oversampling buffer maintained during injection sequence */

void MX_ADC3_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  /** Common config
  */
  hadc3.Instance = ADC3;
  hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
  hadc3.Init.Resolution = ADC_RESOLUTION_16B;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = ENABLE;
  hadc3.Init.NbrOfConversion = 1;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_ONESHOT;
  hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc3.Init.OversamplingMode = ENABLE;
  hadc3.Init.Oversampling.RightBitShift         = RIGHTBITSHIFT;         /* Right shift of the oversampled summation */
  hadc3.Init.Oversampling.TriggeredMode         = TRIGGEREDMODE;         /* Specifies whether or not a trigger is needed for each sample */
  hadc3.Init.Oversampling.OversamplingStopReset = OVERSAMPLINGSTOPRESET; /* Specifies whether or not the oversampling buffer is maintained during injection sequence */    
  
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }
    
  /* ADCУ׼ */
  if ( HAL_ADCEx_Calibration_Start( &hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED ) != HAL_OK )
  {
    Error_Handler();
  }

  if ( HAL_ADCEx_Calibration_Start( &hadc3, LL_ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED ) != HAL_OK )
  {
    Error_Handler();
  }
    
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

ADC配置参数说明

  1. ContinuousConvMode
    hadc3.Init.ContinuousConvMode = ENABLE;
    如果ContinuousConvMode 配置为ENABLE,表示启动ADC之后,ADC自动连续转化,不需要再次启动

  2. ConversionDataManagement
    hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_ONESHOT;
    当使用ADC查询模式或者中断模式时,需要配置为ADC_CONVERSIONDATA_DR
    当使用ADC DMA传输时,需要配置为ADC_CONVERSIONDATA_DMA_ONESHOT或者ADC_CONVERSIONDATA_DMA_CIRCULAR
    其中,ADC_CONVERSIONDATA_DMA_ONESHOT表示DMA只传输一次,需要再次开启DMAch
    如果配置为ADC_CONVERSIONDATA_DR,使用DMA传输,无法进入DMA传输完成中断。

oversample 过采样

ADC通过过采样技术,STM32H7的ADC可以做到26位分辨率
STM32H7 ADC 过采样对精度的影响效果
STM32H7的ADC过采样功能立竿见影,效果的确不错
过采样移位,会导致计算系数不一样

#define ADC_RIGHTBITSHIFT_NONE             (LL_ADC_OVS_SHIFT_NONE)    /*!< ADC oversampling no shift (sum of the ADC conversions data is not divided to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_1                (LL_ADC_OVS_SHIFT_RIGHT_1) /*!< ADC oversampling shift of 1 (sum of the ADC conversions data is divided by 2 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_2                (LL_ADC_OVS_SHIFT_RIGHT_2) /*!< ADC oversampling shift of 2 (sum of the ADC conversions data is divided by 4 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_3                (LL_ADC_OVS_SHIFT_RIGHT_3) /*!< ADC oversampling shift of 3 (sum of the ADC conversions data is divided by 8 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_4                (LL_ADC_OVS_SHIFT_RIGHT_4) /*!< ADC oversampling shift of 4 (sum of the ADC conversions data is divided by 16 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_5                (LL_ADC_OVS_SHIFT_RIGHT_5) /*!< ADC oversampling shift of 5 (sum of the ADC conversions data is divided by 32 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_6                (LL_ADC_OVS_SHIFT_RIGHT_6) /*!< ADC oversampling shift of 6 (sum of the ADC conversions data is divided by 64 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_7                (LL_ADC_OVS_SHIFT_RIGHT_7) /*!< ADC oversampling shift of 7 (sum of the ADC conversions data is divided by 128 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_8                (LL_ADC_OVS_SHIFT_RIGHT_8) /*!< ADC oversampling shift of 8 (sum of the ADC conversions data is divided by 256 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_9                (LL_ADC_OVS_SHIFT_RIGHT_9) /*!< ADC oversampling shift of 9 (sum of the ADC conversions data is divided by 512 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_10               (LL_ADC_OVS_SHIFT_RIGHT_10)/*!< ADC oversampling shift of 10 (sum of the ADC conversions data is divided by 1024 to result as the ADC oversampling conversion data) */
#define ADC_RIGHTBITSHIFT_11               (LL_ADC_OVS_SHIFT_RIGHT_11)/*!< ADC oversampling shift of 11 (sum of the ADC conversions data is divided by 2048 to result as the ADC oversampling conversion data) */

AdcHandle.Init.Oversampling.RightBitShift         = ADC_RIGHTBITSHIFT_6;
 /* Read the converted value */
    uwConvertedValue = HAL_ADC_GetValue(&AdcHandle);

    /* Convert the result from 20 bit value to the voltage dimension (mV unit) */
    /* Vref = 3.3 V */
    uwInputVoltage = uwConvertedValue * 3300;  
    /* ADC_RIGHTBITSHIFT_6 计算结果需要除以64=2^4,左移4we
    uwInputVoltage = uwInputVoltage / 0xFFFF0; 

DMA数据长度范围为:1-65535
#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x01U) && ((SIZE) < 0x10000U))

第43章 STM32H7的DMA应用之双缓冲控制任意IO和脉冲数控制
STM32_H7_第8张图片
STM32_H7_第9张图片

最后特别注意一点,如果STM32H7工作在400MHz,ADC使用AHB做时钟源,超频是不可避免的。ADC1和ADC2位于200MHz的AHB1总线时钟,而ADC3位于200MHz的AHB4下。根据上面的框图,ADCx_CCR寄存器的CKMODE最高可以选择4分频,那么就是50MHz,而ADC数据手册限制最高是36MHz,也就是说已经超频了。

使用AHB作为时钟源的好处就是定时器等外部触发方式的效果好。
STM32_H7_第10张图片
STM32_H7_第11张图片
STM32_H7_第12张图片

STM32_H7_第13张图片

STM32三个ADC同步规则采样
【STM32H7教程】第46章 STM32H7的ADC应用之DMA方式多通道采样
第44章 STM32H7的ADC基础知识和HAL库API
How to persistently write into option byte BOOT_ADD0/1
第51章 设置FLASH的读写保护及解除—零死角玩转STM32-F429系列

HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
FLASH_OBProgramInitTypeDef obData;
HAL_FLASHEx_OBGetConfig(&obData);
obData.BootAddr1 =(CalValue<<16);  //自定义数据
obData.OptionType = OPTIONBYTE_BOOTADD;
obData.BootConfig =OB_BOOT_ADD_BOTH;
if (  HAL_FLASHEx_OBProgram(&obData)!= HAL_OK){
    Error_Handler();
}
HAL_FLASH_OB_Launch();
HAL_FLASHEx_OBGetConfig(&obData);
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();

像使用内部SRAM一样定义使用STM32H7的外部SDRAM


1、在IAR的分散配置文件中,定义SDRAM放在“不初始化区域”(因为系统启动后,sdram并没有完成初始化配置,此时初始化sdram区域中的变量会导致系统进入硬件错误HardFault_Handler)

do not initialize  { section .noinit ,section .sdram2};

2、系统启动后,初始化SDRAM

3、将变量定义在sdram中

__attribute__((section (".sdram2")))  float x_buff[1024];
__attribute__((section (".sdram2")))  float farFFTBuffer_t[1024*2];
__attribute__((section (".sdram2")))  float farFFTOutBuffer[1024];

4、使用定义的变量(使用变量之前,必须完成SDRAM初始化,否则系统进入硬件错误HardFault_Handler)

memory map

STM32_H7_第14张图片

STM32_H7_第15张图片

ETH

  1. 必须添加MAC的复位操作,否则无法通信
    在ethernetif.c文件中的low_level_init函数中,添加复位操作
 /* USER CODE BEGIN MACADDRESS */
  LAN8720A_reset();
  /* USER CODE END MACADDRESS */
  hal_eth_init_status = HAL_ETH_Init(&heth);
static void LAN8720A_reset(void)
{
  ETH_CTR_RESET;
  HAL_Delay(50);
  ETH_CTR_SET;
  HAL_Delay(50);
}

SDIO

使用注意事项

  1. 必须使能SDMMC中断
    STM32_H7_第16张图片
  2. 必须配置SDMMC时钟频率为200MHz
    只需要将SDIO的时钟频率配置为200MHz,HAL库会根据不同的SD卡设置不同的速率
    STM32_H7_第17张图片
  3. 使能ENABLE_SD_DMA_CACHE_MAINTENANCE和ENABLE_SCRATCH_BUFFER
    使能sd_diskio.c中的ENABLE_SD_DMA_CACHE_MAINTENANCE和ENABLE_SCRATCH_BUFFER,否则数据读写不正确
    STM32_H7_第18张图片

只需要将SDIO的时钟频率配置为200MHz,HAL库会根据不同的SD卡设置不同的速率。
STM32H7教程】第87章 STM32H7的SDMMC总线基础知识和HAL库API
[SD/SDIO] STM32H7的SDIO自带的DMA控制器数据传输的地址是强制4字节对齐
STM32_H7_第19张图片

SD卡的协议上说上限是48MHz,但许多SD卡上不了这么高的频率
一般设置为36MHz或者24MHz
STM32_H7_第20张图片
STM32_H7_第21张图片
STM32_H7_第22张图片
STM32_H7_第23张图片
STM32_H7_第24张图片

SD specification上明确写着speed class存在SSR寄存器中,[447:440] 是speed class,[399:396]是UHS speed grade。如下图所示。另外,SSR的访问向SD device发送ACMD13即可在data line上返回SSR的内容。下图中的内容是V5.0中呈现的。
作者:晴天
链接:https://www.zhihu.com/question/55487660/answer/171128582
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

STM32_H7_第25张图片STM32_H7_第26张图片

STM32_H7_第27张图片
图中1-9序号分别表示:

1、品牌

2、产品定位或系列

3、容量等级32GB

4、SDHC容量等级为2GB - 32GB

5、最快读取速度95MB/s

6、Class等级C10,即最低写入速度10MB/s

7、UHS等级U3,即支持UHS模式时,最低写入速度30MB/s

8、支持UHS-I模式,最大读取速度104MB/s

9、VSC视频速度等级V3,即最低写入速度30MB/s

总结一下卡面信息就是:

(1)容量32GB。

(2)普通模式,最低读写速度10MB/s。

(2)支持UHS模式,最低写入速度30MB/s,最高读取速度95MB/s。
STM32_H7_第28张图片
STM32_H7_第29张图片

【图拉丁】SD卡速度规范
深入理解SD卡:协议
都是高速SD卡,支持UHS-I和UHS-II的区别是什么?
UHS-I、UHS-II、UHS-III接口
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器

USART

串口时钟的大小影响通信速率,时钟速率设置过高会导致低速率时无法通信。
串口时钟频率设置过高,导致最低通信速率被限制,之前是120000KHz,16倍过采样,最高120000/16=7500Kbps,最低120000/65535=1.8310Kbps,超过1200bps。
修改串口分频为4分频,串口时钟为30000KHz,最高30000/16=1875Kbps,最低30000/65535=0.457Kbps,满足要求
STM32_H7_第30张图片

STM32_H7_第31张图片

LTDC

STM32F429之LTDC驱动图解
H743教程五:stm32H743 cubumx配置驱动LTDC RGB屏幕
基于STM32H743设计UI界面心得(还没写完)
LTDC/DMA2D——液晶显示
第27章 LTDC/DMA2D—液晶显示

DMA2D

STM32的“GPU”——DMA2D实例详解

QSPI

STM32硬件基础–QaudSPI总线读写片外FLASH(二)

SPI

H7的SPI功能更强大,需要配置的参数更多,一般配置如下。需要注意几点

  1. MasterSSIdleness:设置第一个数据发送开始前CLK的延时
  2. MasterInterDataIdleness :设置每个DataSize 之间,CLK的延时
  3. MasterKeepIOState :设置是否保持SPI的IO状态(CLK和MOSI),如果关闭该功能,在使用完SPI后,SPI引脚状态释放。如果片选配置成SPI_NSS_SOFT,最好使能改功能,使SPI的IO口保持在正确的状态
  4. IOSwap :设置是否交换MISO和MOSI口
  hspi4.Instance = SPI4;
  hspi4.Init.Mode = SPI_MODE_MASTER;
  hspi4.Init.Direction = SPI_DIRECTION_2LINES;
  hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi4.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi4.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi4.Init.NSS = SPI_NSS_SOFT;
  hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi4.Init.CRCPolynomial = 0x0;
  hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
  hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi4) != HAL_OK)
  {
    Error_Handler();
  }

I2C

i2c timing配置
STM32H7的硬件I2C fast mode 速度不能到400K?

内置温度传感器

[ADC] STM32H7的ADC温度传感器测量

你可能感兴趣的:(STM32,stm32)