#define GPIOB_CLK (*(volatile unsigned int *)(0x40021000+0x18))
#define GPIOB_CRL (*(volatile unsigned int *)(0x40010C00+0x00))
#define GPIOB_ODR (*(volatile unsigned int *)(0x40010C00+0x0C))
int main(void)
{
//1、使能GPIOB的外设时钟GPIOB_CLK |= (1<<3);
//2、GPIOB配置推挽输出模式GPIOB_CRL &=~(0xf<<(4*0));GPIOB_CRL |=(2<<(4*0));GPIOB_ODR &=~(0x1<<(1*0));
// GPIOB_ODR |=~(1<<0);
}
The code analysis:
1、目的;点亮开发板上面的一个LED灯,但这个灯到底连接在开发板的那个引脚上面呢?
查找原理图可知:
它连接在GPIOB上面,分析电路图可知只要PB0输出为低电平,绿灯就会亮,PB5输出为低电平,红灯就会亮,PB1输出为低电平,蓝灯就会亮。所以我们要去找GPIOB
2、而要控制一个引脚点亮LED灯必不可少的是时钟,而控制时钟是总线的功能,所以要去查找该GPIOB所连接在那条总线上面。
查找STM32参考手册系统结构图得知GPIOB连接在AHB2总线上面。
3、而AHB2总线上面连接了很多外设,而我们只需要打开GPIOB的时钟,那我们就需要去查找AHB2的寄存器,去查看怎样打开GPIOB的时钟,查表如下要把位3设置为1就打开了GPIOB的时钟
4、现在把GPIOB的时钟打开了,但这只是让GPIOB能够工作了,我们是需要把灯点亮,就要使GPIOB输出低电平,而现在GPIOB只是能够工作了,而根据STM公司规定,引脚还要规定它的工作模式。
通过分析上图,我们知道它应该工作在输出模式,而GPIOB输出模式又细分为几种:
通过学的知识知道,开漏输出不好弄,所以就选择了推挽式输出。
5、
而配置GPIOB的时钟是在APB2的寄存器里面进行的,而配置GPIOB输出模式这些需要查找寄存器的端口配置表(同样在参考手册里面)
分析上表并结合查找可知:这四个是在下面这个寄存器里面的(我也不知道怎么得知是在这个寄存器里面的,野火没讲)
下面这个是在
为啥事这个寄存器呢?估计是字母相同吧,哈哈啊啊啊啊啊哈哈哈哈哈哈哈哈哈哈。
最后操作的是
最后一位(这个我也不晓得为啥操作这一位,而不是其他位)
6、
```c
#define GPIOB_CLK (*(volatile unsigned int *)(0x40021000+0x18))
这个使用了宏定义:那为啥取这个宏定义名字呢?可能是官方就是这么取的吧(我现在都傻了,感觉自己现在就是个无情的学习机器,毫无 感情,哈哈哈哈哈哈哈哈哈哈哈哈哈哈)。
volatile:加这个是防止编译器对于代码的优化(编译器会对我们写的所有代码进行优化,如果没有加volatile这个单词的话)。
unsigned:------地址没有负数所以加无符号整数。
0x40021000(基地址):查找参考手册知道的0x18(偏移地址):查找参考手册知道的7、```c
#define GPIOB_CRL (*(volatile unsigned int *)(0x40010C00+0x00))
0x40010C00(基地址):
0x00(偏移地址):
8、
#define GPIOB_ODR (*(volatile unsigned int *)(0x40010C00+0x0C))
0x40010C00:
0x0C:
9、
GPIOB_CLK |= (1<<3);
10、
GPIOB_CRL &=~(0xf<<(4*0));//清除低四位寄存器
防止之前的内存存储有脏数据
GPIOB_CRL |=(2<<(4*0));
11、
GPIOB_ODR &=~(0x1<<(1*0));