(本文仅为记录本人的学习过程以供个人复习、查询等。如有错误欢迎交流指正,本人不胜感激!)
目录
寄存器操作点亮led灯基本流程
开启使用PC13引脚对应的时钟——配置PC13引脚的输入或输出模式——输出低电平
软件/文件准备
在之前配置好的Keil5、STM32F10x参考手册。
硬件准备
STM32f103c6t6开发板(PC13连接着低电平触发的led灯)、ST-Link。
操作步骤
1、在储存器映像查找时钟控制寄存器的地址。
查找手册可得知时钟控制寄存器(RCC)在0x4002 1000处。
2、在APB2外设时钟使能寄存器的页面中进行查找
由页可知APB2外设时钟使能寄存器的偏移地址为0x18,同时在此地址的第四位控制IO端口C引脚的时钟。
由此页可知此地址第四位 置1时IO端口C时钟开启。
综上所述,在0x4002 1000+0x18=0x4002 1018地址处的第4位值为1时,IO端口C时钟开启。
3、在储存器映像的页面中进行查找GPIO端口C的地址。
由此页可知GPIO端口C的起始地址为0x400 1000。
4、在GPIO寄存器的页面中进行查找PC13引脚的位置。
(端口配置低寄存器设定0—7引脚,端口配置高寄存器设定8—15引脚)
由图可知,偏移地址位0x04。四位数字控制引脚的输入输出模式,我们需要输出模式和通用推挽输出模式(一般用这个)因此在23、22、21、20位应该分别是0、0、0、1。
5、配置PC13端口输出低电平。
由于我们要PC13端口输出低电平,因此需要查阅端口输出数据寄存器。
由此页面可得知地址偏移为0Ch(16进制),结合之前储存器映像端口C的基地址是0x4001 1000
可得出PC13端口输出低电平需将0x4001 1000 + 0Ch = 0x4001 100C 地址处的第13位改为0。
通过以上步骤我们总结出如下代码:
int main()
{
*(unsigned int*)0x40021018 |= (1<<4);//打开对应时钟
*(unsigned int*)0x40011004 &= ~(0x0f<<(4*5));//配置输出模式
*(unsigned int*)0x40011004 |= (1<<(4*5));
*(unsigned int*)0x4001100C &= ~(1<<13);//输出低电平
while(1);
}
void SystemInit(void)
{
}
注:1、 *(unsigned int*)0x4001100C &= ~(1<<13); 可以保持其他位置不变并改变第13位为0
2、创建项目时记得正确选择自己使用设备。
3、将启动文件加入项目中。
4、下方的while(1);和void SystemInit(void){} 保留就好,其原因可以之后再了解
附:地址相关
在M3内核中由4GB的地址空间,其中0x4000 0000—0x5FFF FFFF用于片上外设
基地址+偏移地址=所需要的地址
例:基地址:0x4002 1000+偏移地址:0x18 =所需地址:0x4002 1018,因此0x4002 1018是我们需要的地址。
STM32是32位的,即单位时间内(同一时间)能一次处理的二进制数的位数为32位,因此我们就是配置对应地址的32位二进制数来实现手册上的相应功能。
那么是如何通过编程来实现这些操作呢?
0x4002 1018一开始是一个16进制数字,通过(unsigned int*)0x4002 1018将这串数字变成一个指针。(unsigned int的意思是“无符整型”,表示从0开始到2^32-1的所有整数;加上“ * ”后就是定义一个unsigned int指针类型)而我们需要改变的是指针地址所对应的值,因此还要再前面加一个“ * ”就可以变为所对应的值。所以最后的语句为:
*(unsigned int*)0x40021018
那么接下来该如何改变其中的值呢?
一开始说STM32是32位,每个地址对应的值就是32位的二进制数字即
0000 0000 0000 0000 0000 0000 0000 0000
我们需要使用位操作&(与)、|(或)、<<(左移)、>>(右移)等来改变这个值。
比如我们需要将上面这个二进制数字的第4位改为1(地址的位置是0-31),那我们需要首先将1左移4位变为0001 0000即为:
从:0000 0000 0000 0000 0000 0000 0000 0001
到:0000 0000 0000 0000 0000 0000 0001 0000
然后使用变化后的数字与地址对应的值中每一位数字都与对应位数的数字进行“ 或 ”操作:
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0001 0000
↓
0000 0000 0000 0000 0000 0000 0001 0000
由此便可得到0000 0000 0000 0000 0000 0000 0001 0000
最后完整的语句为:
*(unsigned int*)0x40021018 |=(1<<4);
按照手册的提示,这个地址的第4位为1时 IO端口C 时钟开启。