STM32学习笔记1:点亮第一盏LED灯

本文不特殊说明都以stc32F103C8为例,软件平台为KEIL5V5.15 
首先这次我们用寄存器直接点亮LED灯 
LED电路图如下图:
STM32学习笔记1:点亮第一盏LED灯 
可以看出如果需要点亮一盏LED灯只需要IO口输出高电平即可,本次以GPIOB为例子。


点亮LED灯


控制IO输出高电平通常需要三步: 
1.开启时钟:因为STM32为了节约消耗,故上电时候外设时钟默认不开启。故我们需要开始GPIO的时钟。 
2.设置GPIO输出模式:stm32F103提供了4种输出模式和3种输出速度: 
- 通用输出推挽 
- 通用输出开漏 
- 复用输出推挽:串口输出 
- 复用输出开漏:IIC


推挽输出电路如下图:
STM32学习笔记1:点亮第一盏LED灯 
两个三极管都是半个周期导通,轮流导通。从而减低了功耗,提高了每个管的承受能力。又由于不论走哪一路,管子导通电阻都很小,使RC常数很小,转变速度很快。因此,推拉式输出级既提高电路的负载能力,又提高开关速度。所以推挽输出可以输出高低电平,但输出幅度取决于输入,不可控。


开漏输出电路如下图: 
STM32学习笔记1:点亮第一盏LED灯 
从图中可以看出,当没有上拉电平和上拉电阻,当IN输出低电平时候,OUT输出低电平,当IN输出高电平时,OUT处于开漏状态,电平状态未知,当加上拉电阻时候,则上拉电平跟上拉电阻有关。 
开漏输出相当于三极管集电极,故它只能输出低电平,需要接上拉电阻才能得到高电平。开漏是用来连接不同电平的器件。很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平。比如加上上拉电阻就可以提供TTL/CMOS电平输出等。(上拉电阻的阻值决定了逻辑电平转换的沿的速度 。阻值越大,速度越低功耗越小,所以负载电阻的选择要兼顾功耗和速度。) 
而且可以将多个开漏输出的管脚,连接到一条线上。通过一只上拉电阻,在不增加任何器件的情况下,形成“与逻辑”关系。这也是I2C,SMBus等总线判断总线占用状态的原理。
3.输出高电平


寄存器设置

1.设置时钟寄存器 
首先GPIO是挂载在APB2总线上的,APB2时钟使能寄存器为RCC_APB2ENR,如下图 
STM32学习笔记1:点亮第一盏LED灯 
故只需开启GPIOB的时钟,即将RCC_APB2ENR第3位置1


2.设置IO口输出状态 
有关寄存器为GPIOB_CRL和GPIOB_CRH,如下图:
STM32学习笔记1:点亮第一盏LED灯 
可以看出只需要设置MODEx[1:0]即可,我们可将他置01,设置成中速即可,则默认为推挽输出


3.设置IO口输出电平 
IO电平有3个寄存器有关,分别是GPIOB_ODR,GOIOB_BSRR,和GPIOB_BRR;其中GOIOB_BSRR为置位/复位寄存器,GPIOB_BRR为复位寄存器,这两个寄存器都是间接控制GPIOB_ODR即端口数据输出寄存器,故为了初学方便,我们直接控制GPIOB_ODR寄存器。寄存器相关内容如下:
STM32学习笔记1:点亮第一盏LED灯 
因为寄存器可以写和读,故可以直接置1即可。


注意事项: 
1.需要提前设定相关总线和寄存器地址,如下表: 
STM32学习笔记1:点亮第一盏LED灯 
2.初学者为了简单,通常都操作GPIOx_ODR寄存器,但实际上我还是推荐使用GPIOx_BSRR寄存器,因为BSRR只有写操作,和ODR要经历读——写操作,时间显然慢很多,而且使用BSRR不会被中断打断。


以下附代码(灯接GPIOB_8~15)
  1. /*定义相关寄存器地址*/
  2. #define GPIOB_ODR            *(unsigned int *)(0x40010C00+0x0c)
  3. #define GPIOB_CRH            *(unsigned int *)(0x40010C00+0x04)
  4. #define RCC_APB2ENR          *(unsigned int *)(0x40021000+0x18)
  5. /*延时函数*/
  6. void delay(){
  7.     unsigned long n = 30000,j;
  8.     while(n--){
  9.         j = 12;
  10.         while(j--);
  11.     }
  12. }
  13. int main(){
  14.     unsigned char i;

  15.     /*开启时钟*/
  16.     RCC_APB2ENR |= 1<<3;

  17.     /*配置PB8到PB15推挽输出,中速模式*/
  18.     GPIOB_CRH |= 0x33333333;        

  19.     while(1){
  20.         /*闪烁两次*/
  21.         GPIOB_ODR |= 0XFF00;
  22.         delay();
  23.         GPIOB_ODR &= ~0XFF00;
  24.         delay();

  25.         GPIOB_ODR |= 0XFF00;
  26.         delay();
  27.         GPIOB_ODR &= ~0XFF00;
  28.         delay();
  29.         GPIOB_ODR = 0x0100;
  30.         /*流水灯*/
  31.         for(i = 0;i<7;i++){
  32.             GPIOB_ODR<<=1; 
  33.             delay();
  34.         }
  35.         for(i = 0;i<7;i++){
  36.             GPIOB_ODR>>=1; 
  37.             delay();
  38.         }

  39.     }

  40. }
复制代码