前言:学就要学懂,别以为做出来就行,要弄懂通路,思路要清楚-谨记
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 ,也就是图中的地址
未完待续。。。



















