02:(寄存器开发)流水灯/按键控制LED

news/2024/10/4 19:04:15 标签: 嵌入式硬件, 单片机, stm32, c语言

寄存器开发

  • 1、LED流水灯
  • 2、按键控制LED

1、LED流水灯

通过第一章的学习,我们已然知晓了LED的点亮和熄灭的方式,下面学习流水灯的制作流程。
流水灯呈现的样子:就是第一个LED灯点亮,延迟一段时间,第一个LED灯熄灭+第二个LED灯点亮,延迟一段时间,第二个LED灯熄灭+第三个LED灯点亮…依次循环下去。其中延迟一段时间就是让单片机不做任何与LED灯有关的事情,这里使用延迟函数来实现。

在工程目录里面新建Driver文件夹用来保存配置片上外设的代码文件,如下图所示:
在这里插入图片描述
LED连接的实物图如下图所示:
在这里插入图片描述

①LED.c文件的代码如下:

#include "stm32f10x.h"                  
#include "LED.h"

/*
 * @Function:PA0~PA7引脚选择性的初始化
 * @para:对应的GPIOA的引脚PA_0~PA_7
 */
void LED_Init(uint32_t PA_x)
{
	/* 1. 打开GPIOA的时钟 */
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	
	/* 2. 将PA0~PA7配置为通用输出开漏模式  */
	if(PA_x != PA_ALL)
	{
		GPIOA->CRL |= PA_x; 
		GPIOA->CRL &= ~(PA_x << 2);
	}else{
		GPIOA->CRL |= PA_ALL;
		GPIOA->CRL &= PA_ALL;
	}
	
}

/*
 * @Function:输出1点亮LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_ON(uint16_t LEDx)
{
	GPIOA->ODR |= LEDx;
}


/*
 * @Function:熄灭LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_OFF(uint16_t LEDx)
{
	GPIOA->ODR &= ~LEDx;
}


/*
 * @Function:翻转LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_Turn(uint16_t LEDx)
{
	/* 如果是关闭那么就打开,如果是打开那么就关闭 */
	if((GPIOA->ODR & LEDx) == 0)//关闭
	{
		LED_ON(LEDx);
	}else{
		LED_OFF(LEDx);
	}
}

②LED.h文件的代码如下:

#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"                  

#define PA_0  0x00000003 //GPIO_CRH_MODE0
#define PA_1  0x00000030 //GPIO_CRH_MODE1
#define PA_2  0x00000300 //GPIO_CRH_MODE2
#define PA_3  0x00003000 //GPIO_CRH_MODE3
#define PA_4  0x00030000 //GPIO_CRH_MODE4
#define PA_5  0x00300000 //GPIO_CRH_MODE5
#define PA_6  0x03000000 //GPIO_CRH_MODE6
#define PA_7  0x30000000 //GPIO_CRH_MODE7
#define PA_ALL  0x33333333 //GPIO_CRH_MODE

#define LED0 GPIO_ODR_ODR0
#define LED1 GPIO_ODR_ODR1
#define LED2 GPIO_ODR_ODR2
#define LED3 GPIO_ODR_ODR3
#define LED4 GPIO_ODR_ODR4
#define LED5 GPIO_ODR_ODR5
#define LED6 GPIO_ODR_ODR6
#define LED7 GPIO_ODR_ODR7

void LED_Init(uint32_t PA_x);
void LED_ON(uint16_t LEDx);
void LED_OFF(uint16_t LEDx);
void LED_Turn(uint16_t LEDx);

#endif

③主函数文件的代码如下:

#include "stm32f10x.h"                
#include "Delay.h"
#include "LED.h"

#define timer 500

/*
	LED流水灯,LED灯的负极连接着GND,正极连接着单片机的引脚(PA0~PA4)
	一共5个LED灯,引脚输出1点亮,输出0熄灭
*/
int main(void)
{
	LED_Init(PA_ALL);//将所有的引脚都配置为通用输出推挽模式
	
	while(1)
	{
		LED_ON(LED0);//点亮LED0
        Delay_ms(timer);
        LED_OFF(LED0);//熄灭LED0
    
        LED_ON(LED1);//点亮LED1
        Delay_ms(timer);
        LED_OFF(LED1);//熄灭LED1
        
        LED_ON(LED2);//点亮LED2
        Delay_ms(timer);
        LED_OFF(LED2);//熄灭LED2
        
        LED_ON(LED3);//点亮LED3
        Delay_ms(timer);
        LED_OFF(LED3);//熄灭LED3
        
        LED_ON(LED4);//点亮LED4
        Delay_ms(timer);
        LED_OFF(LED4);//熄灭LED4
	}
}

代码优化如下:

#include "stm32f10x.h"                
#include "Delay.h"
#include "LED.h"

#define timer 500
/*
	LED流水灯,LED灯的负极连接着GND,正极连接着单片机的引脚(PA0~PA4)
	一共5个LED灯,引脚输出1点亮,输出0熄灭
*/
int main(void)
{
	LED_Init(PA_ALL);//将所有的引脚都配置为通用输出推挽模式
	
	while(1)
	{
        for(uint8_t i = 0; i<5 ;i++)
        {
            LED_ON(LED0 << i);
            Delay_ms(timer);
            LED_OFF(LED0 << i);
        }   
	}
}

代码优化2:制作来回流水灯

#include "stm32f10x.h"                
#include "Delay.h"
#include "LED.h"

#define timer 500
/*
	LED流水灯,LED灯的负极连接着GND,正极连接着单片机的引脚(PA0~PA4)
	一共5个LED灯,引脚输出1点亮,输出0熄灭
*/
int main(void)
{
	LED_Init(PA_ALL);//将所有的引脚都配置为通用输出推挽模式
	
	while(1)
	{
		/*
  	 		 代码改进:来回流水灯
		*/ 
           
        for(uint8_t i = 0; i<4 ;i++)
        {
            LED_ON(LED1 << i);
            Delay_ms(timer);
            LED_OFF(LED1 << i);
        }
        for(uint8_t i = 0; i<4 ;i++)
        {
            LED_ON(LED3 >> i);
            Delay_ms(timer);
            LED_OFF(LED3 >> i);
        }   
	}
}

演示效果如下:

VID_20241004_105203

2、按键控制LED

使用按键控制则需要按键检测,检测引脚的输入输入电平,所以需要用到端口输入寄存器GPIO_IDR,如下图所示:
在这里插入图片描述
所以被检测的引脚要配置为输入模式。
在这里插入图片描述

实物连接如下图所示:

在这里插入图片描述

在这里插入图片描述
①Key.c文件的代码如下:

#include "stm32f10x.h"                  
#include "Delay.h"

/*
 * @Function:按键引脚(GPIOB0)的初始化
 */
void Key_Init(void)
{
    //1、开始GPIOB的时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    
    //2、配置引脚GPIOB0的输入模式:上拉输入,MODE0 = 00,CNF0 = 10,ODR0 = 1。
    GPIOB->CRL &= ~GPIO_CRL_MODE0;
    GPIOB->CRL &= ~GPIO_CRL_CNF0_0;
    GPIOB->CRL |= GPIO_CRL_CNF0_1;
    GPIOB->ODR |= GPIO_ODR_ODR0;//表示上拉模式
}

/*
 * @Function:按键按下并返回一个值
 */
uint8_t Key_Num(void)
{
    uint8_t Number = 0;

    //引脚配置为上拉输入,则默认输入为高电平,按键按下由高电平变为低电平
    if((GPIOB->IDR & GPIO_IDR_IDR0)!= 0)//代表按键没有按下
    {
        Delay_ms(5);//软件消抖
        if((GPIOB->IDR & GPIO_IDR_IDR0)== 0)//代表按键按下
        {
            Number = 1;
        }
    }
    return Number;
}

②LED.c文件代码如下:

#include "stm32f10x.h"                  
#include "LED.h"

/*
 * @Function:PA0~PA7引脚选择性的初始化
 * @para:对应的GPIOA的引脚PA_0~PA_7
 */
void LED_Init(uint32_t PA_x)
{
	/* 1. 打开GPIOA的时钟 */
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	
	/* 2. 将PA0~PA7配置为通用输出开漏模式  */
	if(PA_x != PA_ALL)
	{
		GPIOA->CRL |= PA_x; 
		GPIOA->CRL &= ~(PA_x << 2);
	}else{
		GPIOA->CRL |= PA_ALL;
		GPIOA->CRL &= PA_ALL;
	}
	
}

/*
 * @Function:输出1点亮LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_ON(uint16_t LEDx)
{
	GPIOA->ODR |= LEDx;
}


/*
 * @Function:熄灭LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_OFF(uint16_t LEDx)
{
	GPIOA->ODR &= ~LEDx;
}


/*
 * @Function:翻转LED灯
 * @para:对应的GPIOA的引脚输出值LED0~LED7
 */
void LED_Turn(uint16_t LEDx)
{
	/* 如果是关闭那么就打开,如果是打开那么就关闭 */
	if((GPIOA->ODR & LEDx) == 0)//关闭
	{
		LED_ON(LEDx);
	}else{
		LED_OFF(LEDx);
	}
}

③主函数文件的代码如下:

#include "stm32f10x.h"                
#include "Delay.h"
#include "LED.h"
#include "Key.h"

/*
	按键控制LED
*/
int main(void)
{
	LED_Init(PA_0);     //将GPIOA0引脚都配置为通用输出推挽模式
	Key_Init();         //初始化GPIOB0
    
    LED_OFF(LED0);      //关闭LED0
    
	while(1)
	{
        if(Key_Num() == 1)//代表按键按下
        {
            LED_Turn(LED0);//LED灯翻转
        }   
	}
}

演示效果如下:


http://www.niftyadmin.cn/n/5690263.html

相关文章

Study-Oracle-10-ORALCE19C-RAC集群维护

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。 一、RAC的逻辑架构与进程 1、RAC 与单实例进程的对比 2、RAC相关进程功能 3、在主机查看RAC进程 其他的不列举了 4、RAC集群启停命令 检查集群状态 ORACLE 19C …

项目-坦克大战笔记-墙体销毁以及人机销毁

在子弹撞到墙或者人机身上时会将碰撞到的墙体或者人机销毁 我们需要做到几点 检测子弹碰撞到的墙体或者人机将物体获取到 每帧遍历墙体列表与人机列表&#xff0c;检测被碰撞的墙&#xff0c;创建一个方法返回值为对应类型将被碰撞的物体返回出来 public static gudin wallp…

Go基础学习11-测试工具gomock和monkey的使用

文章目录 基础回顾MockMock是什么安装gomockMock使用1. 创建user.go源文件2. 使用mockgen生成对应的Mock文件3. 使用mockgen命令生成后在对应包mock下可以查看生成的mock文件4. 编写测试代码5. 运行代码并查看输出 GomonkeyGomonkey优势安装使用对函数进行monkey对结构体中方法…

Pikachu-Sql Inject-搜索型注入

MySQL的搜索语句&#xff1a; select * from table where column like %text%&#xff1b; 如&#xff1a;使用引号闭合左边的引号&#xff0c; or 11 把所有数据查询出来&#xff1b; # 注释掉后面的 引号等&#xff1b; test or 11# 查询出结果&#xff1a; 注入的核心点…

【CKA】十二、持久化存储卷PersistentVolume

12、持久化存储卷PersistentVolume 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 按题目要求检查各个参数&#xff0c;我就是第一次没看清楚&#xff0c;把ReadWriteOnce写成ReadWriteMany了&#xff0c;幸亏做完检查了一遍 这个参数可有可无&#xff0c;加上也不影响 …

小红书制作视频如何去原视频音乐,视频如何去原声保留背景音乐?

在视频编辑、音乐制作或个人娱乐中&#xff0c;有时我们希望去掉视频中的原声&#xff08;如对话、解说等&#xff09;&#xff0c;仅保留背景音乐。这种处理能让观众更加聚焦于视频的氛围或节奏&#xff0c;同时也为创作者提供了更多创意空间。选择恰当的背景音乐&#xff0c;…

自学网络安全(黑客技术)90天学习计划

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”…

电脑出现msvcp140.dll丢失的解决方法,总结6种解决方法

在计算机使用过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中最常见的就是“msvcp140.dll丢失”的错误。这个错误提示通常出现在运行某个程序时&#xff0c;它意味着计算机无法找到所需的msvcp140.dll文件。那么&#xff0c;msvcp140.dll丢失是怎么回事呢&#…