前言:学就要学懂,别以为做出来就行,要弄懂通路,思路要清楚-谨记
1.先讲讲背景,此次需要研究的是stm32的跑马灯代码,下图是个本实验用的正点原子的代码目录
1)HARDWARE-》LED
2)SYSTEM-》delay/sys/usart
3)USER-》test.c
2.首先我们看下最简单的目录,LED模块,LED模块只有led.h和led.c文件
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
//LED端口定义
#define LED0 PAout(8) // PA8
#define LED1 PDout(2) // PD2
void LED_Init(void); //初始化
#endif
led.c
#include "sys.h"
#include "led.h"
//初始化PA8和PD2为输出口.并使能这两个口的时钟
//LED IO初始化
void LED_Init(void)
{
RCC->APB2ENR|=1<<2; //使能PORTA时钟
RCC->APB2ENR|=1<<5; //使能PORTD时钟
GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;//PA8 推挽输出
GPIOA->ODR|=1<<8; //PA8 输出高
GPIOD->CRL&=0XFFFFF0FF;
GPIOD->CRL|=0X00000300;//PD.2推挽输出
GPIOD->ODR|=1<<2; //PD.2输出高
}
3.准备开始啦
我们先来看下led.h文件
#define LED0 PAout(8)
#define LED1 PDout(2)
这里定义了两个IO,一个是LED0和一个LED1,分别代表了PA8和PD2 GPIO端口,我们来看看它们是怎么定义的吧,我们跳转到sys.h文件中,可以看到
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
那BIT_ADDR()又是怎么定义的?
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
| | | // 那MEM_ADDR()和BITBAND()怎么定义的,往下看
V V V
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
可以看出它们都在sys.h中定义的
还有GPIOA_ODR_Addr和GPIOD_ODR_Addr是怎么定义的,当然,这个也是在sys.h中定义的
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
这样GPIO端口的地址就清晰了
我们来看看芯片数据手册里面的存储映像,看下stm32F103RCT6的
我们可以看到红框框里写的Port A ,其实就是GPIOA,左边是它的地址,可以看出这个地址和上面咱们看到的地址是接近的
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
再接着看,那GPIOA_BASE是什么呢
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
然后就是APB2PERIPH_BASE,这个就是APB2的基地址
/*!< Peripheral memory map */
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
| | | //PERIPH_BASE
V V V
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
stm32f10x.h中定义
所以GPIOA_BASE就是 0x40000000 + 0x10000 + 0x0800 ,也就是图中的地址
未完待续。。。