关于51单片机的一些花式点灯的实验代码

使用编译器以及仿真工具 编译器 keil5 C 51 仿真工具 Proteus 8.15 任务名称:花式点灯 硬件平台:STC89C52(仿真内可用AT89S52替代),四个独立按键,八颗LED、 矩阵键盘,根据个人情况选择添加 任务需求: 1.系统上电后(开始仿真后)八颗LED流水闪烁一次(闪烁顺序为0123456780876543210)流水灯闪烁间隔时间为200ms 2.按下按键1,LED灯全部点亮,点亮1S后,自动熄灭 3.按下按键2,LED灯持续流水灯,(流水顺序1234567876543212345678765……)闪烁间隔100ms,再次按下按键2时,流水灯停止,所有LED灯熄灭 4.按下按键3,使用定时器控制8颗LED灯,实现呼吸灯效果,要求PWM频率为500hz,占空比动态变化实现呼吸灯,呼吸灯效果不做要求(占空比范围和变化时间),但要实现亮暗的变化 5.按下按键4,8颗LED灯随机点亮并闪烁(查阅随机数函数原理) 6.按下其他功能按键时,停止当前功能的运行,执行对应功能(程序的打断)

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int
    

sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit LED5 = P1^4;
sbit LED6 = P1^5;
sbit LED7 = P1^6;
sbit LED8 = P1^7;

sbit KEY1=P3^5;
sbit KEY2=P3^4;
sbit KEY3 = P3^3;
sbit KEY4 = P3^2;


bit Direct_flag = 0;     //LED的呼吸方向的开关
bit LED_flag = 0;       //LED工作状态的标志


/****全局变量****/
uchar flag = 0;  // 定义标志变量,控制流水灯的循环
uchar cnt = 0;   // 定义计数变量,控制流水灯的速度
uchar i = 0;     // 定义循环变量,控制流水灯的顺序
unsigned int PWM_wanttime=0;            //想要多长时间改变的占空比一次
unsigned int Breath_wanttime=0;        //想要多长时间改变呼气或者吸气的值时间
unsigned int  PWM_value = 0;                //占空比的大小
unsigned char led_num = 0;//用于存储当前随机点亮的LED灯的编号
unsigned char last_led_num = 0;//用于存储上一次随机点亮的LED灯的编号


/****函数声明****/
void T1init();
void KeyScan();
uchar GetRandomLED();//随机生成函数声明


void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}

void Timer0_Init()
{
     TMOD = 0x01;  // 设置定时器工作方式为方式1
    TH0 = (65536 - 20000) / 256;  // 设置定时器初值,定时20ms
    TL0 = (65536 - 20000) % 256;
    ET0 = 1;      // 开启定时器中断
    EA = 1;       // 开启总中断
}

void T1init()
{
    TMOD |= 0x10;    //设置定时器为工作方式1 
    TH1=0XFC;   //1ms定时,装入初值
    TL1=0X66;
    ET1 = 1;    //开定时器的中断
    TR1 = 1;    //开定时器
    EA = 1;     //开总中断
}


/*********************************************************
* 函数说明 :按键扫描函数
* 入口参数 :void
* 返回值   :void
*********************************************************/
void KeyScan()
{
                if(KEY1 == 0)  
                        {
                        delay(10);  
                        if(KEY1 == 0)  
                        {
                             P1 = 0x00;  
                             delay(1000);  
                             P1 = 0xff;  
                        }
                        
                        while(!KEY1);  
                    }
                
                    if(KEY2 == 0)  
                  {
                        while(!KEY2);   
                        flag = !flag;   
                        if(flag)
                        {
                             TR0 = 1;   
                        }
                        else
                        {
                             TR0 = 0;   
                             P1 = 0xff; 
                             i = 0;     
                        }
                  }
            if(KEY3 == 0) //如果按键被按下
        {
        delay(10); //消抖动处理

        if(KEY3 == 0) //再次确认按键是否被按下
        {
            while(KEY3 == 0); //等待按键释放

            if(LED_flag == 0) //如果LED灯当前是关闭状态,则打开LED灯并开始呼吸效果
            {
                TR1 = 1; //打开定时器,开始呼吸效果

                LED_flag = 1; //更新LED灯工作状态标志位
            }
            else if(LED_flag == 1) //如果LED灯当前是打开状态,则关闭LED灯并停止呼吸效果
            {
                TR1 = 0; //关闭定时器,停止呼吸效果

                PWM_wanttime = 0;      //清零PWM计数器
                Breath_wanttime = 0;   //清零呼吸计数器

                PWM_value = 0;         //清零PWM值

                Direct_flag = 0;       //重置方向标志位

                P1 = 0xFF;             //熄灭所有LED灯

                LED_flag = 0;          //更新LED灯工作状态标志位
            }
        }
    }
        
    
    //此处编写按键4的函数逻辑代码
     if(KEY4 == 0) //如果按键被按下
    {
        delay(10); //消抖动处理

        if(KEY4 == 0) //再次确认按键是否被按下
        {
            while(KEY4 == 0); //等待按键释放
              
              
              
              
                if(last_led_num != 0) //如果之前有点亮的LED,则熄灭它
            {
                switch(last_led_num)
                {
                    case 1:
                        LED1 = 1;
                        break;
                    case 2:
                        LED2 = 1;
                        break;
                    case 3:
                        LED3 = 1;
                        break;
                    case 4:
                        LED4 = 1;
                        break;
                    case 5:
                        LED5 = 1;
                        break;
                    case 6:
                        LED6 = 1;
                        break;
                    case 7:
                        LED7 = 1;
                        break;
                    case 8:
                        LED8 = 1;
                        break;
                    default:
                        break;
                }
            }

           led_num = GetRandomLED(); //获取随机LED编号

            switch(led_num) //根据随机LED编号点亮对应的LED灯
            {
                case 1:
                    LED1 = 0;
                    break;
                case 2:
                    LED2 = 0;
                    break;
                case 3:
                    LED3 = 0;
                    break;
                case 4:
                    LED4 = 0;
                    break;
                case 5:
                    LED5 = 0;
                    break;
                case 6:
                    LED6 = 0;
                    break;
                case 7:
                    LED7 = 0;
                    break;
                case 8:
                    LED8 = 0;
                    break;
                default:
                    break;
            }
                
                   last_led_num = led_num; //保存当前点亮的LED编号
        }
    }
    
    
}

unsigned char GetRandomLED()
{
    return (rand() % 8) + 1; //生成一个范围在1~8之间的随机数
}

void main()
{
    uchar i;

     Timer0_Init(); // 定时器0初始化
     T1init();//定时器1初始化    
    
        for(i=0;i<8;i++)
        {
            P1 = ~(0x01 << i);
            delay(200);
        }
        for(i=0;i<7;i++)
        {
            P1 = ~(0x40 >> i);
            delay(200);
              P1=0XFF;
        }
          while(1)
                {
                 KeyScan(); //在主循环中调用按键扫描函数
                    
             }
}

void timer0() interrupt 1  // 定时器0中断服务函数
{
    TH0 = (65536 - 20000) / 256;  // 设置定时器初值,定时20ms
    TL0 = (65536 - 20000) % 256;
    cnt++;  // 计数变量自增
    if(cnt == 10)  // 每隔200ms执行一次
    {
        cnt = 0;  // 清零计数变量
        if(flag)  // 检查标志变量的值
        {
            if(i < 8)
            {
                P1 = ~(0x01 << i);
                i++;
            }
            else if(i < 15)
            {
                P1 = ~(0x40 >> (i - 8));
                i++;
            }
            else
            {
                i = 0;
            }
        }
    }
}

void Time1(void) interrupt 3
{
    if(LED_flag == 1) //如果LED灯处于打开状态,则执行呼吸效果代码
    {
        TH1=0XFC;   //1ms定时,装入初值
        TL1=0X66;

        PWM_wanttime++;            //改变的占空比一次的标志
        Breath_wanttime++;        //呼气或者吸气的时间改变的标志

        if(PWM_wanttime == PWM_value)          //判断是否到了点亮LED的时候
        {
            LED1 = 0;     //点亮LED1
            LED2 = 0;
            LED3 = 0;
            LED4 = 0;
            LED5 = 0;
            LED6 = 0;
            LED7 = 0;
            LED8 = 0;
        }

        if(PWM_wanttime == 10)                //当前周期结束
        {
            //熄灭所有LED
            LED1 = 1;
            LED2 = 1;
            LED3 = 1;
            LED4 = 1;
            LED5 = 1;
            LED6 = 1;
            LED7 = 1;
            LED8 = 1;

            PWM_wanttime = 0; //重新计时,去改变占空比
        }

        if((Breath_wanttime == 200) && (Direct_flag == 0))      //200ms 改一次占空比,占空比每次增加10%
        {  
            Breath_wanttime = 0;
            PWM_value++;                //改变占空比的值

            if(PWM_value == 9)          //占空比更改方向
                Direct_flag = 1; 
        }

        if((Breath_wanttime == 200) && (Direct_flag == 1))      //200ms 改一次占空比,占空比每次减少10%
        {  
            Breath_wanttime = 0;

            PWM_value--;                //改变占空比的值

            if(PWM_value == 1)          //占空比更改方向
                Direct_flag = 0;
        }
    }
}
 

实验现象

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值