类比51单片机写法
在学51单片机的时候,我们第一句是#include<reg52.h>。关于基础部分,大家可以看我的51单片机部分,很详细,这里不具体展开。
在第5小节中零零碎碎讲了一些地址,这节课逻辑性的讲一下。
在stm32芯片手册中可以看到(P28),一共4G大小,地址范围0x0000 0000到0xFFFF FFFF,分成8个块(Block0~Block7),每块大小为512M。
在第4小节中我们用到了block2,具体看下block2的内容(参考stm32f10x系列参考手册)
可以看到一共有3条总线:APB1、APB2、AHB。
| 总线名称 | 总线基地址 |
|---|---|
| APB1 | 0x4000 0000 |
| APB2 | 0x4001 0000 |
| AHB | 0x4001 8000 |
其实APB1、APB2和AHB都是在外设地址(0x4000 0000)偏移,分别偏移0x0,0x0001 0000和0x0002 0000。
那么定义
#define PERIPH_BASE 0x4000 0000 //总线基地址 #define APB1PERIPH_BASE PERIPH_BASE #define APB2PERIPH_BASE (PERIPH_BASE+0x00010000) #define AHBPERIPH_BASE (PERIPH_BASE+0x00020000)看到GPIOC在APB2上偏移0x0001 0000。
定义
#define GPIOC_BASE (APB2PERIPH_BASE+0x00010000)再看下GPIOC相关寄存器
都是在GPIOC_BASE的基础上偏移地址,每次都是4个字节(32位)。
所以定义
#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+0x18)接下来配置时钟地址
根据地址分配可得
#define RCC_BASE (AHBPERIPH_BASE+0x1000)
根据上图可知,RCC_APB2ENR是在RCC基础上偏移0x18
所以
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)以上讲了那么多无非是把上节课程序中的
*(unsigned int*)0x4002 1018 *(unsigned int*)0x40011004 *(unsigned int*)0x40011004 *(unsigned int*)0x4001 100C讲解更能清楚,我们不希望在main函数中出现类似0x4002 1018的地址,而使用可读性更好的英文单词来表述。因此仿51单片机的写法,把一些地址定义放在头文件stm32f10x.h中。
//头文件stm32f10x.h #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) /* AHB总线基地址 */ #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) /*GPIOC外设基地址*/ #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) /* GPIOC寄存器地址 */ #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+0x18) /*RCC外设基地址*/ #define RCC_BASE (AHBPERIPH_BASE + 0x1000) /*RCC的AHB2时钟使能寄存器地址*/ #define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)那么在main函数中可以写成
#include “stm32f10x.h” int main(void) { RCC_APB2ENR |= 1<<4; GPIOC_CRH &=~(0x0F<<(4*5)); GPIOC_CRH |=(1<<(4*5)); GPIOC_ODR &=~(1<<13); while(1); } void SystemIinit() { }接下来做实验,在文件夹中新建文件“stm32f10x.h”。
将头文件添加到Keil工程中,添加方式参考添加启动文件的过程。打开头文件,输入如下程序。
在main.c中输入如下程序。
编程下载到开发板观察到实验现象。