直接通过地址常量对应给寄存器赋值的方式是最简捷的方式,但程序的可读性极差(不容易地址常量值得知是对应哪个寄存器),程序的可移植性差,为了提高程序的可读性和可移植性,通常预定义符号常量和符号变量。
void SystemInit() { } void delay(int t) { int i; for( ;t>0; t--) for(i=0;i<1000;i++); } int main() {
*((unsigned int *)0x40021018) |= 0x1<<4; //开启GPIOC时钟 *((unsigned int *)0x40011000) &= ~(0x0F<<(4*0)); //对GPIOC_0设置为通用推挽输出,最大速度50MHz *((unsigned int *)0x40011000) |= (0x03<<(4*0)); while(1) { *((unsigned int *)0x40011010) |= 0x01<<(16+0); //对GPIOC_0复位 delay(1000); *((unsigned int *)0x40011010) |= 0x01<<(0+0); //对GPIOC_0置位 delay(1000); } } |
对上述main.c程序进行如下改进:
1、在user文件夹下新建一个stm32f10x.h文件,其内容为:
#define PERIPH_BASE ((unsigned int)0x40000000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) #define GPIOC_CRL *(unsigned int *)(GPIOC_BASE +0x00) #define GPIOC_CRH *(unsigned int *)(GPIOC_BASE +0x04) #define GPIOC_IDR *(unsigned int *)(GPIOC_BASE +0x08) #define GPIOC_ODR *(unsigned int *)(GPIOC_BASE +0x0C) #define GPIOC_BSRR *(unsigned int *)(GPIOC_BASE +0x10) #define GPIOC_BRR *(unsigned int *)(GPIOC_BASE +0x14) #define GPIOC_LCKR *(unsigned int *)(GPIOC_BASE +0x08) #define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000) #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define RCC_APB2ENR *(unsigned int *)(RCC_BASE + 0x18) |
定义这些标示符后,可以通过对GPIOC_CRL等表示符直接赋值给相应寄存器。
2、在main.c中包含上述头文件,并使用对应表示符操作寄存器
#include "stm32f10x.h" void SystemInit() { } void delay(int t) { int i; for( ;t>0; t--) for(i=0;i<1000;i++); } int main() {
RCC_APB2ENR |= 0x1<<4; //开启GPIOC时钟 GPIOC_CRL &= ~(0x0F<<(4*0)); //对GPIOC_0设置为通用推挽输出,最大速度50MHz GPIOC_CRL |= (0x03<<(4*0)); while(1) { GPIOC_BSRR |= 0x01<<(16+0); //对GPIOC_0复位 delay(1000); GPIOC_BSRR |= 0x01<<(0+0); //对GPIOC_0置位 delay(1000); } } |
这种方式下,通过标示符可以知道对应哪个寄存器,方便编程和程序阅读。