0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32时钟与GPIO分析 基于STM32的LED灯开发

CHANBAEK 来源:Qt历险记 作者:诺苏编程 2023-08-22 15:57 次阅读

一、 STM32时钟分析

寄存器 :寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成

在计算机领域,寄存器是CPU内部的元件,包括通用寄存器、专用寄存器和 控制寄存器 。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。

控制寄存器 :相当一排可通过0/1进行设置外设功能的开关,程序中通过地址查找到对应的寄存器,所以说控制寄存器的地址是唯一。

芯片时钟:芯片工作时,是需要脉冲,脉冲相当于给芯片起振,可保证芯片的正常工作,类似于人,心脏正常跳动,人体生命特征才能正常。

1HZ:一秒产生1个脉冲

频率换算单位:

1GHZ = 1000MHZ = 1000 000KHZ = 1000 000 000HZ

STM32时钟源

时钟源是可以产生器件。

LSIRC 32KHZ32 kHz低速内部RC (LSI RC)
LSEOSC 32.168KHZ32.768 kHz低速外部晶振(LSE晶振)
16MHZ HSI RC16MHZ高速内部RC (LSI RC)
4-26MHZ HSE OSC4-26MHZ高速外部晶振(HSE 晶振)粤嵌开发板外部晶振为8MHZ

注意:外部晶振产生的脉冲是精准, RC振荡时钟产生的脉冲是不精准

STM32主要总线时钟频率

SYSCLK168MHZ
HCLK168MHZ
AHB1/AHB2168MHZ
APB142MHZ
APB284MHZ

Al解释:

在STM32微控制器中,有一些关键的概念需要了解:

  1. SYSCLK(System Clock):是微控制器系统中的主时钟源,它驱动着整个系统,包括CPU、外设等。SYSCLK的频率决定了整个系统的工作速度。
  2. HCLK(AHB Bus Clock):是系统的主总线时钟,它连接了CPU、内存、外设等,用于数据传输和控制信号
  3. AHB1/AHB2(Advanced High-performance Bus):是高性能总线,用于连接内存和一些高性能外设,如DMA控制器、GPIO控制器等。AHB1和AHB2是两个不同的总线,它们可以拥有不同的配置和频率。
  4. APB1(Advanced Peripheral Bus 1):是高级外设总线,用于连接一些低速外设,如定时器、串口通信等。APB1总线上的外设可以以较低的频率工作。
  5. APB2(Advanced Peripheral Bus 2):是高级外设总线,用于连接一些高速外设,如GPIO、SPI、I2C等。APB2总线上的外设可以以较高的频率工作。

二、 GPIO分析

1、GPIO

GPIO: GPIO(英语:General-purpose input/output),通用型之输入输出的简称。

GPIO分组

STM32F407ZET6(芯片型号)

-  一共有7组IO口(PA  PB  PC  PD  PE  PF  PG)

-  每组IO口有16个IO引脚

-  一共16X7=112个IO引脚

外加2个PH0和PH1

一共114个IO口引脚(I:input O:output)

原理图上GPIO连接与功能说明

图片

每组(PA PB PC PD PE PF PG)通用 I/O 端口包括:

•4 个 32 位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR 和 GPIOx_PUPDR)。

•2 个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR)。

•1 个 32 位置位/复位寄存器 (GPIOx_BSRR)、

•1 个 32 位锁定寄存器(GPIOx_LCKR)

•2 个 32 位复用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)。

GPIO工作方式寄存器设置GPIO工作方式

n4种输入模式

q浮空输入(没有上下拉电阻

q上拉输入(有上拉电阻)

q下拉输入(有下拉电阻)

q模拟输入

n4种输出模式

q开漏输出(带上拉或者下拉)

q开漏复用功能(带上拉或者下拉)

q推挽式输出(带上拉或者下拉)

q推挽是复用功能(带上拉或者下拉)

n4种最大输出速度

q2MHZ

q25MHZ

q50MHZ

q100MHZ

注意点:

开漏输出只能输出0(低电平),若想出输出1(高电平),需要外部接上拉电阻(类似到51单片机P0组)。

推挽式输出可输出0(低电平)或者1(高电平),这是常用模式

2、寄存器地址查找

寄存器地址 = 寄存组基地址+偏移地址

图片

图片

寄存器查看

图片

三、 LED灯开发

1、理解led灯原理图

LED0连接在PF9

PF9输出低电平(0),灯亮;PF9输出高电平(1),灯灭;

图片

2、打开GPIOF组时钟

//将第5位置1 使能GPIOF组时钟
RCC_AHB1ENR |= (0x01< < 5);

3、设置PF9灯为输出模式 输出推挽 上拉 速度(50MHZ)

4、通过GPIOF_BSRR控制LED灯亮与灭

LED举例-1

一、led.h

#ifndef __LED_H
#define __LED_H


#include "stm32f4xx.h"





#define RCC_AHB1ENR   (*((unsigned int *)(0x40023800+0x30)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值


#define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_OSPEEDR (*((unsigned int *)(0x40021400+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值










void Led_Init(void);


#endif

二、led.c

#include "led.h"




/*********************************
引脚说明:


LED0 -- PF9


**********************************/
void Led_Init(void)
{
  //将第5位置1  使能GPIOF组时钟
  RCC_AHB1ENR |= (0x01< < 5);

  //设置GPIOF9为输出模式
  GPIOF_MODER &= ~(0x01< < 19);  //19位清0
  GPIOF_MODER |= (0x01< < 18);  //18位置1


  //设置GPIOF9为输出推挽
  GPIOF_OTYPER &= ~(0x01< < 9);  //9位清0

  //设置GPIOF9为上拉
  GPIOF_PUPDR &= ~(0x01< < 19);  //19位清0
  GPIOF_PUPDR |= (0x01< < 18);  //18位置1  

  //设置GPIOF9输出速度50MHZ
  GPIOF_OSPEEDR |= (0x01< < 19);  //19位置1
  GPIOF_OSPEEDR &= ~(0x01< < 18);  //18位清0
}

三、main.c

#include "stm32f4xx.h"
#include "led.h"




// 延时函数
void delay(int n)
{
  int i,j;

  for(i=0; i< n; i++)
    for(j=0; j< 30000; j++);


}






int main(void)
{
  Led_Init();

  while(1)
  {
    //BSRR 25位置1  ODR输出0  灯亮
    GPIOF_BSRR |= (0x01< < 25);
    delay(1000);

    //BSRR 9位置1  ODR输出1  灯灭
    GPIOF_BSRR |= (0x01< < 9);
    delay(1000);

  }
  return 0;
}

四、作业拓展

上拉电阻和下拉电阻二者共同的作用是:避免电压的“悬浮”,造成电路的不稳定。

1、概念:将一个不确定的信号,通过一个电阻与电源VCC相连,固定在高电平;通过一个电阻与电源GND相连,固定在低电平

2、上拉是对器件注入电流,灌电流;下拉是对引脚进行分流,拉电流;

3、当一个接有上拉电阻的IO端口设置为输入状态时,它的常态为高电平。

图片

LED流水灯举例-2

一、led.h

#ifndef __LED_H
#define __LED_H


#include "stm32f4xx.h"





#define RCC_AHB1ENR   (*((unsigned int *)(0x40023800+0x30)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值


#define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_OSPEEDR (*((unsigned int *)(0x40021400+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值


#define GPIOE_MODER   (*((unsigned int *)(0x40021000+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOE_OTYPER  (*((unsigned int *)(0x40021000+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOE_OSPEEDR (*((unsigned int *)(0x40021000+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOE_PUPDR   (*((unsigned int *)(0x40021000+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOE_ODR     (*((unsigned int *)(0x40021000+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
#define GPIOE_BSRR    (*((unsigned int *)(0x40021000+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值






void Led_Init(void);








void Led0(void);
void Led1(void);
void Led2(void);
void Led3(void);
void Beep(void);


#endif

二、led.c

#include "led.h"






void Led_Init(void)
{
  //将第5位置1  使能GPIOF组时钟
  RCC_AHB1ENR |= (0x01< < 5);

  //将第4位置1  使能GPIOE组时钟
  RCC_AHB1ENR |= (0x01< < 4);

  Led0();
  Led1();
  Led2();
  Led3();

}
/*********************************
引脚说明:


LED0 -- PF9


**********************************/
void Led0()
{
  //设置GPIOF9为输出模式 
  GPIOF_MODER &= ~(0x01< < 19);    //19位清0
  GPIOF_MODER |= (0x01< < 18);    //18位置1


  //设置GPIOF9为输出推挽
  GPIOF_OTYPER &= ~(0x01< < 9);    //9位清0

  //设置GPIOF9为上拉
  GPIOF_PUPDR &= ~(0x01< < 19);    //19位清0
  GPIOF_PUPDR |= (0x01< < 18);    //18位置1  

  //设置GPIOF9输出速度50MHZ
  GPIOF_OSPEEDR |= (0x01< < 19);  //19位置1
  GPIOF_OSPEEDR &= ~(0x01< < 18);  //18位清0
}
/*********************************
引脚说明:


LED1 -- PF10


**********************************/
void Led1()
{
  //设置GPIOF10为输出模式
  GPIOF_MODER &= ~(0x01< < 21);    //21位清0
  GPIOF_MODER |= (0x01< < 20);    //20位置1


  //设置GPIOF9为输出推挽
  GPIOF_OTYPER &= ~(0x01< < 10);  //10位清0

  //设置GPIOF9为上拉
  GPIOF_PUPDR &= ~(0x01< < 21);    //21位清0
  GPIOF_PUPDR |= (0x01< < 20);    //20位置1  

  //设置GPIOF9输出速度50MHZ
  GPIOF_OSPEEDR |= (0x01< < 21);  //21位置1
  GPIOF_OSPEEDR &= ~(0x01< < 20);  //20位清0
}
/*********************************
引脚说明:


LED2 -- PE13


**********************************/
void Led2()
{
  //将第4位置1  使能GPIOE组时钟
  RCC_AHB1ENR |= (0x01< < 4);

  //设置GPIOF13为输出模式
  GPIOE_MODER &= ~(0x01< < 27);     //27位清0
  GPIOE_MODER |= (0x01< < 26);     //26位置1

  //设置GPIOE输出速度为50MHZ
  GPIOE_OSPEEDR |= (0x01< < 26);   //26位置1
  GPIOE_OSPEEDR &= ~(0x01< < 27);  //27为清0

  //设置GPIOE为上拉
  GPIOE_PUPDR &= ~(0x01< < 27);    //27位清0
  GPIOE_PUPDR |= (0x01< < 26);     //26位置1

  //设置GPIOE为输出推挽
  GPIOE_OTYPER &= ~(0x01< < 13);    //13位清0
}


/*********************************
引脚说明:


LED3 -- PE14


**********************************/
void Led3()
{
  //设置GPIOE14为输出模式
  GPIOE_MODER &= ~(0x01< < 29);     //29位清0
  GPIOE_MODER |= (0x01< < 28);     //28位置1

  //设置GPIOE输出速度为50MHZ
  GPIOE_OSPEEDR |= (0x01< < 28);   //28位置1
  GPIOE_OSPEEDR &= ~(0x01< < 29);  //29为清0

  //设置GPIOE为上拉
  GPIOE_PUPDR &= ~(0x01< < 29);    //29位清0
  GPIOE_PUPDR |= (0x01< < 28);     //28位置1

  //设置GPIOE为输出推挽
  GPIOE_OTYPER &= ~(0x01< < 14);   //14位清0
}

三、main.c

#include "stm32f4xx.h"
#include "led.h"




void delay(int n)
{
  int i,j;

  for(i=0; i< n; i++)
    for(j=0; j< 30000; j++);


}




int main(void)
{
  Led_Init();
  while(1)
  {
    //BSRR 25位置1  ODR输出0  Led0灯亮
    GPIOF_BSRR |= (0x01< < 25);
    delay(1000);

    //BSRR 9位置1  ODR输出1  灯灭
    GPIOF_BSRR |= (0x01< < 9);
    //delay(1000);

    //BSRR 26位置1  ODR输出0  Led1灯亮
    GPIOF_BSRR |= (0x01< < 26);
    delay(1000);

    //BSRR 10位置1  ODR输出1  灯灭
    GPIOF_BSRR |= (0x01< < 10);
    //delay(1000);

    //BSRR 29位置1  ODR输出0  Led2灯亮
    GPIOE_BSRR |= (0x01< < 29);
    delay(1000);

    //BSRR 13位置1  ODR输出1  灯灭
    GPIOE_BSRR |= (0x01< < 13);
    //delay(1000);

    //BSRR 30位置1  ODR输出0  Led3灯亮
    GPIOE_BSRR |= (0x01< < 30);
    delay(1000);

    //BSRR 14位置1  ODR输出1  灯灭
    GPIOE_BSRR |= (0x01< < 14);
    //delay(1000);

    //BSRR 24位置1  ODR输出0  蜂鸣器响
    GPIOE_BSRR |= (0x01< < 30);
    delay(1000);

    //BSRR 8位置1  ODR输出1  蜂鸣器关
    GPIOE_BSRR |= (0x01< < 14);

    //BSRR 24位置1  ODR输出0  蜂鸣器响
    GPIOF_BSRR |= (0x01< < 8);

    delay(100);

  }


  return 0;
}

LED流水灯和蜂鸣器举例-3

一、beep.h

#ifndef __BEEP_H
#define __BEEP_H


#include "stm32f4xx.h"
#include "led.h"






void Beep_Init(void);


#endif

二、beep.c

#include "beep.h"




/*********************************
引脚说明:


Beep -- PF8


**********************************/




void Beep_Init(void)
{
  //将第5位置1  使能GPIOF组时钟
  RCC_AHB1ENR |= (0x01< < 5);

  //设置GPIOF8为输出模式 
  GPIOF_MODER &= ~(0x03< < 16);    //16、17位清0
  GPIOF_MODER |= (0x01< < 16);    //16位置1


  //设置GPIOF8为输出推挽
  GPIOF_OTYPER &= ~(0x01< < 8);    //8位清0

  //设置GPIOF8为下拉
  GPIOF_PUPDR &= ~(0x03< < 16) ;

  //设置GPIOF8输出速度100MHZ
  GPIOF_OSPEEDR |= (0x01< < 17);  //17位置1
  GPIOF_OSPEEDR |= (0x01< < 16);  //16位置1
}

三、main.c

#include "stm32f4xx.h"
#include "led.h"
#include "beep.h"


void delay(int n)
{
  int i,j;

  for(i=0; i< n; i++)
    for(j=0; j< 30000; j++);


}




int main(void)
{
  Beep_Init();

  while(1)
  {
    //BSRR 24位置1  ODR输出0  蜂鸣器响
    GPIOF_BSRR |= (0x01< < 8);

    delay(100);

    //BSRR 8位置1  ODR输出1  蜂鸣器关
    GPIOF_BSRR |= (0x01< < 24);
    delay(1000);
  }


  return 0;
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5037

    浏览量

    117765
  • STM32
    +关注

    关注

    2240

    文章

    10675

    浏览量

    348866
  • 时钟
    +关注

    关注

    10

    文章

    1480

    浏览量

    130306
  • 触发器
    +关注

    关注

    14

    文章

    1685

    浏览量

    60412
  • GPIO
    +关注

    关注

    16

    文章

    1137

    浏览量

    50596
收藏 人收藏

    评论

    相关推荐

    基于STM32GPIO操作

    1.基于STM32GPIO操作理解,使用的是STM32CubeMx生成软件,目的实现2个的流水,使用的是STM32G473这个芯片。硬件
    发表于 08-16 08:24

    如何利用stm32GPIO口去点亮一个LED

    stm32GPIO口的基本结构是怎样构成的?stm32GPIO口的工作模式有哪几种呢?如何利用stm32
    发表于 12-15 07:04

    采用STM32上一个GPIO口来控制对应的一个LED的点亮和熄灭

    实验一 单个LED的闪烁1.1系统功能实现对STM32开发板上单个LED的循环点亮与熄灭,使
    发表于 12-15 06:08

    stm32控制led的过程分享

    stm32控制LEDGPIO初始化配置void GPIO_Config(void) //GPIO
    发表于 02-21 07:27

    STM32469I_EVAL-GPIO

    单片机开发STM32469I_EVAL的开发例程STM32469I_EVAL-GPIO
    发表于 06-03 15:53 9次下载

    STM32GPIO使用

    分享本文,介绍STM32GPIO使用。
    的头像 发表于 09-03 09:28 4069次阅读

    STM32单片机GPIO学习

    7组 A组 ---G 组每一组都有16个引脚 PX0-PX15对应的库文件:stm32f4xx_gpio.c思路=================1.分析硬件电路2...
    发表于 11-14 11:36 24次下载
    <b class='flag-5'>STM32</b>单片机<b class='flag-5'>GPIO</b>学习

    STM32单片机学习】第四课:GPIO控制LED(用寄存器编程)

    GPIO点亮熄灭LED13.5.5.写代码控制GPIO点亮熄灭LED23.5.6.STM32时钟设置函数移植与讲解13.5.7.
    发表于 11-14 15:36 0次下载
    【<b class='flag-5'>STM32</b>单片机学习】第四课:<b class='flag-5'>GPIO</b>控制<b class='flag-5'>LED</b>(用寄存器编程)

    STM32-GPIO

    GPIO被分成很多组,每组有16个引脚,所有的GPIO引脚都有基本的输入输出功能。最基本的输出功能是由STM32控制引脚输出高、低电平,实现开关控制,如把GPIO引脚接入
    发表于 11-22 19:51 10次下载
    <b class='flag-5'>STM32-GPIO</b>篇

    [STM32CubeMX]学习笔记1:GPIO输出LED流水灯

    [STM32CubeMX]学习笔记1:GPIO输出LED流水灯
    发表于 12-05 13:36 12次下载
    [<b class='flag-5'>STM32</b>CubeMX]学习笔记1:<b class='flag-5'>GPIO</b>输出<b class='flag-5'>LED</b>流水灯

    STM32开发板学习1 NUCLEO-L476RG:GPIO例程 点亮LED2灯

    STM32开发板学习1 NUCLEO-L476RG:GPIO例程 点亮LED2灯
    发表于 12-08 15:36 31次下载
    【<b class='flag-5'>STM32</b>】<b class='flag-5'>开发</b>板学习1 NUCLEO-L476RG:<b class='flag-5'>GPIO</b>例程 点亮<b class='flag-5'>LED</b>2灯

    STM32单片机基础03——使用GPIO点亮一个LED

    本篇文章主要介绍如何使用STM32CubeMX初始化STM32L431RCT6的GPIO,并点亮一个LED。1. 准备工作硬件准备开发板首先
    发表于 12-24 19:21 0次下载
    <b class='flag-5'>STM32</b>单片机基础03——使用<b class='flag-5'>GPIO</b>点亮一个<b class='flag-5'>LED</b>

    STM32F103LED流水灯

    中的STM32系列。所有的资料都可以在野火官网上下载野火资料下载中心二、点灯点亮LED灯,需要用到GPIO端口。为了点亮LED灯,需要三个步骤:打开
    发表于 01-12 19:57 4次下载
    <b class='flag-5'>STM32F103LED</b>流水灯

    STM32库函数开发-GPIO

    “追毛求疵” 的学习STM32,实际操作过程中知识盲区比想象中要多很多!只做了两个GPIO口项目。实战一 · I/O口1. 文件夹结构USERsystem_stm32f10x.c 系统时钟
    发表于 01-13 16:17 13次下载
    <b class='flag-5'>STM32</b>库函数<b class='flag-5'>开发</b>-<b class='flag-5'>GPIO</b>

    STM32GPIO在实际开发设计的使用配置和技巧

    一、前言 本篇开始对STM32GPIO在实际开发设计中的使用配置和技巧进行探讨,可以先去回顾下之前介绍的GPIO的相关理论基础知识包括基本结构,工作模式和寄存器原理。 了解过
    的头像 发表于 06-22 10:22 524次阅读
    <b class='flag-5'>STM32</b>的<b class='flag-5'>GPIO</b>在实际<b class='flag-5'>开发</b>设计的使用配置和技巧