直接调用定义好的文件来编程是很方便,但对于初学者很难理解,正所谓,学从难处学,用从易处用,今天看一下只需要启动文件和主函数点亮LED灯的方法。
一、创建一个文件
创建一个文件用来保存我们的工程。打开我的电脑在内存较多的盘里创建一个文件夹,记住这个文件夹的路径。
二、在keil中创建工程
1.打开keil5,找到Project。
2.点击Projict选择New μVision Project…
3.找到我们第一步里创建的文件,把工程放在创建的文件里,然后选择自己使用的芯片,我这里选的是STM32F103ZE。
4.创建一个文件命名为main.c并保存。
5.将启动文件放入到第一步新建的文件夹内。
6.向工程里添加启动文件和main.c文件。
7.可以看到右侧出现了两个文件,一个main.c文件和启动文件
8.在工程面板里也有了这两个文件,到这我们的准备工作就做完了,开始讲解如何点亮LED灯。
三、点亮LED灯的流程和寄存器讲解
1.点亮流程
想让小灯亮起来,我们得有以下三个步骤:
(1)使能GPIO口(为节能,STM32时钟默认都是关闭的,需手动开启)
(2)初始化GPIO口(选择模式)
(3)点亮LED灯。
2、RCC_APB2ENR(外设时钟使能寄存器)
想打开时钟,我们得知道GPIO口是挂在哪
通过数据手册可以看到,GPIO口都是挂在APB2上,所以我们得打开APB2的时钟。
可以看到,在这个寄存器里,2~8位分别控制GPIOA~GPIOG,哪个位 置1,就开启了对应GPIO口的时钟,相反置 0 就是关闭了时钟。
//对于不同的开发板,灯的连接IO口不一样
//我使用的开发板LED连接在GPIOB和GPIOE上
RCC_APB2ENR|=1<<3; //使能GPIOB口
3、GPIOx_CRL(端口配置低寄存器)/GPIOx_CRH(端口配置高寄存器)
GPIO口有八种模式:
─ 输入浮空
─ 输入上拉
─ 输入下拉
─ 模拟输入
─ 开漏输出
─ 推挽式输出
─ 推挽式复用功能
─ 开漏复用功能
如何配置这些功能?我们来看这个寄存器:
图里标注出了,0~3位控制 0 号引脚,4~7位控制1 号引脚,依次类推,端口低位配置寄存器控制0~7号引脚,端口高位配置寄存器控制8~15号引脚,两个寄存器配置方式一样,我们先配置MODE,再配置CNF,我们在点灯时需要设置推挽输出,先配置MODE就是10,再配置CNF就是00,所以,给哪个引脚设置0010,哪个引脚就是推挽输出。
在这,说明一下,引脚是复位值是0x44444444,也就是复位后为浮空输入,我们要设置PB5推挽输出,所以我们得用GPIOB_CRL&=0xFF0FFFFF; 将需要设置的位清零,如若不清零,在设置后GPIOB_CRL的值实际上为0x44644444;可以看到,它是开漏输出。
GPIOB_CRL&=0xFF0FFFFF; //复位值是0x44444444,我们得把需要设置的引脚先置 0 再设置
GPIOB_CRL|=0x00200000; //PB5推挽输出模式
3、BSRR、BRR、ODR
(1)GPIOx_BSRR(位设置/清除寄存器)
BSRR寄存器低15位置 1 是设置输出高电平,高15位置 1 是设置输出低电平。
GPIOB_BSRR|=1<<5; //PB5输出高电平
GPIOB_BSRR|=1<<21; //PB5输出低电平
(2)GPIOx_BRR(位清除寄存器)
BRR寄存器只能用来清除,也就是如果低15位置 1 是输出低电平,高15位是保留的。
GPIOB_BRR|=1<<5; //PB5输出低电平
(3)GPIOx_ODR(端口输出数据寄存器)
和BSRR类似,低15位置 1 输出高电平,置 0 输出低电平,高15位保留。
GPIOB_ODR|=1<<5; //PB5输出高电平
GPIOB_ODR|=~(1<<5); //PB5输出低电平
点亮LED灯需要根据线路来确定
我的开发板上是低电平亮,高电平灭。
四、寄存器地址查询
寄存器地址可以在STM32参考手册里找到,在存储器映像中
每个寄存器都有偏移地址,初始地址+偏移地址就是这个寄存器的地址。
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)//RCC_APB2ENR寄存器地址
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)//GPIOB_CRL寄存器地址
#define GPIOB_BSRR *((unsigned volatile int*)0x40010C10)//GPIOB_BSRR寄存器地址
#define GPIOB_BRR *((unsigned volatile int*)0x40010C14)//GPIOB_BRR寄存器地址
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)//GPIOB_ODR寄存器地址
需要哪个寄存器我们就按上边定义寄存器地址
五、总程序
//程序实现点亮PB5 LED灯
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)//RCC_APB2ENR寄存器地址
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)//GPIOB_CRL寄存器地址
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)//GPIOB_ODR寄存器地址
int main()
{
RCC_APB2ENR|=1<<3; //GPIOB时钟使能
GPIOB_CRL&=0xFF0FFFFF; //引脚初始化
GPIOB_CRL|=0x00200000; //PB5推挽
GPIOB_ODR|=1<<5; //若LED低电平亮,设置推挽输出后LED灯就会亮,所以这先设置输出高电平,让灯灭
while(1) //不设置死循环,程序运行结束,灯只亮一下
{
GPIOB_ODR|=~(1<<5); //输出低电平,灯亮
}
}
六、总结
其实调用库文件写程序和定义好的寄存器文件写程序,都是对寄存器的操作,就是人家给你提前定义好了,你只需要调用文件就行了,我这样写出来,对寄存器操作更直观,能够让初学者不再困惑对于寄存器的操作,到这既然点亮了一个LED,那做流水灯也已经很容易了,只需要再点亮一个LED,并让两个灯一亮一灭,就能达到流水灯的效果,操作蜂鸣器也呼之欲出,因为都是GPIO口输出。
初学STM32,也是第一次发博客,不正确的地方敬请指教~~~
转载:https://blog.csdn.net/gelad_w/article/details/115429648