STM32实现LED流水灯闪烁

        本文通过对STM32最小系统核心板及其寄存器进行了简要描述,并利用GPIO口推挽输出进行了LED流水灯闪烁的实验。

一、STM32最小系统核心板(STM32F103C8T6)

        简介:STM32最小系统核心板(STM32F103C8T6)由单片机芯片、供电电路、时钟电路、复位电路、程序下载电路、启动配置电路组成。 ​
        其引脚原理图如下所示。

        其电路原理图如下所示。

二、GPIO端口

1.概述

        GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。 ​
        每个 GPIO 端口有两个 32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个 32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个 32 位置位/复位寄存器(GPIOx_BSRR),一个 16 位复位寄存器(GPIOx_BRR)和一个 32 位锁定寄存器(GPIOx_LCKR)。

2.GPIO寄存器

2.1-低寄存器(0-7引脚)

1.CNF:configure。配置对应端口的输入输出模式。
2.MODE:配置对应端口的输出速度。

2.2-高寄存器(8-15引脚)

2.3-APB2 外设时钟使能寄存器(RCC_APB2ENR)

三、LED流水灯闪烁

        要求:以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只_(或更多)红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。

        点亮LED灯,实现流水灯效果需要用到GPIO端口。为了点亮LED灯,进行以下三个步骤:

1.打开GPIO口时钟

        GPIO地址:

        时钟地址:

        时钟设置:通过查询STM32参考手册,可以找到APB2的外设时钟使能寄存器进行设置。RCC时钟控制的起始地址为0x4002 1000,APB2外设时钟使能寄存器(RCC_APB2ENR)的偏移地址为0x18,所以打开三个IO口的时钟需要将三个位都需要置1。

 #define RCC_APB2ENR (*(unsigned int *)0x40021018)
  
 // 打开时钟
 RCC_APB2ENR |= (1<<3);  // 打开 GPIOB 时钟
 RCC_APB2ENR |= (1<<4);  // 打开 GPIOC 时钟
 RCC_APB2ENR |= (1<<2);  // 打开 GPIOA 时钟

2.初始化GPIO口(选择推挽输出)

        本次实验通过推挽输出通过先前对GPIO寄存器的描述,选择相对应的编码,以实现推挽输出。

 #define GPIOA_CRL (*(unsigned int *)0x40010800)

 // 最后四位变为0001
 GPIOA_CRL |= (1<<0);  // 最后一位变1
 GPIOA_CRL &= ~(0xE<<0);  // 倒数2、3、4位变0

        对于GPIOB的B9、GPIOC的C15、GPIOA的A4,设置如下:

 #define GPIOB_CRH (*(unsigned int *)0x40010C04)
 #define GPIOC_CRH (*(unsigned int *)0x40011004)
 #define GPIOA_CRL (*(unsigned int *)0x40010800)
  
 GPIOB_CRH&= 0xffffff0f;     
     GPIOB_CRH|=0x00000020;
  
     GPIOC_CRH &= 0x0fffffff; 
     GPIOC_CRH|=0x30000000;
  
     GPIOA_CRL &= 0xfff0ffff; 
     GPIOA_CRL|=0x00010000;

3.设置高电平

        输出高电平则为1,低电平则为0。 ​ 对于GPIOB的B9、GPIOC的C15、GPIOA的A4,设置如下:

 #define GPIOB_ODR (*(unsigned int *)0x40010C0C)
 #define GPIOC_ODR (*(unsigned int *)0x4001100C)
 #define GPIOA_ODR (*(unsigned int *)0x4001080C)
  
 GPIOB_ODR &= ~(1<<9);  
 GPIOC_ODR &= ~(1<<15); 
 GPIOA_ODR &= ~(1<<4);  

4.代码实现

        在Keil中新建一个工程,选择STM32F103C8,以便完成STM32的操作。

代码如下。

 #define GPIOB_BASE 0x40010C00
 #define GPIOC_BASE 0x40011000
 #define GPIOA_BASE 0x40010800
  
 #define RCC_APB2ENR (*(unsigned int *)0x40021018)
  
 #define GPIOB_CRH (*(unsigned int *)0x40010C04)
 #define GPIOC_CRH (*(unsigned int *)0x40011004)
 #define GPIOA_CRL (*(unsigned int *)0x40010800)
  
 #define GPIOB_ODR (*(unsigned int *)0x40010C0C)
 #define GPIOC_ODR (*(unsigned int *)0x4001100C)
 #define GPIOA_ODR (*(unsigned int *)0x4001080C)
     
 void SystemInit(void);
 void Delay_ms(volatile  unsigned  int);
 void A_LED_LIGHT(void);
 void B_LED_LIGHT(void);
 void C_LED_LIGHT(void);
 void Delay_ms( volatile  unsigned  int  t)
 {
      unsigned  int  i;
      while(t--)
          for (i=0;i<800;i++);
 }
  
 void A_LED_LIGHT(){
     GPIOA_ODR=0x0<<4;       //PA4低电平
     GPIOB_ODR=0x1<<9;       //PB9高电平
     GPIOC_ODR=0x1<<15;      //PC15高电平
 }
 void B_LED_LIGHT(){
     GPIOA_ODR=0x1<<4;       //PA4高电平
     GPIOB_ODR=0x0<<9;       //PB9低电平
     GPIOC_ODR=0x1<<15;      //PC15高电平
 }
 void C_LED_LIGHT(){
     GPIOA_ODR=0x1<<4;       //PA4高电平
     GPIOB_ODR=0x1<<9;       //PB9高电平
     GPIOC_ODR=0x0<<15;      //PC15低电平   
 }
  
 int main(){
     int j=100;
     // 开启时钟
     RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
     RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
     RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
     
     // 设置 GPIO 为推挽输出
     GPIOB_CRH&= 0xffffff0f; //设置位 清零        
     GPIOB_CRH|=0x00000020;  //PB9推挽输出
  
     GPIOC_CRH &= 0x0fffffff; //设置位 清零       
     GPIOC_CRH|=0x30000000;  //PC15推挽输出
  
     GPIOA_CRL &= 0xfff0ffff; //设置位 清零       
     GPIOA_CRL|=0x00010000; //PA4推挽输出
  
     // 3个LED初始化为不亮(即高点位)
     GPIOB_ODR |= (1<<9); 
     GPIOC_ODR |= (1<<15); 
     GPIOA_ODR |= (1<<4);  
     
     while(j){
         
         B_LED_LIGHT();
         Delay_ms(1000000);
  
         C_LED_LIGHT();
         Delay_ms(1000000);
  
         A_LED_LIGHT();
         Delay_ms(1000000);
     }
     
 }
  
  
 void SystemInit(){
     
 }

5.Proteus仿真

        在Proteus中绘制如下图所示电路图,并将上述代码生成hex文件,录入Proteus中,便能看到LED灯流水灯闪烁。

6.开发板展示

        首先在开发板上进行电路连接,ST-LINK与开发板的连接如下所示。

        再将三个灯分别连接在对应位置,本例中将蓝灯连在B9端口,黄灯连在C15端口,红灯连在A4端口

        通过ST-LINK将开发板与电脑连接,并在Debug中做如下设置,以便进行连接。

        运行后便可以在开发板上看到LED灯流水灯闪烁。

7.附加

        STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),一般可通过此灯的点亮让编程者验证自己烧录的代码是否正常运行了。现需将这个灯也用在流水灯中。 ​ 代码如下所示。

 #include "stm32f10x.h"                  // Device header
 #include "Delay.h"
 ​
 int main()
 {
     //配置三个口的时钟
     RCC->APB2ENR=0x0000001C;                //给GPOIA、B、C口配置时钟
     
     //配置GPIOA2口的输出模式及输出电平
     GPIOA->CRL=0x00000300;                  //使用GPIOA2引脚
     //GPIOA->ODR=0x00000000;                //GPIOA2引脚低电平点亮
     GPIOA->ODR=0x00000004;              //GPIOA2引脚高电平熄灭
     
     //配置GPIOB12口的输出模式及输出电平
     GPIOB->CRH=0x00030000;                  //使用GPIOB12引脚
     //GPIOB->ODR=0x00000000;                //GPIOB12引脚低电平点亮
     GPIOB->ODR=0x00001000;              //GPIOB12引脚高电平熄灭
     
     //配置GPIOC13口和GPIOC15口的输出模式及输出电平
     GPIOC->CRH=0x30300000;                  //使用GPIOC13和15引脚
     //GPIOC->ODR=0x00000000;                //GPIOC13和15引脚低电平点亮
     GPIOC->ODR=0x0000A000;                  //GPIOC13和15仍然保持高电平
     
     while(1)
     {
         GPIOA->ODR=0x00000000;              //GPIOA2引脚低电平点亮
         Delay_s(1);
         GPIOA->ODR=0x00000004;              //GPIOA2引脚高电平熄灭
         
         GPIOB->ODR=0x00000000;              //GPIOB12引脚低电平点亮
         Delay_s(1);
         GPIOB->ODR=0x00001000;              //GPIOB12引脚高电平熄灭
                 
         GPIOC->ODR=0x00008000;              //GPIOC13引脚低电平点亮,GPIOC15仍然保持高电平
         Delay_s(1);
         GPIOC->ODR=0x0000A000;              //GPIOC13和GPIOC15引脚高电平熄灭
         
         GPIOC->ODR=0x00002000;              //GPIOC15引脚低电平点亮,GPIOC13仍然保持高电平
         Delay_s(1);
         GPIOC->ODR=0x0000A000;              //GPIOC13和GPIOC15引脚高电平熄灭
         
     }
 }

        开发板展示如下所示。

四、总结

        本文通过使用寄存器进行单片机编程,需要依靠STM32F103参考手册去查找地址,编程方式比较原始,但是能让我们懂得一些底层原理,帮助我们更好地理解和学习STM32。

五、参考资料

STM32F103的流水灯点亮版本1(寄存器地址操作)

  • 29
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F4系列微控制器是基于ARM Cortex-M4内核的高性能嵌入式处理器,常用于各种工业控制和物联网应用中。要实现流水灯效果,你需要使用STM32F4的GPIO(General Purpose Input/Output)功能来控制LED,并利用定时器或中断系统来控制闪烁。 以下是实现基本流水灯的步骤: 1. **硬件连接**: - 将LED串联起来接到STM32的GPIO口,通常使用P0、P1、P2等GPIO作为输出。 - 为了方便控制,可以将LED分组,比如每8个LED为一组,每个组独立控制。 2. **初始化GPIO**: - 设置GPIO口为推挽输出模式,确保能直接驱动LED。 - 分配定时器或DMA资源,用于周期性的改变LED状态。 3. **定时器设置**: - 使用TIMx(如TIM2)配置定时器,设置周期(例如1秒)。 - 定义计数器,当计数达到某个值时,触发LED状态切换。 4. **状态切换**: - 利用定时器中断或DMA完成LED状态的切换。在中断服务函数中,改变当前LED组的输出状态(亮或灭),并使下一个LED组进入点亮状态。 5. **循环更新**: - 主程序进入无限循环,等待定时器中断,处理中断后继续执行下一次定时器周期。 6. **可选:流水灯动画**: - 如果需要流水灯效果,可以通过改变点亮LED的速度或顺序,模拟流动的效果。 **相关问题--:** 1. STM32F4的哪些GPIO口适合连接LED? 2. 如何配置STM32的定时器来实现LED的延时操作? 3. 使用中断服务函数还是DMA来实现LED状态的切换更高效?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值