(51单片机)独立按键控制流水灯LED流向(独立按键教程)(LED使用教程)

源代码

如上图将7个文放在Keli5 中即可,然后烧录在单片机中就行了

烧录软件用的是STC-ISP,不知道怎么安装的可以去看江科大的视频:

【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?p=2\&vd_source=ada7b122ae16cc583b4add52ad89fd5e

源代码:

++头文件要记得宏定义和重定义,避免重复调用:++

cpp 复制代码
#ifndef _Timer0_h_//名字根据文件名定义即可
#define _Timer0_h_

//声明函数......

#endif

main.c

cpp 复制代码
#include <STC89C5xRC.H>
#include <INTRINS.H>
#include "Timer0.h"
#include "Key.h"//调用头文件

unsigned char KeyNum,LEDMode;//定义全局变量KeyNum(获取按键的值),LEDMode(切换流水灯流向)
void main()
{
	P2=0xFE;//初始化灯P20=0,1111 1110(就是让01灯亮)
	Timer0_Init();//初始化定时器/计时器
	while(1)
	{
		KeyNum=Key();//获取按键值
		if(KeyNum){
			if(KeyNum==1){
				LEDMode++;//切换流水灯模式
				if(LEDMode>=2)LEDMode=0;
			}
		}
	}
}
//中断程序函数

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;//局部静态变量
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=1000){
		T0Count=0;
		if(LEDMode==0)P2=_crol_(P2,1);//左移函数,P2每秒左移动一次
		if(LEDMode==1)P2=_cror_(P2,1);//右移函数,P2每秒右移动一次
	}
}

Timer0.c

cpp 复制代码
#include <STC89C5xRC.H>

//void Timer0_Init()
//{
//	TF0=0;TR0=1;//TCON,寄存器
//	//TMOD=0x01;//0000 0001,寄存器
//	TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位不变,方便使用两个定时器
//	TMOD=TMOD&0x01;//把TMOD的最低位置1,高四位不变,方便使用两个定时器
//	TH0=64535/256;//高电位,寄存器,1毫秒
//	TL0=64535%256;//低电位,寄存器,1毫秒
//	ET0=1;EA=1;PT0=0;//打开中断开关
//	
//}
//定时器0初始化函数
void Timer0_Init()		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;//允许中断
	EA=1;//允许总中断
	PT0=0;//低优先级
}


中断程序函数
//中断函数模版
//void Timer0_Routine() interrupt 1
//{
//	static unsigned int T0Count;
//	TL0 = 0x66;		//设置定时初值
//	TH0 = 0xFC;		//设置定时初值
//	T0Count++;
//	if(T0Count>=1000){
//		T0Count=0;
//		P20=~P20;
//	}
//}

Timer0.h

cpp 复制代码
#ifndef _Timer0_h_
#define _Timer0_h_

void Timer0_Init();


#endif

Key.c

cpp 复制代码
#include <STC89C5xRC.H>
#include "Delay.h"

unsigned char Key()//获取独立按键
{
	unsigned char KeyNumber=0;
	//进行判断是否摁下按键和防抖操作
	if(P31==0){Delay(20);while(P31==0);Delay(20);KeyNumber=1;}
	if(P30==0){Delay(20);while(P30==0);Delay(20);KeyNumber=2;}
	if(P32==0){Delay(20);while(P32==0);Delay(20);KeyNumber=3;}
	if(P33==0){Delay(20);while(P33==0);Delay(20);KeyNumber=4;}
	return KeyNumber;
}

Key.h

cpp 复制代码
#ifndef _Key_h_
#define _Key_h_

unsigned char Key();

#endif

Delay.c

cpp 复制代码
//Delay.c

#include <STC89C5xRC.H>
#include <INTRINS.H>

//延时函数
void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms){
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

Delay.h

cpp 复制代码
//Delay.h

#ifndef __Delay_H__
#define __Delay_H__

//延时函数头文件
void Delay(unsigned int xms);
#endif

代码解析与教程:

main.c
  • 注释解释很清楚,重点来讲解一下中断函数中的左移右移函数
    他们哥俩是依赖头文件**<INTRINS.H>的库函数** :

    会用即可,这是char类型的,里面也有其他类型的,参数一是要移动的数,参数二是移动的位数。
    例如:0000 0001使用左移函数_crol_左移一位就是0000 0010,其他同理,因此,加上中断函数,灯就会每秒移动一次
Dealy模块
  • 包含源代码与头文件,不需要知道怎么实现的会用即可,后续使用,直接将头文件和源代码拿过来用即可;


xms是定义的毫秒,1000毫秒就是1秒;模版生成的是1毫秒的,因此xms等于1000

Timer0模块
  • 包含源代码与头文件,需要知道怎么实现,会用
  • 51单片机的定时器和计数器十分重要,要理解怎么用,要知道原理是什么,要结合原理图来分析怎么做,先看代码
cpp 复制代码
#include <STC89C5xRC.H>

//void Timer0_Init()
//{
//	TF0=0;TR0=1;//TCON,寄存器
//	//TMOD=0x01;//0000 0001,寄存器
//	TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位不变,方便使用两个定时器
//	TMOD=TMOD&0x01;//把TMOD的最低位置1,高四位不变,方便使用两个定时器
//	TH0=64535/256;//高电位,寄存器,1毫秒
//	TL0=64535%256;//低电位,寄存器,1毫秒
//	ET0=1;EA=1;PT0=0;//打开中断开关
//	
//}
//定时器0初始化函数
void Timer0_Init()		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;//允许中断
	EA=1;//允许总中断
	PT0=0;//低优先级
}


中断程序函数
//中断函数模版
//void Timer0_Routine() interrupt 1
//{
//	static unsigned int T0Count;
//	TL0 = 0x66;		//设置定时初值
//	TH0 = 0xFC;		//设置定时初值
//	T0Count++;
//	if(T0Count>=1000){
//		T0Count=0;
//		//下面是代码区
//	}
//}
  • 最上面注释掉的代码是要求理解的;中间的代码是STC-ISP软件生成的;最下面的代码是中断函数模版,拿到main.c中可直接使用,但是也要了解原理:

大家可以这个博客深度理解定时器计数器和中断,这个是教程博客:(51单片机)计时器时钟(C语言代码编撰)(定时器/中断器、计数器教程)(51单片机重点)-CSDN博客

Key模块
  • 包含源代码与头文件,不需要知道怎么实现的会用即可,后续使用,直接将头文件和源代码拿过来用即可;

    序号1是按键的防抖操作,不需要理解,有按键的地方直接用即可
    序号2是独立按键控制变量。
    KeyNumber就是返回值,按键K1就返回1,其他同理

独立按键教程、LED教程

由于单片机系列版本不一样,单片机核心控制可能会有不同,例如:有些单片机的LED的L1是P21,有些就是P2_1,需要看单片机核心,或者头文件:

++可以看到我的STC89C52RC是P21;++

独立按键
  • 先看原理图:


    可以看到控制K1的是P31,同理K2是P30,按键都是高电位 ,因此只要将P31设置成0,就是按键通电,相当于激活

LED教程
  • 先看原理图:

    LED是高电位,设定为0就是通电

  • P2就是16进制的LED灯总控制,如:0xFF=1111 1111,就是全关,例如代码中的:
    P2=0xFE,就是1111 1110,就是L1亮,左移一位就是1111 1101,就是L2亮,其他同理,配合中断函数 ,就可以每秒移动一次

效果视频:

(51单片机)按键控制流水灯移位

注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!

相关推荐
白狐_7986 分钟前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25828 分钟前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
qq_448011161 小时前
C语言中的动态内存分配
c语言·开发语言·php
船厂电气自动化ai大模型2 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
动词ing2 小时前
【学习笔记】C语言(数组指针与指针数组+字符数组+函数+参数传递+字符串作为形参+递归函数+指针函数+回调函数+结构体嵌套+内存动态分配函数)
c语言·笔记·学习
旖旎夜光2 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
汉字萌萌哒2 小时前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter2 小时前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具
周洲08303 小时前
STM32 GPIO 外部中断深度解析:边沿触发 / 电平触发、NVIC 优先级配置、中断嵌套实战
stm32·单片机·嵌入式硬件
汉字萌萌哒3 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++