> 文章列表 > 【梦回stm32】-寄存器篇-跑马灯代码研读-总结

【梦回stm32】-寄存器篇-跑马灯代码研读-总结

【梦回stm32】-寄存器篇-跑马灯代码研读-总结

前言:学就要学懂,别以为做出来就行,要弄懂通路,思路要清楚-谨记

 

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  ,也就是图中的地址

未完待续。。。