接着上文,我们对点灯项目做了初步的实现。
但由于如果我们每次都使用上文的方法去实现我们需要的东西,会十分繁琐,且32单片机相比于51单片机,寄存器数量多很多。所以我们需要借助ST提供的标准库,来完成开发,以提高我们的开发效率。
上文我们提到使用以下代码来实现点灯。
#include <stdint.h>
int main(void)
{
//1.时钟配置
*(uint32_t *)(0x40021000 + 0x18) = 0x04;
//2.GPIO工作模式的配置
*(uint32_t *)(0x40010800 + 0x04) = 0x03;
//3.端口给信号
*(uint32_t *)(0x40010800 + 0x0C) = 0xfeff;
while(1){}
}
我们借助标准库 #include "stm32f10x.h" 这个头文件里面已经编写好了相关寄存器的名称,我们不需要去记相关寄存器地址,只需记住寄存器相关名称,用结构体指针的方式,指针访问结构体成员。有兴趣的小伙伴可以查看一下stm32f10x.h文件代码。
#include "stm32f10x.h"
int main(void)
{
// //1.时钟配置
// *(uint32_t *)(0x40021000 + 0x18) = 4;
// //2.GPIO工作模式的配置
*(uint32_t *)(0x40010800 + 0x04) = 0;
// *(uint32_t *)(0x40010800 + 0x04) = 3;
// //3.端口给信号
// *(uint32_t *)(0x40010800 + 0x0C) = 0xfeff;
//代码优化
RCC->APB2ENR = 0x04;
GPIOA->CRH = 0x03;
GPIOA->ODR = 0xfeff;
while(1)
{
}
}
以这样的方法赋予寄存器值,能够更高效开发,并提高代码的可读性。
由于上述代码,直接对寄存器每一位都进行了修改。我们可以通过位与,位或的形式置零,置一,只改变寄存器的单独一位。从而保证寄存器单独每一位功能的完整性。如下:
#include "stm32f10x.h"
int main(void)
{
RCC->APB2ENR |= (1<<2);
//GPIO工作模式 11最大输出模式
GPIOA->CRH |= ((1<<0) | (1<<1));
//GPIO输出模式 00推挽输出
GPIOA->CRH &= ~((1<<2) | (1<<3));
GPIOA->ODR &= ~(1<<8);
while(1)
{
}
}
这个相当于在做左移后,位与,位或的操作,不太熟悉的小伙伴可以借助稿纸,或者程序员计算器,进行推导,或者查找相关资料熟悉一下。实在是不懂的小伙伴也不用着急,标准库里还提供了这些寄存器功能开启的宏定义。我们只需要知道我们要开启的功能名称即可。操作如下:
#include "stm32f10x.h"
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRH &= ~GPIO_CRH_CNF8;
GPIOA->CRH |= GPIO_CRH_MODE8;
GPIOA->ODR &= ~GPIO_ODR_ODR8;
while(1)
{
}
}
这样的写法才符合我们开发的需求。以上代码均经过验证无误。如有问题欢迎留言询问。