类比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。

总线名称总线基地址
APB10x4000 0000
APB20x4001 0000
AHB0x4001 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中输入如下程序。
在这里插入图片描述
编程下载到开发板观察到实验现象。

更多推荐