本文内容基于https://www.bilibili.com/video/BV1Lx411Z7Qa
P11
GPIO工作模式:
输入模式1:浮空输入
输入模式2:输入上拉模式
输入模式3:输入下拉模式
由于浮空输入模式的电压不确定,容易误读,检测高电平时一般用输入下拉模式,检测低电平时一般用输入上拉模式。
输入模式4:模拟模式
输出模式1:开漏输出
输出控制电路输出1时,N-MOS断开,实际输出由外部上拉下拉决定,输出0时,N-MOS闭合,实际输出0,实际输出可以由输入数据寄存器读取
输出模式2:开漏复用输出模式
与开漏输出模式区别:输出来自片上的外设模块,而不是由CPU控制。
输出模式3:推挽输出模式
P-MOS与N-MOS同时参与控制,输出控制电路直接决定实际输出
输出工作模式4:推挽复用输出模式
输出来自外设
GPIO端口介绍:
BSRR寄存器可以单独设置ODR寄存器的其中一位,较为方便。由于ODR寄存器只能以字的形式操作,如果直接设置ODR寄存器则需要先读入ODR寄存器的值再改变其中的某一位。
P12
4个读取输入/输出电平函数有读取一位和读取整组的区别
先定义结构体变量,再逐个设置参数,具体的参数名称在函数中的有效性判断里,最后使用函数初始化IO口。
1.复制库函数工程模板
2.新建文件夹HAREWARE,子文件夹LED,并新建led.c,led.h
写头文件
3.新建分组HAREWARE,添加led.c
4.添加led.h
5.编译以便查看头文件
6.初始化时钟
方法一:
方法二:
由于操作的是同一个寄存器中不同的位,可以用或运算写
7.在led.c中写初始化程序
GPIO_Init()这个函数在stm32f10x_gpio.h头文件的最下方
先定义结构体变量,再逐个设置参数,配置好后使用函数初始化IO口。
初始化完成后使用置位函数将IO口设为高电平,使得初始化完成时LED熄灭
8.通过控制IO口输出控制LED灯,这里引入了延时函数
P13
1.创建工程
2.初始化IO口时钟
通过或运算设置寄存器,防止影响其它位
3.模式配置为推挽输出,并配置为输出为1,使得LED熄灭
与运算清0,或运算置1,防止影响其它位
5.写主函数
这里应改为GPIOB->ODR&=~(1<<5); GPIOE->ODR&=~(1<<5);
否则将改变其它位。
P14
这里通过宏定义将PAout(n)映射到ODR寄存器的特定位,具体过程为
PAout(n)
》》BIT_ADDR(GPIOA_ODR_Addr,n)
》》MEM_ADDR(BITBAND((GPIOA_ODR_Addr,n))
》》 MEM_ADDR(((GPIOA_ODR_Addr & 0xF0000000)+0x2000000+(( GPIOA_ODR_Addr &0xFFFFF)<<5)+(n<<2)))
》》*((volatile unsigned long *)(((GPIOA_ODR_Addr & 0xF0000000)+0x2000000+(( GPIOA_ODR_Addr &0xFFFFF)<<5)+(n<<2))))
最终的映射结果表明PAout(n)即是*(指向ODR寄存器的特定位的指针),改变PAout(n)的值即是改变ODR寄存器特定位的值
注:位带操作最终是操作了ODR、IDR寄存器,所以对应的IO口也需要先初始化
P15
三极管可以起到放大电流的作用。
R38电阻可以将小电流导入GND,防止浮空状态时蜂鸣器响。
P16
按键有两种,一种支持连续按,一种不支持
通过静态局部变量key_up保存按键是否被释放的信息,再通过一个if语句决定其是否生效,达到了两种模式合二为一的效果。
P17
增加结构体成员不影响其它代码,可扩展性强
GPIOA->ODR
》》((GPIO_TypeDef*)GPIOA_BASE)->ODR
这里GPIOA_BASE是一串地址常量,((GPIO_TypeDef*)GPIOA_BASE)将GPIOA_BASE强制转换为指向GPIO_TypeDef结构体变量首地址的指针变量 ,于是GPIO_TypeDef结构体变量首地址变成了GPIOA_BASE。
因为结构体中的变量按顺序存储在内存中,GPIOA系列寄存器的地址也按顺序排列在内存中,两者成一一对应的关系,所以改变结构体成员的值就是改变对应寄存器的值。