STM32H7

STM32H7概览

  • Cube工程结构
  • HAL库及编程tips
  • H7内存及总线
  • 外设使用

Cube工程结构

Keil中打开

  • driver
    • Application/MDK-ARM
      • 启动文件:startup_stm32xxxx.s
    • Application/User
      • 主程序文件:main.c
      • 中断服务定义文件:stm32xxxx_it.c
      • 进行芯片级别硬件初始化设置:stm32xxxx_hal_msp.c
    • Drivers/STM32xxxx_HAL_Driver
      标准HAL库驱动
    • Drivers/CMSIS
      • 定义系统初始化函数及时钟更新函数:system_stm32xxxx.c

文件夹中打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--+ Project             //工程根目录
--+ Drivers //驱动源文件(CubeMX生成)
--+ CMSIS //ARM的MCU软件接口标准
--+ STM32H7xx_HAL_Driver //H7芯片的HAL库
--+ inc //外设初始化头文件(CubeMX生成)
--+ MDK-ARM //Keil工程目录
--+ Middlewares //第三方软件包
--+ Src //外设初始化源文件(CubeMX生成)
--+ Task //如果有OS的话,该文件夹为任务or线程文件
--+ BSP //BSP文件
--+ REFERENCE //使用到的参考资料(笔者自己添加的)
--+ link.md
--- ...
--+ Project.ioc //CubeMX工程文件
--+ README.md //README文件(笔者自己加的)

HAL库及编程tips

  • _IO成员变量修饰符:相当于const、variable等
  • HAL_Delay()采用的是中断原理,所以有时会误差严重
  • 注意H7的Dcache功能,若不开启强制透写,可能出现与ram数据不同步bug
  • 一定一定注意H7的总线结构噢!在AXI总线上的告诉存储是不能被普通DMA访问的!
  • 在不进行固件升级下,ST-link最大速度为1.8MHz
  • _weak函数修饰符:用户可以再次定义为自己的函数内容
  • volatile修饰符:修饰的变量是随时改变的,每次读取的时候都要乖乖从变量地址读出

    该修饰符主要用于修饰特殊状态寄存器,这些寄存器是硬件触发改变状态的!

  • __align()修饰符:内存对齐
  • 内存定位
    1
    uint8_t mpudata[128] __attribute__((at(0x20002000)));

H7内存及总线

  • ITCM
    • 地址:0X0000 0000 ~ 0X0000 FFFF
    • 大小:64Kbytes
    • 访问:仅CPU和MDMA
  • DTCM
    • 地址:0X2000 0000 ~ 0X2001 FFFF
    • 大小:128Kbytes
    • 访问:仅CPU和MDMA
  • AXI-SRAM
    • 地址:0X2400 0000 ~ 0X2407 FFFF
    • 大小:512Kbytes
    • 访问:仅CPU和MDMA
  • SRAM1
    • 地址:0X3000 0000 ~ 0X3001 FFFF
    • 大小:128Kbytes
  • SRAM2
    • 地址:0X3002 0000 ~ 0X3003 FFFF
    • 大小:128Kbytes
  • SRAM3
    • 地址:0X3004 0000 ~ 0X3004 7FFF
    • 大小:32Kbytes
    • 一般独立给以太网使用
  • SRAM4
    • 地址:0X3800 0000 ~ 0X3800 FFFF
    • 大小:64Kbytes
  • Reserved
    • 地址:0X3801 0000 ~ 0X3FFF FFFF
    • 大小:127Mbytes

H7总线

显然挂在内核上的高速RAM是只能被主DMA设备(MDMA)和内核本身访问!这个不注意会坑得很死
还有H7的AXI总线是64位的呢!可以说和存储设备的访问简直nice到没盆友

外设使用

GPIO

1
2
3
HAL_GPIO_WritePin(GPIOx,GPIO_PIN_x,GPIO_PIN_xxx);   //写端口
HAL_GPIO_ReadPin(GPIOx,GPIO_PIN_x); //读端口状态
HAL_GPIO_TogglePin(GPIOx,GPIO_PIN_x); //端口翻转

复位后一般默认输入模式

UART

  • 过采样模式,16倍过采样可获得高容错性
  • 使能校验位时,MSB位是接收到的校验位
  • 中断回调函数函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //直接定义该函数就是中断的
    {
    if(huart->Instance == USART1) //判断是否你要处理的uart接口
    {
    /* TODO */

    while(HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY); //检测是否空闲
    while(HAL_UART_Receive_IT(&huart1,bufferUART1Rx,UART1RXBUFFERSIZE)!=HAL_OK); //重新开启接收中断
    }
    }
  • 数据收发
    1
    2
    HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)//数组数据发送
    HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //接收开启

中断

1
2
HAL_NVIC_EnableIRQ(USART1_IRQn);    //使能中断
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //设置中断优先级
  • 外部中断
    1
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin); //在该回调函数中定义各中断处理

看门狗

独立看门狗:IWDG

  • 时钟源:LSI
    1
    HAL_IWDG_Refresh(&hiwdg1);  //喂狗
  • 超时公式
    1
    T = \frac{4 \cdot 2^{PRE} \cdot RLR}{CLK}
    PRE为分频系数,RLR为重装载值

窗口看门狗:WWDG

  • 时钟源:PCLK1
  • 可采用中断触发方式喂狗
    1
    2
    HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef*);  //提前唤醒中断
    HAL_WWDG_Refresh(WWDG_HandleTypeDef*); //喂狗
  • 超时公式
    1
    T = \frac{4096 \cdot 2^{PRE} \cdot (T[5:0]+1)}{PCLK}

定时器

  • 高级定时器:1、8
  • 通用定时器:2 ~ 5,12 ~ 17
    • TIM2、5是32位,其他为16位
    • TIM12 ~ 14不支持DMA
    • TIM12 ~ 17只能向上计数,不支持编码器
  • LP开头的为低功耗计时器
  • 基本定时器:6、7
  • 对齐模式
    • 边沿:递增or递减
    • 中心1:交替递增递减;仅递减时,输出通道比较中断才能置1
    • 中心2:交替递增递减;仅递增时,输出通道比较中断才能置1
    • 中心3:交替递增递减;都能输出通道比较中断置1
1
2
3
__HAL_TIM_SET_COUNTER(&htim5,0);    //设置计数器值
__HAL_TIM_DISABLE(&htim5); //停止定时器
__HAL_TIM_ENABLE(&htim5); //启动定时器

定时器中断

1
2
HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim); //开启中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定义改函数就可以处理更新中断

PWM

1
2
3
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel); //开启PWM输出
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_4,pwmValue); //设置PWM比较器值
__HAL_TIM_GetCompare(&htim3,TIM_CHANNEL_4); //获取当前PWM比较器值
  • 输出模式
    • PWM1
    • PWM2
    • C1
    • C2
    • A1
    • A2

输入捕获

1
2
3
4
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);   //输入捕获中断回调处理
uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel)//获取输入捕获值
TIM_RESET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1); //清楚原捕获设置
TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING); //设置捕获

内存保护

  • Memory Protection Unit
    1
    2
    void MemManage_Handler(void);   //内存操作错误中断服务函数
    NVIC_SystemReset(); //软复位

    保护模式

  • 背景区域:开启MPU后,特权程序可以访问无region地址,用户程序被卡
  • 错误静止MPU:若有NMI和硬件fault中断,则关闭MPU
    • NMI:不可屏蔽中断
    • 硬件fault:硬件错误

Rigion

  • 最小容量:32字节
  • 缓存:预先读取
  • 缓冲:写入一定数量后一次性写(提高性能)
  • 子Rigion属性和主一样
  • Rigion必须8等分为子Rigion

DMA

注意:非MDMA使用时,注意总线域访问问题

用于图像的DMA2D

  • 用特定颜色填充图像的一部分
  • 源图像一部分复制到目标图像的一部分
  • 通过像素格式转换将源图像的一部分复制到目标的一部分
  • 将像素格式不同的两个源部分/全部混合

MDMA

  • AXI总线和AHBS总线

双口DMA

  • 8个数据流/DMA,115通道/数据流
  • 四级32位FIFO/数据流
  • 4个请求优先级
  • 数据数目可以软件控制,也可以外设硬件结束
  • 数据宽度不等时,自动优化带宽(仅仅FIFO)
  • 可突发传输(4、8、16节拍)
  • 5个事件:半传输、传输完成、传输错误、FIFO错误、直接传输错误

BDMA

RTC

  • 闹钟A、B和中断、唤醒
  • 读写掉电备份寄存器
    1
    2
    uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister);
    HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data);
  • 读写RTC时间
    1
    2
    3
    4
    HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);   //设置时间
    HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); //读取时间
    HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); //设置日期
    HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); //读取日期
  • 注意BUG:读取时间后必须读取日期

RNG

1
HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit);  //获取随机数

ADC

  • 注意:时钟不能超过36M
  • 注入通道:中断一样的转换请求,可以打断规则通道
  • 芯片温度通道在ADC3
  • 非触发模式下,软件直接开始转换
    1
    HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc);
  • 校准ADC
    1
    HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc, uint32_t CalibrationMode, uint32_t SingleDiff);
  • 获取目前规则通道转换值
    1
    uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc);

DAC

  • 供电:VDDA、VSSA
  • 参考电压:Vref+
  • 硬件触发:3个APB时钟后传输数据;否则一个APB时钟
  • DA建立时间最大2us
  • 输出
    1
    2
    HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel);
    HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data);

IIC

  • SCL为高时,SDA不变;若SDA拉高,为结束信号,若SDA拉低为起始信号
  • 接受器件拉低SDA为应答
  • 7位地址+1位操作(W/R)
    注意:使用CubeMX生产的代码,IIC初始化函数中要修正时钟初始化步骤
    1
    2
    HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);   //写内容到I2C存储器
    HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); //从I2C存储器读内容

Quad SPI

  • 工作模式
    • 间接模式:使用QSPI寄存器完成所有操作
    • 状态轮询:周期性读取外部FLASH状态位,若置1时会产生中断
    • 内存映射模式:当作系统内部定时器使用
  • 双闪存模式:并行两个FLASH
  • 可SDR和DDR
  • DMA可用于间接模式
  • 内部有直接拉到AXI总线的接口
  • 传输阶段
    1
    2
    3
    4
    5
    graph LR
    指令-->地址
    地址-->交替字节
    交替字节-->空指令周期
    空指令周期-->数据
  • 时钟模式
    • 模式0:CS高电平(空闲)时CLK保持低电平
    • 模式3:CS高电平(空闲)时CLK保持高电平
  • NOTE : QSPIQuad SPI是不同的
    • QSPI指令采用4线传输
    • Quad SPI指令采用单线传输
  • BUG:CubeMX默认生成的初始化代码,GPIO时钟是Low!会导致传输卡住

FDCAN

  • 由ID显性确定抢占优先级
  • ID和ACK的速率是和普通CAN一样的,最高1M;但是,数据段可以甚至超过5M
  • 一帧最高64字节
  • 总线起止要有120R终端电阻
  • 帧结构
    1
    2
    3
    4
    5
    6
    7
    graph LR
    帧起始-->仲裁段
    仲裁段-->控制段
    控制段-->数据段
    数据段-->CRC
    CRC-->ACK
    ACK-->帧结束
  • 位段
    • 同步
    • 传播时间
    • 相位缓冲1
    • 相位缓冲2
  • 消息RAM是FDCAN1和FDCAN2共享的
  • 工作在普通CAN模式时,要关闭自动重传机制

SPI

  • 基本信号线
    • MISO/SDI:主设备数据输入and从设备数据输出
    • MOSI/SDO:主设备数据输出and从设备数据输入
    • SCK/CK:主设备产生的时钟
    • SS/WS/CS:主设备控制的从设备片选信号
  • SPI模式
    • 模式0
      • CPOL:0(时钟空闲电平低)
      • CPHA:0(在第一个时钟沿采集信号)
    • 模式1
      • CPOL:0
      • CPHA:1(在第二个时钟沿采集信号)
    • 模式2
      • CPOL:1(时钟空闲电平高)
      • CPHA:0
    • 模式3
      • CPOL:1
      • CPHA:1
  • H7性能
    • 最高时钟133M
    • 可配成全双工I2S

SDMMC

  • MicroSD卡引脚定义
    PIN SD SPI
    1 DATA2 X
    2 DATA3/CD CS
    3 CMD DI
    4 VDD VDD
    5 CLK SCLK
    6 VSS VSS
    7 DATA0 DO
    8 DATA1 X
  • FIFO读写,必须是对4字节对齐的内存进行操作

FPU

NOTE:该部分笔记全部为H7平台

  • 开启方式
    1
    2
    #define __FPU_PRESENT 1
    #define __FPU_USED 1

DSP

NOTE:该部分笔记全部为H7平台

  • 支持指令集
    • 单周期乘加(MAC)
    • 单指令多数据指令(SIMD)
  • 开启方法(添加全局宏)
    1
    2
    3
    4
    ARM_MATH_CM7
    __CC_ARM
    ARM_MATH_MATRIX_CHECK
    ARM_MATH_ROUNDING

USB

  • 内核时钟必须是48MHz

硬件层

  • D+和D-差分传输
  • 主机双线过15K下拉到地
  • 设备机
    • 高速设备:D+过1K5上拉
    • 低速设备:D-过1K5上拉
  • 高速USB要外扩高速物理接口芯片,480Mbps
  • 全速,12Mbps
  • 低速,1.5Mbps
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2022-2023 RY.J
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信