=============================
2022-8-19
=============================
一.温故知新
1.GPIO的输出实验->蜂鸣器
2.GPIO的输入实验->功能按键
检测按键是否被按下
(轮询 和 中断)
3.更换开发方式->调用ST公司的LIB库
4.演示STM32CUBEMX工具的使用
二.位带(bitband)
位带可以以原子操作的方式操作寄存器中的某些位
1.引出位带
----------------------------------------------------
例子 :
想要把十进制整数100,赋值到0x12345678地址中?
*(volatile unsigned int *)(0x12345678) = 100;
一次性操作32bit
----------------------------------------------------
例子:
想要把0x12345678地址中的第9bit,置1
*(volatile unsigned int *)(0x12345678) |= (1 << 9);
想要把0x12345678地址中的第8bit,清0
*(volatile unsigned int *)(0x12345678) &= ~(1 << 8);
一次操作1bit
----------------------------------------------------
但是上述直接给某一个位赋值的操作,不是原子操作
原子操作 : 就是不可分割的操作,原子操作在执行结束前,
不会被任何信号或者任何中断打断
2.介绍位带
位带并不是C语言提供的,是硬件提供的,并不是STM32芯片提供的,
而是由ARM-CORTEX-M3的核心提供的
----------------------------------------------------
位带和位域有点类似
----------------------------------------------------
打开<STM32RBT6\DataSheet\ARM-CORTEX-M>目录下
<Cortex-M3权威指南CnR2(电子书).pdf>
P83 查看存储器的映射
ARM-CORTEX-M3支持访问4Gb的空间大小(物理的空间)
只有片上SRAM开头的1Mb空间和片上外设的1MB空间支持位带访问
位带的操作其实
就是把位带区中的每一位都做一个地址别名,映射到位带别名区
将来在访问位带别名区的空间时,就相当于是在访问位带区中某一位
位带区的空间有1M个字节,等于有8M个位,每一位都做一个地址别名映射到
位带别名区,映射的地址需要以4字节的方式对齐,所以
位带区的1MB会在位带别名区膨胀成32MB
虽然片上SRAM和片上外设都支持位带访问,
但是片上外设的位带操作会用的更多一些(尤其是GPIO的输入与输出)
3.位带转换的表达式
可以把位带转换的操作封装成宏函数
#define BITBAND(ADDR, BITNUM)
((ADDR&0xF0000000)+0x2000000+((ADDR&0xFFFFF)<<5)+(BITNUM<<2))
#define MEM_ADDR(ADDR) *(volatile unsigned int *)(ADDR)
#define BIT_BAND(ADDR,BITNUM) MEM_ADDR(BITBAND(ADDR, BITNUM))
#define GPIOA_IDR (GPIOA_BASE + 0x08)
#define GPIOA_ODR (GPIOA_BASE + 0x0C)
#define GPIOB_IDR (GPIOB_BASE + 0x08)
#define GPIOB_ODR (GPIOB_BASE + 0x0C)
#define GPIOC_IDR (GPIOC_BASE + 0x08)
#define GPIOC_ODR (GPIOC_BASE + 0x0C)
#define GPIOD_IDR (GPIOD_BASE + 0x08)
#define GPIOD_ODR (GPIOD_BASE + 0x0C)
#define PAOut(BITNUM) BIT_BAND(GPIOA_ODR, BITNUM)
#define PAIn(BITNUM) BIT_BAND(GPIOA_IDR, BITNUM)
PAOut(9) = 1;//把PA9管脚拉高
PAOut(8) = 0;//把PA8管脚拉低
ret = PAIn(0);//读取PA0管脚的电平高低
4.在项目工程中引入位带的操作
三.定时器
流水灯的程序中需要使用延时(精确延时 和 粗略延时)
精确延时需要使用定时器
无论何种定时器都是由两个因素来决定定时长短的
时钟频率 和 计数值
计数值 10 10 72000000 72000 72 72 / 1000
时钟频率 1Hz 10Hz 72MHz 72MHz 72MHz 72MHz
定时时间 10s 1s 1s 1ms 1us 1ns
1s = 1000ms = 1000000us = 1000000000ns
四.系统定时器
通过最新选型手册可知,在STM32芯片中有非常丰富的定时器资源
可以分为普通定时器和其他(特殊)定时器
除了STM32芯片为程序员提供了定时器资源以外,ARM-CORTEX-M3的核心
也为程序员提供了定时器的资源
由ARM核心提供的定时器资源叫做系统定时器(system timer | systick)
1.系统定时器的时钟频率
打开<STM32RBT6\DataSheet\STM32>目录下<STM32F10x中文参考手册.pdf>
P46
在STM32芯片中有多个时钟源
HSI 系统内部的高速时钟 8MHz
HSE 系统外部的高速时钟 8MHz
PLL 锁相环(倍频器) 72MHz
LSI 系统内部的低速时钟 40KHz
LSE 系统外部的低速时钟 32.768KHz
系统定时器的时钟频率 = SYSCLK / 8 或者 SYSCLK
SYSCLK的时钟 可以由 HSI 或者HSE或者PLL提供
已知HSI和HSE都是8MHz的时钟频率,都不足以达到72MHz
所以只能是由PLL为SYSCLK提供时钟频率
PLL是一个锁相环,是一个倍频器,本身是不会产生时钟频率的,
需要有基础的时钟频率才能进行倍频
PLL的基础时钟频率 可以由 HSI或者HSE来提供
默认会选择HSE为PLL提供基础的时钟频率
芯片外部的晶振产生的时钟频率要比芯片内部自己产生的时钟频率稳定的多
2.系统定时器的计数值范围
打开<STM32RBT6\DataSheet\ARM-CORTEX-M>目录下
<Cortex-M3权威指南CnR2(电子书).pdf>
P189
控制及状态寄存器
第0位 开启系统定时器的计数
0:关闭 1:开启
第1位 是否触发中断
0:不触发 1:触发
第2位 时钟源的选择
0:外部的 1:内部的
第3-15位 保留
第16位 用于判断计数器是否计数到0
第17-31位 保留
重装载值寄存器
第0-23位 用来存放重装载值
第24-31位 保留
当前值寄存器
第0-23位 用来存放当前计数值
第24-31位 保留
计数值的范围是[24个0 - 24个1](0 - 16M-1)
3.调用官方固件驱动系统定时器
官方提供的固件有问题
1)只有开启系统定时器,没有关闭系统定时器
2)默认开启了中断
==============================
作业
1.把这周讲过的内容完完整整的复习一遍
2.把这周写过的项目工程再重新写一遍
==============================