Ⅰ 用汇编语言编写一个按钮控制8个流水灯的亮灭
51单片机汇编语言程序设计如下,实现通过按键控制8个流水灯的亮灭功能:
KEY被定义为P3.2端口,LED被定义为P1端口。
程序起始地址为0000H,跳转到主程序MAIN。
主程序MAIN从0030H地址开始:
清除00H单元的内容。
将0FEH的值送入累加器A。
进入循环LOOP。
检查P3.2端口的状态,如果为低电平,跳转到LOOP1。
如果P3.2端口为高电平,则执行下一条指令。
将0FFH的值送入LED端口。
跳转到LOOP2。
进入LOOP2,检查00H单元状态,如果为高电平,则跳转到LOOP2。
将0FFH的值送入P1端口。
右移累加器A的内容。
调用延时子程序DELAY。
返回到LOOP。
延时子程序DELAY从200H地址开始:
将200H送入R2。
进入循环DLY1。
将250H送入R3。
当R3不为0时,循环继续。
R2减1,直到为0,跳出循环。
返回到调用处。
这个程序通过按键P3.2控制8个流水灯P1端口的亮灭,通过右移操作实现流水效果,并通过延时子程序实现一定的视觉效果。在实际应用中,可以根据需求调整延时子程序的延时时间,以适应不同的显示效果要求。
在编写和调试此类程序时,需要注意按键的抖动问题,以及单片机的时钟频率对延时时间的影响。此外,还可以通过增加更多的逻辑判断,实现更加复杂的功能,比如增加计数器,实现流水灯的计数显示,或者加入更多的控制逻辑,实现更复杂的灯光控制效果。
通过这种编程方式,可以实现对单片机的精细控制,满足各种不同的应用需求。在实际应用中,这种编程方式还可以与外部设备或传感器结合,实现更加复杂的功能。
Ⅱ 一个按键怎么实现两个Led灯切换,就是按下第一个灯亮松手灯灭,再按一下第二个灯亮松平灯灭。单片机C
/*
按键位置:P0.1;
功能:1,当第一次按键按下,第一个灯亮,按键放开灯灭
2,当第二次按键按下,第二个灯亮,按键放开灯灭
3,重复执行前面两个步骤
灯的位置:P2口;
*/
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit BUTTON=P0^1;//按键的位置
void DELAY(uint x)
{
uchar s,j;
for(s=0;s<x;s++)
for(j=0;j<114;j++);
}
void main()
{
uint led=0;
while(1)
{
if(BUTTON==0)
{
led++;
if(led==1)//第一次按键按下
{
P2=0XFE;//1111 1110 第一个灯亮
DELAY(500);//延时
while(BUTTON!=0)//等待按键放开
{
P2=0xff;/1111 1111灯灭
DELAY(500)//延时
}
}
if(led==2)//第二次按键按下
{
led=0;//要给次数初始化
P2=0XFC;//1111 1101第二个灯亮
DELAY(500);//延时
while(BUTTON!=0)//等待按键放开
{
P2=0xff;//1111 1111第二个灯灭
DELAY(500)//延时
}
}
}
}
Ⅲ 如何用单片机一个按钮开关控制3个灯3种效果。流水。闪烁。还有一直亮。用keil编程。
下面是用C51编写的简单程序:
#include <reg51.h>
#include <intrins.h>
sbit io_Key = P1 ^ 1;
sbit led1 = P1 ^ 2;
sbit led2 = P1 ^ 3;
sbit led3 = P1 ^ 4;
unsigned char ucCount = 0;
bit flag05s = 0;
//---------------------------------
void delay125us(void) //@12.000MHz
{
unsigned char i;
i = 60;
while (--i);
}
void Timer0Init(void) //10毫秒@12MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
TR0 = 1; //开定时器0
ET0 = 1; //开定时器0中断
EA = 1; //开总中断
}
//T0中断用来计数器溢出
void zd0(void) interrupt 1
{
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
if(++ucCount >= 50)
{
ucCount = 0;
flag05s = 1; //g_flag05s = isYes定时0.52秒到,用于测量周期延时
}
}
void main(void)
{
unsigned char CountTemp = 0, ucState = 0;
Timer0Init();
while(1)
{
//-------------------------------
//简单的按键检测程序:
io_Key = 1;
_nop_();
if( io_Key == 0 )
{
CountTemp = 0;
do
{
delay125us();
if( io_Key != 0 ) break;
} while(++CountTemp > 160); // 延时20ms去抖动
if(CountTemp > 160)//如果按键时间有效,改变状态
{
switch(ucState)
{
case(0):
{
ucState = 1;
led1 = 0;
led2 = 0;
led3 = 0;
}
break;
case(1):
{
ucState = 2;
led1 = 0;
led2 = 0;
led3 = 0;
}
break;
case(2):
{
ucState = 0;
led1 = 0;
led2 = 1;
led3 = 1;
}
break;
}
while(io_Key == 0); //等待按键释放
}
}
//------------------------------
//每0.5秒改变一下LED状态
if(flag05s == 1)
{
flag05s = 0;
switch(ucState)
{
case(0):
{
led1 = !led1;
led2 = !led2;
led3 = !led3;
}
break;
case(1):
{
bit ledTemp = led1;
led1 = led2;
led2 = led3;
led3 = ledTemp;
}
break;
//LED常亮可以忽略改变LED状态
/*
case(2):
{
led1 = 0;
led2 = 0;
led3 = 0;
}
break;
*/
}
}
}
}
//-----------------------------------------------
//上面程序中有很多地方可以优化,这里只是给出一个参考供学习。
Ⅳ 如何使用旋转编码开关
具有左转,右转,按下三个功能。4、5 脚是中间按下去的开关接线 1 2 3 脚 一般是中间2
脚接地,1、3 脚上拉电阻后,当左转、右转旋纽时,在1、3 脚就有脉冲信号输出了。
着这是标准资料:
在单片机编程时,左转和右转的判别是难点,用示波器观察这种开关左转和右转时两个输出
脚的信号有个相位差,见下图:
由此可见,如果输出1 为高电平时,输出2 出现一个高电平,这时开关就是向顺时针旋转; 当输
出1 为高电平,输出2 出现一个低电平,这时就一定是逆时针方向旋转.
所以,在单片机编程时只需要判断当输出1 为高电平时,输出2 当时的状态就可以判断出是左
旋转或是右旋转了。
还有另外一种3 脚的,除了不带按钮开关外,和上面是一样的使用。
参考:
#include "reg51.h"
#define uint unsigned int
sbit CodingsWitch_A=P1_1;
sbit CodingsWitch_B=P1_2;
uint CodingsWitchPolling()//
{
static Uchar Aold,Bold; //定义了两个变量用来储蓄上一次调用此方法是编码开关两引
脚的电平
static Uchar st; //定义了一个变量用来储蓄以前是否出现了两个引脚都为高电
平的状态
uint tmp = 0;
if(CodingsWitch_A&&CodingsWitch_B)
st = 1; //
if(st) //如果st 为1 执行下面的步骤
{
if(CodingsWitch_A==0&&CodingsWitch_B==0) //如果当前编码开关的两个引脚
都为底电平执行下面的步骤
{
if(Bold) //为高说明编码开关在向加大的方向转
{
st = 0;
tmp++; //
}
if(Aold) //为高说明编码开关在向减小的方向转
{
st = 0;
tmp--; //设返回值
}
}
}
Aold = CodingsWitch_A; //
Bold = CodingsWitch_B; //储
return tmp; //
}
//
Ⅳ 单片机 一个按钮设置按一下加1 另一个按键按一下减1 求帮忙编写程序
#include<reg52>
#define uchar unsigned char
#define uint unsigned int
sbit K1 = P1^4;
sbit K2 = P1^5;
uchar data K1state;
uchar data K2state;
uint data num,ntmp;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x06f,0x77,0x7c,0x39,0x5e,0x79,0x71} ;
uchar data showIndex,indexTmp;
uchar data W[8];
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);//能使之延时接近1毫秒就成 无需精确
}
void main()
{
K1state = 0xFF;
K2state = 0xFF;
num = 0;
while(1)
{
delay(1);//每毫秒轮询一回
//移位法,延时防抖
K1state = (K1state<<1);
K2state = (K2state<<1);
if(K1) K1state++;
if(K2) K2state++;
//检查开关状态
if(K1state==0x80) num++;
if(K2state==0x80) num--;
for(indexTmp=0,ntmp = num;indexTmp<=7;indexTmp++)
{
W[indexTmp] = num%10;
num /=10;
}
P0 = (0x01<<showIndex);//位选
P2 = table[W[showIndex]];//段选
showIndex++;
if(showIndex>=8)
showIndex=0;
}
}
看了你的全图,修改后了,用Keil uVision 3或4都可以,编译后可以查看对应的汇编代码
程序稍大一点的,不会有人用汇编来给你蘑菇,汇编设计写编码太慢了,开发代价不值得
Ⅵ 十二、利用单片机、1个按钮(注意是按钮,不是开关)、8个LED发光二极管(水平排列),实现按钮按下次数
原理图如下:
希望对你有所帮助