类比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中输入如下程序。
编程下载到开发板观察到实验现象。