单片机流水灯程序按键

2019-12-21 15:03:29 weixin_46063794 阅读数 307

51单片机怎么在定时器流水灯里加按键控制程序


怎么让key1按下去向左流水而key2按下去向右流水?


已经定义好key
↓↓↓↓↓↓↓↓↓↓↓↓↓↓

sbit key1=P3^2;
sbit key2=P3^3;


void time0init1() interrupt 1
{
static u16 i=0,n;
i++;
if(i == 5000)
{
LED=~(0x01<<n);
if(++n==8)n=0;
i=0;
}
TH0=0xfc;
TL0=0x18;
}

2016-01-25 12:06:58 baidu_33836580 阅读数 3642


要求:8个流水灯靠一个按键启动,3种不同的点亮方式。

按一下,显示第一种方式,再按一下,切换方式,再一下,再切换。

不用中断。

----------------

不让使用中断,这个要求的比较特殊。

虽然没有明确要求流水灯的切换时间,但是,延时几百毫秒,也是应该有的。

而对按键的检测,应该是在 10 毫秒左右就检测一次。

那么,只好在延时函数中,进行检测了。

做而论道写的程序如下,该答案已经在今天 18:05 被提问者采纳,

----------------

P3.7 连接按键,P2 外接 LED。


没有使用中断。


#include<reg51.h>

#include<intrins.h>

sbit key = P3^7;

unsigned  char  kc, kb, kz, mode = 2, aa = 0xff;

void delay10ms(void)

{

    unsigned  int  i, j;

    for (i = 0; i < 60; i++)  for (j = 0; j < 20; j++);//循环约 10ms


    kc = ~key;           //读入按键,按下时 kc=1

    kz = kc ^ kb;        //和上次的相异或

    kb = kc;             //保存本次键值


    if (kz & kb)  {      //如果是刚按下

      mode++;

      mode %= 3;

      if (mode == 0)  aa = 0x7f;   //3种方式

      if (mode == 1)  aa = 0x3f;

      if (mode == 2)  aa = 0x1f;

    }

}


main()

{

    char  i;

    while(1)   {

      for (i = 0; i < 50; i++)  {

        delay10ms();

        if (kz & kb)  break;

      }

      P2 = aa;

      aa = _cror_(aa, 1);

    }

}


本程序给出的三种方式,显得简陋了一些。

试试看吧。


提问者评价:谢谢了。

题目链接:http://zhidao.baidu.com/question/1493910527414282819.html


----------------


上述的程序,可以用下图来仿真:

用 C 语言编写一个单片机流水灯程序 - 非著名博主 - 电子信息角落


图片链接:http://xiangce.baidu.com/picture/detail/e14083d1450e19b2b426f193e719de86e33b7b3f


----------------


后来,觉得上述三种方式,确实太简陋,就又改动了一下。

现在,可以实现四种方式,流水的方向、速度,都是可以变化的。


程序如下:

#include<reg51.h>

#include<intrins.h>


sbit key = P3^7;


char  kc, kb, kz, mode = 3, aa = 0xff, bb = 50;


void delay10ms(void)

{

    int  i, j;

    for (i = 0; i < 60; i++)  for (j = 0; j < 20; j++);

    kc = ~key;

    kz = kc ^ kb;

    kb = kc;

    if (kz & kb)  {

      mode++;

      mode %= 4;

      if (mode == 0)  {bb = 25; aa = 127;}  //高速

      if (mode == 2)  {bb = 50; aa = 63;}   //低速

    }

}


main()

{

    char  i;

    while(1)   {

      for (i = 0; i < bb; i++)  {

        delay10ms();

        if (kz & kb)  break;

      }

      P2 = aa;

      if (mode % 2)  aa = _cror_(aa, 1);  //右移

      else           aa = _crol_(aa, 1);  //左移

    }

}

----------------

后记:

在本程序中,流水灯和检测按键,都不耽误,互不干扰。

对于按键检测,也包括了消抖、确认释放等环节,不会出现误操作。

虽然没有用到中断,按键的反应,依然很灵敏。

虽然没有用到定时器,各个部分时间段,依然很精确,至少用肉眼是看不出来差别的。

很多人编写延时程序,只是知道延时,却不知道在延时期间,还是可以干很多活的。


如果能学会本程序的编程思路,实现多任务的环境,就不难了。

2018-05-02 22:07:04 Cheetah2 阅读数 12244
/**************************************************************************************
*                       按键控制LED流水灯实验  *
实现现象:定义按键 1,控制流水灯从中间 LED 依次向外点亮,再从两侧向中间依次熄灭,重复
          此过程。按键控制流水灯的运行与暂停  
***************************************************************************************/


#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器


typedef unsigned int u16;  //对数据类型进行声明定义
typedef unsigned char u8;


#define led P2   //将P2口定义为led 后面就可以使用led代替P2口


sbit k1=P3^1;   //定义独立按键1


u16 lightled[6]={0xe7,0xdb,0xbd,0x7e,0xbd,0xdb}; //小灯显示方式


/*******************************************************************************
* 函 数 名         : delay
* 函数功能   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}


/*******************************************************************************
* 函 数 名         : keypros
* 函数功能   : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
if(k1==0)                    //检测按键K1是否按下
{
delay(1000);                    //消除抖动 一般大约10ms
if(k1==0)                    //再次判断按键是否按下
{
while(!k1);                //检测按键是否松开
while(1) //按下后说明需要停止,就会进入这个死循环函数,知道按键再次按下
{
    delay(50000); //用循环的延时函数来实现停止
if(k1==0) //检测按键K1是否按下

    delay(1000);    //消除抖动 一般大约10ms
if(k1==0) //再次判断按键是否按下
{
     while(!k1); //检测按键是否松开
 break; //说明再一次按下了按键,需要进行实验,用break 来跳出循环
}
}
}
}
}
}


/*******************************************************************************
* 函 数 名       : main
* 函数功能 : 主函数
* 输    入       : 无
* 输    出     : 无
*******************************************************************************/
void main()
{
u8 i;
led=0x00;                  //刚开始让小灯全亮
delay(50000);                 //大约延时450ms
while(1)
{
for(i=0;i<6;i++)      //将led左移一位
{
led=lightled[i];
delay(50000);         //大约延时450ms
keypros();  //检测按键是否按下
}
}
}
2018-07-14 17:27:37 qq_27485531 阅读数 15623

要用51单片机实现流水灯操作我想是每个初学者学习单片机,了解嵌入式的第一个动手的小实验吧,今天在重新学习的时候遇到了一点小问题,在这里和大家分享一下。

要想控制流水灯操作其实是用单片机给每个二极管高低电平来控制灯的亮与不亮。

我用的51单片机学习板的二极管的硬件原理图如下图所示

板子上电之后,J2是跳线帽,一般是连接上的,再过来是LED1~LED8共8个发光二极管,然后经过电阻连接到51单片机的8个P1端口上。

电阻的作用是为了限流,是为了达到二极管规定的电压与电流,避免烧坏二极管。

51单片机上电引脚默认是高电平,所以我们通过给P1各个引脚低电平(即逻辑0),电路即导通则指定的二极管变亮(因为二极管的单向导电性,阳极电压高于阴极电压则二极管导通,则灯亮)。

刚开始我写的程序如下

因为编译器会一直执行主函数里的程序,所以单片机的第一个灯则一直亮

sbit 是位操作,P1^0即对P1的第0位进行操作,所以要想控制哪个灯亮则对哪个位进行置0操作即可。

接下来我又进行了一个操作,我想使8个灯依次点亮,我用了左移运算符 <<,因为单片机的初始引脚都是高电平,所以P1端口8个位的初始值是0xff(即8个位是 1111 1111)依次点亮即每次左移一位即可。所以我进行了如下操作。

我的理解是8个灯依次亮直到全亮,结果实验现象为只有第一个灯亮,当时我就很郁闷,与我设想的实验现象不一致,然后我又回头从新按照网上的一些资料从新编程,结果如下

这次的实验现象为依次点亮直到全亮(由于懒得放视频,就口头描述现象)

这时我就比较纳闷了因为新的程序只比我的多了一个while(1)死循环,但是我当时的理解是程序是一直会执行主函数里的程序,所以我就又做了一个实验来验证我的想法结果如下

假如灯只亮灭一次,那么主函数只执行一次,结果一直在那亮灭,就说明我理解的没有错误,主函数一直在重复执行

这时我就纳闷了,我预想的第一个实验加while 与不加while的实验现象应该都是一样的啊,执行一次主函数P1左移一位,灯依次点亮直到全亮,也是一个无限循环与wile(1)的操作应该是一样的啊,这时我就去请教了一下我的大哥,哈哈哈,终于在一顿激烈的讨论下,得出了一个结论,我的理解如下,加了while(1)的主函数在进行第一次的时候,在执行第一次的主函数时进行了无限循环,即一直是在执行第一次的主函数,P1的值一直是一个局部变量,一直在接着上次的值在改变,而没有加while(1)的则进行了无限次循环,每次循环则重新调用库函数里的P1值每次都是0xFF,左移一位每次都是0xFE,那么每次循环则是第一个灯亮这样就能解释为什么两个实验现象不一致(比较绕,要对c语言变量的作用域与生存空间有一定理解,c语言有一定基础)

所以我就行进行了如下实验来验证这个猜想

如果猜想正确,那么实验现象就应该是第一个灯亮然后8个全亮,接着又是第一个灯亮,怀着激动地心情我烧录了程序之后,果然和我想的一样!!!

最后实现简单流水灯的终极操作如下

所以我们在以后的编程里要注意这个坑!!!

变量的作用域和作用的作用范围,要不然会出现很多难以理解的现象。

 

2016-01-25 12:09:03 baidu_33836580 阅读数 7757

使用C语言编写程序,51单片机通过四个开关(c10~c13)控制LED灯(8颗)的左移右移。


要求:


开关c10控制一颗LED灯向左移;

开关c11控制一颗LED灯向右移;

开关c12控制三颗LED灯同时向左移;

开关c13控制三颗LED灯同时向右移。


是循环移动,时间要求好像是 200ms。


题目链接:http://zhidao.baidu.com/question/680122406274752172.html


这不就太简单了!


如下即可:


#include<reg51.h>

#include<intrins.h>

main()

{

    unsigned char  i, j, M = 0, led1 = 0xfe, led3 = 0xf8;

    while(1) {

      if (M == 0) {P0 = led1; led1 = _cror_(led1, 1);}   //P0外接LED

      if (M == 1) {P0 = led1; led1 = _crol_(led1, 1);}

      if (M == 2) {P0 = led3; led3 = _cror_(led3, 1);}

      if (M == 3) {P0 = led3; led3 = _crol_(led3, 1);}

      for(i = 0; i < 255; i++)  for(j = 0; j < 200; j++);//延时约200ms

      if(P1 == 0xfe) M = 0;

      if(P1 == 0xfd) M = 1;    //P1.0~P1.3,外接四个按键或开关

      if(P1 == 0xfb) M = 2;

      if(P1 == 0xf7) M = 3;

    }

}


提问者评价:谢谢!