时钟周期:时钟周期就是外接晶振的倒数 周期(S) = 1/频率(HZ)
机器周期:完成一个基本操作所需要的时间叫机器周期,根据不同的板子它的机器周期不同
指令周期:是指完成一条指令所需要的时间, 取址-解析-执行所需要的时间。通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令
rigester修饰的变量不能取地址
volatile 防止编译器优化:有时候编译器会将一个地址当成寄存器的值。为了防止出错需要用volatile来修饰该变量。
中断和异常:异常是系统内部的,是发生错误时产生的,而中断大部分是人为的,属于外部发送的是有需求的
查找:
参数带##和#时define是不会展开的
STM32_day1
【1】课程介绍
1. 51 -- 8位单片机
32 -- 32位: 处理数据的宽度是32位 效率高速度快
2. 物联网IOT
工业自动化 -- 工业物联网(4.0) 可编程逻辑控制器(PLC) 机械臂(ABB) 无人机(UAV drone) 京东仓库
医疗 心电图 音视转化 脑电波控制
农业 智慧农业 智能大棚 果蔬溯源 机械采摘
家用 智能家居(小米) 安防 智能供配电
消防 云消防
为什么32? STM32-GD32
3. 嵌入式硬件
C语言基础 计算机组成原理 数字模拟电路 --> 单片机 51 32融合软硬件(裸机 实时操作系统freeRTOS RThread) --> ARM高端处理器平台 移植linux
4. 什么叫学会32 -- 实现功能 学外设
电量显示 LED GPIO
报警功能 蜂鸣器 PWM
电池电压 ADC(模拟 - 数字)
显示信息(打印) UART
时间显示 RTC
按键功能 按键中断
自动重启 WDT
计步功能 加速度传感器(陀螺仪) I2C
5. 7天
入门 基础ARM 开发环境搭建
GPIO UART
提升 中断 时钟系统 ADC+DMA SPI+液晶
6. 开发板观察
芯片:chip
片上系统:soc - system on chip 单个芯片上集成一个完整的计算机系统
最小系统板:CPU 晶振(需要起振 为系统提供基本的时钟信号【*】) 电源 复位 RAM(随机存储器) ROM(只读存储read only)
核心板:CPU
底板:承载
开发板:学习用 外设功能全
PCB板: 电子硬件 AltiumDesigner(DXP) protell
【*】
1. 机器周期 执行一个基本操作
指令周期 取指-解析-执行需要的全部时间
时钟周期 振荡周期 时钟频率的倒数 周期(S)=1/频率(HZ) 时间的量
指令周期 > 机器周期
2. 单片机工作原理
1)PC程序计数器 CPU读取指令的时候知道在什么位置
2)指令解码电路 从内存中读指令的含义
3)运算电路(ALU) ANR OR 门电路实现的
4)CPU内部寄存器 临时存储信息的场所
7. 传感器
检测部分:
可燃气体传感器MQ-5
红外感应 火焰传感器 温湿度传感器DHT11(数字)
光电开关 触摸按键 光敏电阻(随光强增大阻值减小 压敏 热敏 气敏) 超声波 电位器(滑动变阻器)
控制部分:
继电器 蜂鸣器(无源) 风扇 舵机(SG90) 水泵 电机
通信:
NBIOT WiFi
【2】 理论讲解
1. stm32f051k8 - contexM0
ST意法半导体
M micro-eletonics
32 - 32位 (STM32 STM8家族)
f foundition基础的 w-wireless l-low低功耗
051入门级别 103主流接入型 407高性能
k pin count: k/6 32pin c/8 48pin
8 code size: 64kbyets
2. STM32最主要的CPU部分使用的是ARM的核
[面试题] 谈谈你对arm的理解?
1. arm是一个公司 只做技术服务 不生产也不出售芯片 16年被软银收购 (*NXP恩智浦-飞思卡尔 新唐科技nutovon TI德州仪器)
2. arm代表一门技术 精简指令集【*】
精简指令集RISC和复杂指令集CISC有什么区别?
3. arm处理器
3. ARM体系架构发展
V1-V3最早的版本 现在已经废弃
V4-V6经典处理器运用的比较多
V7-Contex系列使用的架构 支持Thumb-32位指令集【*】
V8-支持Thumb-64位指令
ARM指令集:ARM指令是32位的指令,编代码全部是 32bits 的,每条指令能承载更多的信息,因此使用最少的指令完成功能, 所以在相同频率下运行速度也是最快的, 但也因为每条指令是32bits 的而占用了最多的程序空间。
Thumb指令集:Thumb指令是16位的指令长度,编代码全部是 16bits 的,每条指令所能承载的信息少,因此它需要使用更多的指令才能完成功能, 因此运行速度慢, 但它也占用了最少的程序空间,但是Thumb指令集中的数据处理指令的操作数仍然是32位,指令地址也为32位,并且有些处理器可以根据指令译码器将Thumb指令转换为32位的ARM指令
cortexM0只支持thumb指令集
Thumb-2指令集:Thumb-2指令集是16+32混合,在前面两者之间取了一个平衡, 兼有二者的优势, 当一个 操作可以使用一条 32bits指令完成时就使用 32bits 的指令, 加快运行速度, 而当一次操作只需要一条16bits 指令完成时就使用16bits 的指令,节约存储空间。
*
三星: SP6818 A53 arm-v8
高通: 骁龙865 855 arm-v8
华为: 麒麟980 arm-v8
飞思卡尔: IMX6 arm-v7
4. 早期经典处理器 ARM7 ARM9 ARM11之后都叫cortex系列
取指 - 译码 - 执行
arm7: 三级流水线 冯诺依曼结构 程序指令和数据存储混合
arm9: 五级流水线 哈弗结构 程序指令和数据存储分开
cortex-M 低成本优化方案 智能家居周边产品
cortex-A 跑操作系统 高性能 电视手机
cortex-R realtime实时系统 汽车制动 动力系统
实时和分时操作系统?
分时: windows linux 流行的PC和服务器 CPU划分时间片处理
实时: 用在单片机 PLC
5. CortexM0体系
1) 结构框图
线程模式 Thread 芯片复位之后执行用户程序
处理模式 Handler 处理器发生异常或者中断
两种工作状态
thumb状态 处理器正常运行
调试状态 调试程序时候的状态
3)内部寄存器
R0-R12 13个通用寄存器
R13 栈指针寄存器 SP
R14 链接寄存器 LR
R15 程序计数器 PC
xPSR : APSR 应用PSR
IPSR 中断PSR
EPSR 执行PSR
4)cortexM0中断和异常
最多支持32个外部中断(IRQ)和一个不可屏蔽的中断(NMI)同时支持多种系统异常(Reset hardFault Systick)
【3】 安装环境
1. keil MDK-ARM 注册机
2. STM32CubeMX 加载固件库
3. STLink驱动
【4】存储器映射
1. GPIOA地址0x2800 0000 -- 不正确(手册印刷错误)
真正的地址是?
在application/user/core - main.c下的stm32f51x8.h里面找到真正的地址是:0x48000000
#define GPIOA_BASE (AHB2PERIPH_BASE + 0x00000000UL)
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL)
#define PERIPH_BASE 0x40000000UL
#define FLASH_BASE 0x08000000UL
#define FLASH_BANK1_END 0x0800FFFFUL -- FLASH大小:64K
#define PERIPH_BASE 0x40000000UL //外设基地址
MODER 0x00 0x2800 0000
OTYPER 0x04 0x2800 0004
OSPEEDR
PUPDR
IDR
ODR
BSRR
LCKR
对地址进行宏定义
#define GPIOA_BASE ((unsigned int)0x28000000)
#define GPIOA_ODR (GPIOA_BASE + 0x14)
读操作
val = *(unsigned int*)GPIOA_ODR
写操作
*(unsigned int*)GPIOA_ODR = val
改进
#define GPIOA_ODR (*(unsigned int*) (GPIOA_BASE + 0x14))
val = GPIOA_ODR
GPIOA_ODR = val
利用结构体把地址封装
typedef struct{
uint32_t MODER;
uint32_t OTYPER;
uint32_t OSPEEDR;
uint32_t PUPDR;
uint32_t IDR;
uint32_t ODR;
uint32_t BSRR;
uint32_t LCKR
}GPIO_TypeDef;
#define GPIOA_BASE ((unsigned int)0x28000000)
#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)
GPIOA->ODR = 0x20;
3. startup_stm32f051x8.s - 汇编文件 启动代码
Stack_Size EQU 0x400 //定义栈的大小是1K
AREA STACK, NOINIT, READWRITE, ALIGN=3
//AREA定义一个地区,没有初始化的栈,可读可写,起始地址是8的倍数
__initial_sp //是一个标号 指向栈顶
Heap_Size EQU 0x200 //定义堆的的大小是512B
__heap_base //堆的其实地址
Heap_Mem SPACE Heap_Size //堆的空间
__heap_limit //堆的结束地址
AREA RESET, DATA, READONLY //定义一只读数据的区间
EXPORT __Vectors //声明全局标号 __Vectors在其他文件可以引用
DCD __initial_sp //栈顶的地址
AREA |.text|, CODE, READONLY //一般代表代码段
IMPORT __main //表示函数是调用其他文件的
LDR R0, =SystemInit //系统上电复位之后第一个执行的程序 初始化时钟
LDR R0, =__main
//__main是一个标准的C库函数 作用是初始化用户堆栈 在这个函数的结尾会调用main函数
1 byte(B) = 8 bits(b) 八个二进制
1K = 1024byte 1M 1G 1T
【5】拓展补充
1. targer
ROM : 0x10000 = 64K
RAM : 0x200 = 8K
c/c++
USE_HAL_DRIVER,STM32F051x8
#if defined (USE_HAL_DRIVER)
#include "stm32f0xx_hal.h"
#endif /* USE_HAL_DRIVER */
STM32F051x8: 是指flash大小不同
STM32F10X_LD 16-32K
STM32F10X_MD 64-128K
STM32F10X_HD 256-512K
2. 手册架构图2.1
总线矩阵: 协调内核系统总线和DMA总线的访问
AHB: 高速高性能总线
APB:外设总线
AHB2APB bridge: AHB桥 在AHB和APB之间提供同步连接,因为AHB和APB的频率不同
* ICode DCode
3. 位操作
清零 与0清0
num & (~(1<
置1 或1清1
num | (1<
位域: [7:4] 0101 先清0再置1
num & (~(0xf<<4)) | (0x5<<4)
取出某一位的状态
num & (1<<4)
4. # ##用法
#把宏参数变为一个字符串
##把两个宏参数链接在一起
#define STR(s) #s
#define CON(a,b) (int)(a##e##b)
main()
{
printf(STR(bck)); //输出字符串"bck"
printf("%d\n",CON(2,3); //2e3 = 2000
}
5. union联合体/共用体
union 名字{
成员1;
...
};
1)判断大小端
uinon aa{
unsigned char a;
unsigned int b;
};
union aa tt;
tt.b = 0x12345678;
if(tt.a == 0x78) //小端
(tt.a == 0x12) //大端
2)结构体里做差异
struct aa{
int a;
union{
char b;
char c;
}
int d;
}
6.
typedef unsigned int uint32_t;
#define __I volatile const
#define __O volatile
#define __IO volatile
存储类型
1)auto 自动
auto int a; //声明一个自动类型的变量
局部变量在不加auto的时候默认就是自动类型
非自动类型: 1. 全局变量 2.static修饰
2)register 寄存器类型
变量执行的效率高 修饰的变量不能取地址(内存上的变量才取地址)
3)static
延长声明周期
限定作用域 只能在本文中使用
4)extern
声明函数或者变量是在其他文件中定义的
5)const
修饰的是只读变量
const修饰的全局变量.ro
const修饰的局部变量在栈上
const int a = 10; //a是一个只读 不允许修改(不要拿指针去修改)
const int *p // const修饰的是*p 指针指向的内容不能改 指针可以改
int const *p // 和上面一样 const在谁前面 谁就不能改
int * const p //指针不能改
const int * const p //*p p都不能改
6) volatile
1. 防止编译器优化
int a;
a=100; // a=1;
...
a=200; // a=0;
2. 每次从内存里面拿最新的值,不从寄存器或者缓存里面拿
适用情况:
1. 多线程访问同一个变量
2. 中断状态寄存器(通过指针访问硬件地址)
3. 中断中访问非自动类型的变量(全局或者static修饰的)
[笔试]请向0xaaaabbbb地址中写入数据0x12345678i
int *a = (int *)0xaaaabbbb;
*a = 0x12345678;
#define CON (*((volatile int *)0xaaaabbbb))
CON = 0x12345678;