课程内容

描述文本。

STM32点亮一个灯

STM32学习笔记(一)——点亮一个LED

STM32的引脚

STM32的引脚叫GPIO(General-purpose input/output,通用型输入输出),功能类似8051的P0—P3

其接脚可以供使用者由程控自由使用,有8种输入输出模式(或者参考这个)

这些模式的电流输入输出能力不同,还有的具有额外的功能(比如AD)转换,这个根据具体应用场景具体选择

一个

 void GPIO_Config(void)                            //GPIO初始配置
{
    GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //使能GPIOD的时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                    //指定引脚13
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //设置输出速率50MHz
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出模式
    GPIO_Init(GPIOD, &GPIO_InitStructure);                            //初始化外设GPIOx寄存器
}

程序解析

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

这句话比较长,我们首先来逐个的分解一下其中的含义

  • RCC:reset clock control 复位和时钟控制器
  • APB:Advanced Peripheral Bus,即先进的外围(外设)总线.
  • Periph:外围的
  • clock:时钟的
  • cmd:command缩写,命令

这句话的意思是开启外设时钟,具体原因参见此链接

为了节省资源,STM32所有的时钟都是默认关闭的,因此要使用某个外设时,需要打开对应的时钟

控制灯亮的程序

GPIO_SetBits(GPIOD, GPIO_Pin_13) 

从寄存器来点亮一个LED

主程序如下

int main(void)
{				  
	Stm32_Clock_Init(9);
	delay_init(72);	  	
	LED_Init();		  
	while(1)
	{
		LED0=0;
		LED1=1;
		delay_ms(300);
		LED0=1;
		LED1=0;
		delay_ms(300);
	}	 
}

其中的LED初始化的程序如下

void LED_Init(void)
{
	RCC->APB2ENR|=1<<3;    //使能PORTB时钟  	 
	RCC->APB2ENR|=1<<6;    //使能PORTE时钟 
	   	 
	GPIOB->CRL&=0XFF0FFFFF; 
	GPIOB->CRL|=0X00300000;      //PB.5 推挽输出
	GPIOB->ODR|=1<<5;      //PB.5 输出高
											  
	GPIOE->CRL&=0XFF0FFFFF;
	GPIOE->CRL|=0X00300000;      //PE.5推挽输出
	GPIOE->ODR|=1<<5;      //PE.5输出高
}

首先对前两句进行分析

	RCC->APB2ENR|=1<<3;    //使能PORTB时钟  	 
	RCC->APB2ENR|=1<<6;    //使能PORTE时钟 

第一句的意思是把RCC的APB2ENR寄存器的第3位(从0开始计位)变为1

APB2ENR寄存器的第2-8位分别对应着ABCDEFG端口

APB2ENR是APB2 enable register,APB2总线的使能寄存器,所有的通用接口都有APB2总线负责

具体的RCC结构的定义如下所示。

//stdint.h
typedef unsigned int uint32_t;
#define  __IO  volatile
//stm32f10x.h
#define PERIPH_BASE           ((uint32_t)0x40000000)
#define AHBPERIPH_BASE       (PERIPH_BASE + 0x20000)
#define RCC_BASE             (AHBPERIPH_BASE + 0x1000)
#define RCC                 ((RCC_TypeDef *) RCC_BASE)
typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
} RCC_TypeDef;

接下来是对GPIO通用输入输出接口的配置

GPIOB->CRL&=0XFF0FFFFF; GPIOB->CRL|=0X00300000; //PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高

前两句是对GPIOB的CRL寄存器进行配置,具体是把PB5的配置位变为 3

3的二进制是0010,后两位是端口模式MODE,10表示2Mhz输出模式;前两位是端口配置位CNF,00,表示通用推挽输出模式

后一句是对GPIOB的ODR寄存器进行配置,把代表PB5的第5位写位高电平

再看LED0的定义,相关代码如下:

//test.c 
LED = 0;

//led.h
#define LED0 PBout(5)	// DS0

//sys.h
#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //Êä³ö 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 

//stm32f10x.h
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define PERIPH_BASE           ((uint32_t)0x40000000) 

程序里面有bitband的定义,这个名字直译就是比特段,https://wenku.baidu.com/view/16645b5702f69e3143323968011ca300a6c3f6db.html

文件夹的架构如下

  • source group文件夹:startup_stm32f10x_hd.s
  • user文件夹:test.c
  • system文件夹:delay.c, sys.c,usart.c
  • hardware文件夹:led.c
============================找指导老师布置任务吧==============================