一、基础知识
1.1 Cortex--M系列介绍
1.2 什么是stm32
1.3 数据手册查看
1.4 最小系统和 IO 分配
1.4.1 电源电路
1.4.2 复位电路
1.4.3 BOOT 启动电路
1.4.4 晶振电路
1.4.5 下载调试电路
1.4.6 串口一键下载电路
1.4.7 IO 分配
1.4.8 总结
1.5 开发工具
1.6 下载
二、 代码、工程相关
2.1 文本美化
2.2 代码编辑技巧
2.3 查找&替换技巧
三、c语言基础复习
3.1 stdint.h
3.2 位操作
3.3 宏定义
3.4 条件编译
3.5 exturn 声明
3.6 类型别名(typedef)
3.7 结构体
3.8 指针
3.9 代码规范
四、STM32基础知识
4.1 Cortex M内核 & 芯片
4.2 F1 框架
4.3 存储器映射
4.4 寄存器映射
4.4.1 使用结构体对寄存器的映射
五、HAL 库
5.1 认识 HAL 库
5.1.1 CMSIS简介
5.1.2 HAL库
5.1.3 STM32Cube固件包
5.2 HAL库的框架结构
5.3 HAL库的使用
六、新建HAL库版本MDK工程
6.1 新建工程文件夹
6.2 新建工程
6.3 添加文件
6.4 魔术棒设置
七、STM32启动解析
八、STM32CubeMX
8.1 新建 STM32CubeMX 工程
九、认识时钟树(F1)
9.1 认识时钟树
9.2 配置系统时钟
十、SYSTEM文件夹介绍
10.1 sys文件夹
10.2 delay文件夹
10.3 usart文件夹
Flash:存放代码
SRAM:内存
外设
1、STM32片内自带SRAM和FLASH,FLASH是用来存储程序的,SRAM是用来存储程序运行中的中间变量,通常不同型号的STM32的SRAM和FLASH大小是不相同的
FLASH存储器又成为闪存,它与EEPROM都是掉电后数据不丢失的存储器,但是FLASH得存储容量都普遍的大于EEPROM,,在存储控制上,最主要的区别是FLASH芯片只能一大片一大片地擦除,而EEPROM可以单个字节擦除。
2、SRAM是静态随机存取存储器。它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据。STM32F1系列可以通过FSMC外设来拓展SRAM。
注意:SRAM和SDRAM是不相同的,SDRAM是同步动态随机存储器,同步是指内存工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是自由指定地址进行数据读写。STM32的F1系列是不支持SDRAM的。
DMIPS:每秒处理多少指令
MHZ:可以产生多少的DMIPS
MCU指的是微控制器,集合了FLASH、RAM和一些外围器件。MCU一般使用片内FLASH来存储和执行程序代码.
MPU指的是微处理器,FLASH和RAM则需要设计者自行搭建,当然MCU也可以外扩。
MPU的电路设计相对MCU较为复杂。MPU将代码存储在外部FLASH中,上电后将代码搬运至RAM中运行。
MCU的启动速度更快,MCU虽然也可以将代码运行在RAM中,但是内部RAM容量小,使用外部扩展RAM的话速度相对内部也较慢。
MCU不具备内存管理单元(MMU),不能运行Linux这种操作系统,只能运行小型操作系统,因此无法运行多进程程序。小型操作系统的RTOS多任务类似于多线程。
MCU相对MPU具有更强的实时性。
MCU相对MPU具有更低的功耗。虽然MPU也有低功耗模式,但不会像MCU那么低。
MPU的主频相对较高,外接的内存也一般是DDR3,DDR4这种速度比较快的,适用于运算比较复杂的。
根据要求也可以使用MCU和MPU配合,现在好多芯片是同时具有MCU和MPU的多核,更方便设计者使用。
MPU现在主要是linux方向的了
A盘,硬件资料
0R电阻 是维修的时候把这个0欧电阻断开,快速判断是电源问题,还是mcu问题!
正点原子默认用跳线帽将3、5和4、6连接,采用下拉双接地的启动方式,也可上拉,变换跳线帽即可
第3步可选,是针对后三种开发板的
没有DAP,视频未看
该文件可以帮助保存设置
无参数的宏定义:
有参数的宏定义:
指针变量是个变量本身也有地址,就是处理器的位数,stm32就是32位的地址,所以&p_str就是取p_str变量本身的地址
未分配内存时,就是随机指向内存,可能是实际的,也可能是虚拟的内存
主动单元可以单向的向被动单元发送指令
512k *2 = 1MB = 1M字节
16bit=2*8bit=2Byte
通过这个表,可以找到每个外设的基地址 ,只需要再找寄存器的偏移地址就可以
举个例子:
截图软件:snipaste
_ IO表示静态
主要是为了管理代码
只保留 Inc 和 Src
可以删除下面两个文件:
取消只读,就可以取消keil中文件显示的小钥匙
定义了②的宏就说明要用这些
/**
******************************************************************************
* @file main.c
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2020-08-20
* @brief 新建工程实验-HAL库版本 实验
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
******************************************************************************
* @attention
*
* 实验平台:正点原子 STM32F103 开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
******************************************************************************
*/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
void led_init(void); /* LED初始化函数声明 */
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); /* PB5置1 */
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); /* PE5置0 */
delay_ms(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); /* PB5置0 */
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); /* PE5置1 */
delay_ms(500);
}
}
/**
* @brief 初始化LED相关IO口, 并使能时钟
* @param 无
* @retval 无
*/
void led_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOB_CLK_ENABLE(); /* IO口PB时钟使能 */
__HAL_RCC_GPIOE_CLK_ENABLE(); /* IO口PE时钟使能 */
gpio_initstruct.Pin = GPIO_PIN_5; /* LED0引脚 */
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_initstruct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOB, &gpio_initstruct); /* 初始化LED0引脚 */
gpio_initstruct.Pin = GPIO_PIN_5; /* LED1引脚 */
HAL_GPIO_Init(GPIOE, &gpio_initstruct); /* 初始化LED1引脚 */
}
下载成功后,led1和led2交替闪烁
若结果与预期不同,检查:是否是8Mhz,有无勾选 reset and run
p30 - p33 讲
本讲为第 35 讲,建议先去学习始终和GPIO相关知识后再来
系统时钟为72MHz,可以超频,但两个高速时钟是无法得到72MHz的,所以中间需要一个锁相环,分频后再乘以锁相环的2~16,这里就用高速外部的1分频后乘9=72了,用高速内部的话,2分频后乘最大的16也只是64,所以用高速外部时钟
HCLK就是AHB高性能总线,SYSCLK到HCLK有一个分频器,一般是不分频
这里72M经过8分频到达系统的滴答定时器就是9MHz
实际两部分定时器都是72MHz,当APB1是1分频是不满足最大36MHz,会自动2分频,但此时频率×2,所以定时器2-7就是72MHz
RTC是实时时钟:时间啊、日历啊 ,优先选择 LSE
通过PA8往外输出时钟
72MHz经过8分频后,变成9MHz,函数传入的形参就是72,所以除以8后得到9,给g_fac_us这个全局变量, 1/1MHz=1us,现在是1/9MHz,所以要乘9,就是g_fac_us
下面可以参考《CM3技术参考手册》74页图8-2页
微秒计时函数一共可以计时:1/9000000*2^24≈1.864s
超频到128MHz时可以计时:1/(128000000/8)*2^24 = 1.048576s
而毫秒延时函数是通过微秒延时函数实现的,所以当传入的值>1000即>1s时,就要调用多次的微秒延时函数
因为下面的那种情况是正常频率,正常情况的延时时间范围比超频情况的要大,所以范围大的可以兼容小的,所以选择超频情况的时间范围(小的)