1.基础知识

单片机:Single-Chip Microcomputer,单片微型计算机,是一种集成电路芯片

CPU:CPU
内存:SRAM
硬盘:FLASH
主板:外设

仪器仪表:电源/示波器/焊台
家用电器:空调/冰箱/洗衣机
工业控制:机器人/PLC/电梯
汽车电子:GPS/ABS/胎压监测

:数据与程序储存在同一存储器,分时复用

CoreMark分数:https://www.eembc.org/coremark/scores.php
ARM公司官网:https://www.arm.com/
ARM开发者官网:https://developer.arm.com/

STM32:
ST:意法半导体  M:MCU/MPU  32:32位
ST累计推出了:5大类、18个系列、1000多个型号的Cortex内核微控制器
ST中文社区网:https://www.stmcu.org.cn 
ST官网: https://www.st.com
正点原子论坛:www.openedv.com/forum.php
STM32 主要分两大块, MCU 和 MPU, MCU 不能跑 Linux,而 MPU可以跑 Linux。

芯片的基本参数:
1,主频/FLASH/SRAM
2,工作电压/最大电流
3,IO引脚接入电压范围
4,单个IO引脚最大电流

最小系统:电源、复位、启动、晶振、调试
    电源:
        VDD/VSS
        VDDA/VSSA:模拟部分供电
        VREF+/VREF- :给内部 ADC/DAC 提供参考电压
        VBAT:给RTC和后备区域供电。
    复位:
        NRST:低电平复位
    启动:
        BOOT0/BOOT1:启动选择引脚,一般接下拉电阻
    晶振:
        OSC_IN /OSC_OUT:外部 HSE 晶振,提供高精度系统时钟
        OSC32_IN /OSC32_OUT:外部 LSE 晶振,给内部 RTC 提供时钟
    调试:
        SWCLK/SWDIO
 
 
 


外设串口资源:
NVIC(嵌套向量中断控制器):
SysTick(系统滴答定时器):
RCC(复位和时钟控制):
GPIO(通用IO):
AFIO(复用IO):
EXTI(外部中断):
TIM(定时器):
ADC(模数转换器):
DMA(直接内存访问):
USART(同/异步串口通信):2
I2C(通信):2
SPI(通信):4
CAN(通信):2
USB(通信):2
RTC(实时时钟):
CRC(校验):
PWR(电源控制):
BKP(备份寄存器):
IWDG(独立看门狗):
WWDG(窗口看门狗):
DAC(数模转换器):
SDIO(SD卡接口):6
FSMC(可变静态存储控制器):
USB OTG(USB主机接口):

 

标准波特率系列:110,300,600,1200,1800,2400,4800,9600,14.4K,19.2K,28.8K,33.6K,56Kbps

 

C 语言基础知识:
位操作:
    按位与:&
    按位或:|
    按位异或:^
    按位取反:~
    左移:<<
    右移:>>
单片机开发中的一些实用技巧。
    1,在不改变其他位的值的状况下,对某几个位进行设值。用&操作符进行清零操作, 然后用|操作符设值,
        比如:要改变 GPIOA 的 CRL 寄存器 bit6(第 6 位)的值为 1
        GPIOA->CRL &= 0XFFFFFFBF; / 将第 bit6 清 0 /
        然后再与需要设置的值进行|或运算
        GPIOA->CRL |= 0X00000040; / 设置 bit6 的值为 1,不改变其他位的值 /
    2.移位操作提高代码的可读性
        比如:将 CTRL 寄存器的第 1 位(从 0 开始算起)设置为 1
        SysTick->CTRL |= 1 << 1;
    3.~按位取反操用于清除某一个/某几个位
        比如:设置 CTRL 寄存器的第 0 位(最低位)为 0,其他位的值保持不变。
        SysTick->CTRL &= ~(1 << 0) ; / 关闭 SYSTICK /
    4.^按位异或操,用于控制某个位翻转
        比如:使 PB5 的输出状态翻转一次
        GPIOB->ODR ^= 1 << 5;

define :预处理命令,它用于宏定义
常见的格式:define 标识符 字符串
标识符:宏名。

ifdef 条件编译:条件编译命令最常见的形式为:
 #ifdef 标识符
  程序段 1
#else
  程序段 2
#endif
当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译, 否则编译程序段 2。 其中#else 部分也可以没有

extern 外部申明:
extern :置于变量或者函数前,以表示变量或者函数的定义在别的文件中。 extern 申明变量可以多次,但定义只有一次

typedef:为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。定义结构体的类型别名和枚举类型。
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  …
} GPIO_TypeDef;

声明结构体类型:
struct 结构体名
{
  成员列表;
}变量名列表;
  在结构体申明的时候可以定义变量,也可以申明之后定义:struct 结构体名字 结构体变量列表 ;
  结构体成员变量的引用方法是:结构体变量名字.成员名

指针:本质是指向一个地址,从而可以访问一片内存区域。
申明指针我们一般以 p 开头:char * p_str = “This is a test!”;
p_num:变量的地址
*p_num:指向的地址所存储的值
&p_num:指针自身的地址

寄存器:单片机内部一种特殊的内存,它可以实现对单片机各个功能的控制
STM32 寄存器分为两类:内核寄存器和外设寄存器
内核寄存器:
    1.内核相关寄存器:包含 R0~R15、 xPSR、特殊功能寄存器等
    2.中断控制寄存器:包含 NVIC 和 SCB 相关寄存器,
        NVIC: ISER、 ICER、ISPR、 IP 等;
        SCB: VTOR、 AIRCR、 SCR 等
    3.SysTick 寄存器:CTRL、 LOAD、 VAL、CALIB
    4.内存保护寄存器:可选功能, STM32F407 没有
    5.调试系统寄存器:ETM、 ITM、 DWT、IPIU 等相关寄存器
重点关心中断控制寄存器和 SysTick 寄存器
外设寄存器:
    包含 GPIO、 UART、 IIC、 SPI、 TIM、 DMA、 ADC、 DAC、RTC、 I/WWDG、 PWR、 CAN、 USB 等各种外设寄存器

存储器本身是没有地址信息的,存储器分配地址的过程就叫存储器映射。
给寄存器的地址命名的过程就叫寄存器映射。
寄存器的地址=外设基地址+地址偏移量
=总线基地址(BUS_BASE_ADDR)+总线基地址的偏移量(PERIPH_OFFSET)+外设基地址的偏移量(REG_OFFSET)
例如:GPIOB_ODR地址 = AHB1总线基地址 + GPIOB外设偏移量 + 寄存器偏移量
外设基地址在stm32参考手册2.3存储器映射中查看

/*GPIOB_ODR 寄存器的地址为: 0x4002 0414, 假设我们要控制GPIOB 的 16 个 IO 口都输出 1*/
#define GPIOB_ODR      *(unsigned int *)(0x40020414)
GPIOB_ODR = 0XFFFF;
/*这个宏定义过程就可以称之为寄存器的映射。*/
STM32F407所有寄存器映射都在stm32f407xx.h里面完成
stm32f407xx.h文件主要包含五个部分内容
    1.中断编号定义:定义 IRQn_Type 枚举类型,包含STM32内部所有中断编号(中断号),方便后续编写代码
    2.外设寄存器结构体类型定义:以外设为基本单位,使用结构体类型定义对每个外设的所有寄存器进行封装,方便后面的寄存器映射
    3.寄存器映射:定义总线地址和外设基地址;使用外设结构体类型定义将外设基地址强制转换成结构体指针,完成寄存器映射
    4.寄存器位定义:定义外设寄存器每个功能位的位置及掩码
    5.外设判定:判断某个外设是否合法(即是否存在该外设)
寄存器映射主要有两个组成部分:外设寄存器结构体类型定义、寄存器映射
包括3个步骤:
    1, 外设寄存器结构体类型定义
    2, 外设基地址定义
    3, 寄存器映射(通过将外设基地址强制转换为外设结构体类型指针即可)
寄存器映射原理:
    1,结构体地址自增;
    2,地址强制转换;
 
 
 

 

 

固件包目录结构:

Drivers :
    BSP:开发板外设驱动文件
    CMSIS:
        LICENSE.txt:Apache 2.0 授权的许可文件
        ARM.CMSIS.pdsc:描述该 CMSIS 包的文件
        Device:基于 Arm Cortex-M 处理器设备的 CMSIS 参考实现
        CMSIS 组件:
            Documentation:这个数据包的描述文档
            Core:CMSIS-Core(Cortex-M)相关文件的用户代码模板
            Core_A:CMSIS-Core(Cortex-A)相关文件的用户代码模板
            DAP:CMSIS-DAP 调试访问端口源代码和参考实现
            Driver:驱动程序外设接口 API 的头文件
                stm32f4xx.h
                stm32f407xx.h:外设访问层头文件
                system_stm32f4xx.c、system_stm32f4xx.h:声明和定义了系统初始化函数 SystemInit 以及系统时钟更新函数 SystemCoreClockUpdate
                startup_stm32f407xx.s:启动文件,进行堆栈的初始化,中断向量表以及中断函数定义等
            DSP_Lib :DSP 软件库源代码
            NN:NN 软件库源代码
            Include:头文件
                cmsis_armcc.h
                cmsis_armclang.h
                cmsis_compiler.h
                cmsis_version.h
                core_cm4.h:软件复位,开关中断等功能
                mpu_armv7.h
            Lib: CMSIS 核心(Cortex-M)和 CMSIS-DSP的文件
            Pack:示例
            RTOS:CMSIS-RTOS 版本 1 以及 RTX4 参考实现
            RTOS2:CMSIS-RTOS 版本 2 以及 RTX5 参考实现
            SVD:样例,规定开发者、制造商、工具制造商的分工和职能
            Utilities:CMSIS-Pack:架构文件、检查软件包的工具、MSIS-SVD架构文件、SVD文件的转换工具
    STM32F4xx_HAL_Driver:HAL 库头文件和源文件
Middlewares:
    ST:
        STemWin :STemWin 工具包。Segger提供。
        STM32_USB_Device_Library:USB 从机设备支持包。
        STM32_USB_Host_Library:USB 主机设备支持包。
    Third_Party:
        FatFs :FAT 文件系统支持包。采用的 FATFS 文件系统。
        FreeRTOS :FreeRTOS 实时系统支持包。
        LibJPEG :基于 C 语言的 JPEG 图形解码支持包。
        LwIP :LwIP 网络通信协议支持包。
Projects:Project.uvprojx 工程文件
Utilities:为 ST 官方的 Demo 板提供,一些公用组件
License.md:用于声明软件版权信息的文件
package.xml:描述固件包版本信息的文件
Release_Notes.html:对固件包的补充描述和固件版本更新的记录说明

 

文件介绍
用户程序文件
    main.c:存放 main 函数,不一定要在这个文件
    main.h:包含头文件、声明等作用,已删除
    stm32f4xx_it.c/h:用户中断服务函数存放文件,不一定放到这个文件,可删除
    stm32f4xx_hal_conf.h:用户配置文件
    stm32f4xx_hal_msp.c:回调函数存放文件,已删除
设备驱动层
    sm32f4xx_hal.c/h:初始化 HAL 库,主要实现 HAL 库的初始化、系统滴答,HAL 库延时函数、IO 重映射和 DBGMCU 功能等
    stm32f4xx_hal_def.h:通用 HAL 库资源定义
    stm32f4xx_hal_ppp.c/h:外设的操作 API 函数文件
    stm324fxx_hal_ppp_ex.c/h:拓展外设特性的 API 函数文件
    stm32f4xx_II_ppp.c/h:LL 库文件,在一些复杂外设中实现底层功能
CMSIS核心层
    stm32f4xx.h:STM32F4 系列的顶层头文件
    stm32f407xx.h:STM32F407 系列片上外设头文件
    system_stm32f4xx.c/h:主要存放系统初始化函数 SystemInit
    startup_stm32hf407xx.s:启动文件,运行到 main 函数前的准备
    core_cm4.h:内核寄存器定义,如 Systick、SCB 等
    cmsis_armcc.h
    cmsis_armclang.h
    cmsis_compiler.h
    cmsis_version.h
    mpu_armv7.h

 

HAL 的 API 函数,常见的有以下几种:
    初始化/反初始化函数:
        HAL_PPP_Init()
        HAL_PPP_DeInit()
    外 设 读 写 函 数 :
        HAL_PPP_Read()
        HAL_PPP_Write()
        HAL_PPP_Transmit()
        HAL_PPP_Receive()
    控制函数:
        HAL_PPP_Set ()
        HAL_PPP_Get ()
    状态和错误:
        HAL_PPP_GetState ()
        HAL_PPP_GetError ()
与外设句柄相关的宏:
    __HAL_PPP_ENABLE_IT(__HANDLE__, __INTERRUPT__):使能外设中断
    __HAL_PPP_DISABLE_IT(__HANDLE__,__INTERRUPT__):禁用外设中断
    __HAL_PPP_GET_IT (__HANDLE__, __ INTERRUPT __):获取外设的某一中断源
    __HAL_PPP_CLEAR_IT (__HANDLE__, __ INTERRUPT __):清除外设中断
    __HAL_PPP_GET_FLAG (__HANDLE__, __FLAG__):获取外设的状态标记
    __HAL_PPP_CLEAR_FLAG (__HANDLE__, __FLAG__):清除外设的状态标记
    __HAL_PPP_ENABLE(__HANDLE__):使能某一外设
    __HAL_PPP_DISABLE(__HANDLE__):禁用某一外设
    __HAL_PPP_XXXX (__HANDLE__, __PARAM__):针对外设的特殊操作
    __HAL_PPP_GET_ IT_SOURCE (__HANDLE__, __INTERRUPT __) :检查外设的中断源
回调函数,这部分允许用户重定义:
    HAL_PPP_MspInit() / _DeInit():由 HAL_PPP_Init()这个 API 调用,实现外设对应的 GPIO、时钟、DMA 和中断开启的配置和操作
    HAL_PPP_ProcessCpltCallback:由外设中断或 DMA 中断调用
    HAL_PPP_ErrorCallback:外设或 DMA 中断中发生的错误,用于作错误处理。

API 函数的帮助文档:Drivers\STM32F4xx_HAL_Driver\ chm 格式的文档

使用HAL库:
修改stm32f4xx_hal_conf.h:
修改外部高速晶振频率

#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /* 外部高速振荡器的值8MHZ,单位 HZ */
#endif /* HSE_VALUE */


#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768) /* 外部低速振荡器的值32.768KHZ,单位 HZ */
#endif /* LSE_VALUE */

滴答定时器的中断优先级一定要比中断高。

使用断言:取消USE_FULL_ASSERT注释,使能断言->实现assert_failed()函数,在sys.c文件里->->->->

HAL库中断处理:
使用某一外设中断->初始化一个外设->开启外设的中断设置外设中断优先级->定义中断函数并调用HAL库的中断处理->编写中断回调函数的内容->判断有中断发生?->
  是:判断目标中断源?->
    是:执行中断回调函数
    否:顺序执行主程序功能->判断有中断发生?(执行中断回调函数)
  否:顺序执行主程序功能->判断有中断发生?(执行中断回调函数)

外设的控制句柄结构体:PPP_HandleType ->初始化结构体的参数:PPP_InitType ->驱动的初始化:HAL_PPP_Init()->实现外设初始化细节的接口:Hal_PPP_Mspinit()->完成外设时钟、IO 等细节差异的设置->使能外设中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()->定义中断处理函数:PPP_IRQHandler->判断和处理中断标记:HAL_ppp_function_IRQHandler()->调用自定义的中断回调接口:HAL_PPP_ProcessCpltCallback()->->

 

STM32 启动过程:
启动模式复位方式有三种:上电复位,硬件复位和软件复位
内部 FLASH启动方式:读取内部 FLASH的 0x08000000 地址空间存储的内容,赋值给栈指针 MSP,作为栈顶地址,再读取内部 FLASH的 0x08000004 地址空间存储的内容,赋值给程序指针 PC,作为将要执行的第一条指令所在的地址
内部 SRAM 启动方式:

启动模式(也称自举模式)(0:低电平;1:高电平;x:任意电平)
内部 FLASH:
  BOOT0:0
  BOOT1:x
  映射地址:0x08000000、0x08000004
内部 SRAM:
  BOOT0:1
  BOOT1:1
  映射地址:0x20000000、0x20000004
系统存储器:
  BOOT0:1
  BOOT1:0
  映射地址:0x1FFFF000、0x1FFFF004

关于 MicroLIB 更多知识可以看官方介绍 http://www.keil.com/arm/microlib.asp 

.map 文件分析:主要包含了交叉链接信息。
整个工程的函数调用关系、FLASH 和 RAM 占用情况及其详细汇总信息。

 map 文件的基础概念:
Section:描述映像文件的代码或数据块,简称程序段
RO:Read Only 的缩写,包括只读数据(RO data)和代码(RO code)两部分内容,占用 FLASH 空间
RW:Read Write 的缩写,包含可读写数据(RW data,有初值,且不为 0),占用FLASH(存储初值)和 RAM(读写操作)
ZI:Zero initialized 的缩写,包含初始化为 0 的数据(ZI data),占用 RAM 空间
.text:相当于 RO code
.constdata:相当于 RO data
.bss:相当于 ZI data
.data:相当于 RW data

 

时钟系统
时钟树:在 MCU 设计时就设计了专门用于控制时序的电路,在芯片设计中称为时钟树设计
输入时钟源:包括 HSI,HSE,LSI,LSE。 HSI、HSE 高速时钟,LSI 和 LSE 是低速。HSE 和 LSE 是外部时钟源

锁相环:自动控制系统中常用的一个反馈电路
主要作用:输入时钟净化和倍频

系统时钟 SYSCLK:为整个芯片提供了时序信号

 

时钟树:
时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波
外部时钟:

uint8_t sys_stm32_clock_init(uint32_t plln, uint32_t pllm, uint32_t pllp, uint32_t pllq)
SYSCLK=HSE/pllm*plln/pllp
内部时钟:

时钟源、锁相环:HAL_RCC_OscConfig()
系统时钟、总线:HAL_RCC_ClockConfig()
使能外设时钟:__HAL_RCC_PPP_CLK_ENABLE()
扩展外设时钟(RTC/ADC/USB):HAL_RCCEx_PeriphCLKConfig()

系统时钟配置步骤:
1,配置HSE_VALUE:HAL库外部晶振频率,stm32xxxx_hal_conf.h
2,调用SystemInit()函数(可选):在启动文件中调用, 在system_stm32xxxx.c定义
3,选择时钟源,配置PLL:通过HAL_RCC_OscConfig()函数设置
4,选择系统时钟源,配置总线分频器:通过HAL_RCC_ClockConfig()函数设置
5,配置扩展外设时钟(可选):通过HAL_RCCEx_PeriphCLKConfig()函数设置

1.HAL_RCC_OscConfig()函数(F4/F7)
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)

typedef struct 
{ 
	uint32_t  OscillatorType; 		/* 选择需要配置的振荡器 */ 
	uint32_t  HSEState; 			/* HSE 状态 */ 
	uint32_t  LSEState; 			/* LSE 状态 */ 
	uint32_t  HSIState; 			/* HSI 状态 */ 
	uint32_t  HSICalibrationValue; 	/* HSI 校准微调值,范围0x0~0x1F */ 
	uint32_t  LSIState; 			/* LSI 状态 */ 
	RCC_PLLInitTypeDef  PLL; 		/* PLL 结构体 */ 
}RCC_OscInitTypeDef;
typedef struct 
{ 
	uint32_t  PLLState; 		/* PLL 状态 */ 
	uint32_t  PLLSource; 	/* PLL 时钟源 */ 
	uint32_t  PLLM; 		/* PLL 分频系数 M */ 
	uint32_t  PLLN; 		/* PLL 倍频系数 N */ 
	uint32_t  PLLP; 		/* PLL 分频系数 P */ 
	uint32_t  PLLQ; 		/* PLL 分频系数 Q */ 
}RCC_PLLInitTypeDef; 

 

2.HAL_RCC_ClockConfig()函数(F4/F7)
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)

typedef struct 
{ 
	uint32_t  ClockType; 		/* 要配置的时钟(SYSCLK/HCLK/PCLK1/PCLK2) */ 
	uint32_t  SYSCLKSource; 		/* 系统时钟源 */ 
	uint32_t  AHBCLKDivider; 		/* AHB  时钟预分频系数 */ 
	uint32_t  APB1CLKDivider; 	/* APB1 时钟预分频系数 */ 
	uint32_t  APB2CLKDivider; 	/* APB2 时钟预分频系数 */ 
}RCC_ClkInitTypeDef;
uint32_t FLatency 

#define  FLASH_LATENCY_0   FLASH_ACR_LATENCY_0WS 	/* FLASH 0个等待周期 */ 
#define  FLASH_LATENCY_1   FLASH_ACR_LATENCY_1WS 	/* FLASH 1个等待周期 */ 
#define  FLASH_LATENCY_2   FLASH_ACR_LATENCY_2WS 	/* FLASH 2个等待周期 */ 
... 
#define  FLASH_LATENCY_15   FLASH_ACR_LATENCY_15WS 	/* FLASH 15个等待周期 */ 



 

posted @ 2024-07-15 12:49  阿Q熊  阅读(161)  评论(0)    收藏  举报