找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 305|回复: 9
打印 上一主题 下一主题
收起左侧

九齐NY8A051H单片机程序,大佬帮忙看看,灯效进行不下去

[复制链接]
跳转到指定楼层
楼主
ID:1077269 发表于 2025-8-2 11:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这是我写的一个按键切换3颗LED灯的灯光效果代码,想要实现的效果是,按下开关,实现灯效:
(1)3颗LED灯全亮;
(2)3颗LED灯全亮2秒,全灭2秒,循环;
(3)只有1号灯亮2秒,接着,只有2号灯亮2秒,最后只有3号灯亮2秒,循环;
(4)3颗LED灯全灭;
全局效果:当有LED灯点亮时,开始倒计时30分钟,期间没有按下开关,LED灯全灭,IC进入睡眠,等待开关唤醒。

目前我的代码只能在两个灯效之间切换,无法做的4个灯效切换,而且延时30分钟效果不知道怎么进行,求大佬帮忙完善一下!!!

按键切换3灯灯效.docx

12.75 KB, 下载次数: 0

代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1089588 发表于 2025-8-4 14:14 | 只看该作者
有开总中断吗,你的delay要2000
回复

使用道具 举报

板凳
ID:1157445 发表于 2025-8-4 15:51 | 只看该作者
按键部分的问题:1、按下以后Mod会一直加,最好是识别到弹起再加一;2、Mod等于4就置零需要写在Mod++后面,且最好是大于等于4;3、switch增加default。
回复

使用道具 举报

地板
ID:1073939 发表于 2025-8-8 13:33 | 只看该作者
代码结构有问题。你这种软件延时在代码更改工作模式后还是会继续延时,不会立即按新模式进行。要以状态机的方式组织代码。
回复

使用道具 举报

5#
ID:1077269 发表于 2025-8-12 12:00 | 只看该作者
a825563619 发表于 2025-8-4 14:14
有开总中断吗,你的delay要2000

delay时间长了,watchdog 重置了,灯一直频闪,现在不知道怎么操作,刚接触这款单片机,大佬能不能帮我改一下?
回复

使用道具 举报

6#
ID:1077269 发表于 2025-8-12 12:03 | 只看该作者
柠檬脆片 发表于 2025-8-4 15:51
按键部分的问题:1、按下以后Mod会一直加,最好是识别到弹起再加一;2、Mod等于4就置零需要写在Mod++后面, ...

按键部分我是沿用官方示例代码的,应该不会出错,我现在尝试一下default语句
回复

使用道具 举报

7#
ID:1077269 发表于 2025-8-12 12:05 | 只看该作者
ydatou 发表于 2025-8-8 13:33
代码结构有问题。你这种软件延时在代码更改工作模式后还是会继续延时,不会立即按新模式进行。要以状态机的 ...

不太明白是什么意思,我刚接触单片机,网上都说九齐的容易学,大佬能不能帮我改一下?
回复

使用道具 举报

8#
ID:1073939 发表于 2025-8-16 14:56 | 只看该作者
setsu 发表于 2025-8-12 12:05
不太明白是什么意思,我刚接触单片机,网上都说九齐的容易学,大佬能不能帮我改一下?

暂时用你的软延时改了下。代码中不要有长时间(大于10毫秒)延时,中断中延时不要超过10us。
回复

使用道具 举报

9#
ID:1077269 发表于 2025-8-16 15:30 | 只看该作者
ydatou 发表于 2025-8-16 14:56
暂时用你的软延时改了下。代码中不要有长时间(大于10毫秒)延时,中断中延时不要超过10us。

能发出来看看吗?
回复

使用道具 举报

10#
ID:1073939 发表于 2025-8-16 15:58 | 只看该作者
setsu 发表于 2025-8-12 12:05
不太明白是什么意思,我刚接触单片机,网上都说九齐的容易学,大佬能不能帮我改一下?

用你的软延时做了个状态机。
以后编程要注意几点:
1.中断中延时不要超过10uS,不要做复杂运算。
2.不要使用超过20mS的延时,如有超过,请用状态机实现。
3.多使用标志。
4.其中10ms延时要用定时器实现。
  1. #include <ny8.h>
  2. #include "ny8_constant.h"
  3. #include "stdint.h"
  4. #define UPDATE_REG(x) __asm__("MOVR _" #x ",F")
  5. #define unchar unsigned char
  6. #define unint unsigned int

  7. unchar myvar; // 九齐单片机位定义,将一个char拆成8个bit变量
  8. __sbit key = PORTB : 0;
  9. __sbit light1 = PORTB : 1;
  10. __sbit light2 = PORTB : 2;
  11. __sbit light3 = PORTB : 4;
  12. #define light_get() (((PORTB >> 1) & 7) ? 1 : 0)
  13. #define light_set(x)             \
  14.         do                           \
  15.         {                            \
  16.                 PORTB &= 0xf1;           \
  17.                 PORTB |= ((x) & 7) << 1; \
  18.         } while (0)(PORTB |= 0x1 << x)

  19. unint Mod = 3;
  20. unint ModCnt = 0; // 计时,每10mS加1

  21. unchar keyFlag = 0;
  22. unchar keyCnt = 0; // 计时,每10mS加1

  23. unint sleepCnt = 0; // 计时,每10mS加1

  24. void delay(unint z) // 延时函数ms
  25. {
  26.         unint x, y;
  27.         for (x = z; x > 0; x--)
  28.                 for (y = 100; y > 0; y--)
  29.                         ;
  30. }
  31. void keyProc(void) // 按键处理函数,每10mS调用一次
  32. {
  33.         unchar i = key ? 1 : 0;
  34.         if (++keyCnt == 0)
  35.                 keyCnt--;
  36.         if (i == 0) // 按键按下
  37.         {
  38.                 if (keyFlag)
  39.                         keyCnt = 0;         // 按键按下计时开始
  40.                 if (keyCnt == 2) // 消抖
  41.                 {
  42.                         ModCnt = 0;
  43.                         if (++Mod == 4)
  44.                                 Mod = 0;
  45.                 }
  46.                 sleepCnt = 0;
  47.         }
  48.         else
  49.         {
  50.                 if (keyFlag == 0)
  51.                 {
  52.                         // 松手检测,如有松手要处理的代码写在这里
  53.                         sleepCnt = 0;
  54.                 }
  55.         }
  56.         keyFlag = i;
  57. }
  58. void ModProc(void)
  59. {
  60.         switch (Mod)
  61.         {
  62.         case 3: // 灯全灭
  63.                 if (ModCnt == 0)
  64.                         light_set(0);
  65.                 SLEEP(); // LED灯全灭,IC进入睡眠
  66.                 break;
  67.         case 0: // 灯全亮
  68.                 if (ModCnt == 0)
  69.                         light_set(7);
  70.                 break;
  71.         case 1: // 灯1亮 2秒,接着灯2亮 2秒,灯3亮 2秒
  72.                 if (ModCnt == 0 || ModCnt >= 600)
  73.                 {
  74.                         ModCnt = 0;
  75.                         light_set(1);
  76.                 }
  77.                 else if (ModCnt == 200)
  78.                         light_set(2);
  79.                 else if (ModCnt == 400)
  80.                         light_set(4);
  81.                 break;
  82.         case 2: // 灯全亮2秒,全灭两秒
  83.                 if (ModCnt == 0 || ModCnt >= 400)
  84.                         light_set(7);
  85.                 else if (ModCnt == 200)
  86.                         light_set(0);
  87.                 break;
  88.         default:
  89.                 Mod = 3;
  90.                 ModCnt = -1;
  91.                 break;
  92.         }

  93.         if (++sleepCnt >= 30 * 60 * 100) // 30分钟
  94.         {
  95.                 light_set(0);
  96.                 SLEEP(); // 点亮30分钟期间没有按下开关(按下会使sleepCnt清零),IC进入睡眠
  97.         }
  98. }

  99. void isr(void) __interrupt(0)
  100. {
  101.         // if(INTFbits.INTIF)
  102.         //{
  103.         //        //INTF = (unsigned char)~(C_INT_EXT);
  104.         //}

  105.         if (INTFbits.PBIF)
  106.         {
  107.                 INTFbits.PBIF = 0;
  108.                 sleepCnt = 0;
  109.         }
  110. }

  111. void lnit_Timer() // 中断初始化
  112. {
  113.         DISI();                                // 禁用中断
  114.         INTE = C_INT_PBKey; // 启用PB按键中断
  115.         ENI();                                // 启用中断
  116. }

  117. void lnit_Mod()
  118. {
  119.         BPHCON = (unsigned char)~(C_PB0_PHB); // 开启B0口上来电阻
  120.         BWUCON = C_PB0_Wakeup;                                  // 启用PB0输入唤醒功能
  121.         IOSTB = C_PB0_Input;
  122.         PORTB = 0x00;
  123. }

  124. void main(void)
  125. {
  126.         lnit_Mod();
  127.         lnit_Timer();
  128.         Mod = 0;
  129.         key = 1;
  130.         while (1)
  131.         {
  132.                 CLRWDT();
  133.                 delay(1); // 10mS,最好用定时器代替延时函数。
  134.                 keyProc();
  135.                 ModProc();
  136.         }
  137.         // while (1)
  138.         // {
  139.         //         if (gb10ms_flag) // 定时器中断使 gb10ms_flag=1
  140.         //         {
  141.         //                 gb10ms_flag = 0;
  142.         //                 CLRWDT();
  143.         //                 keyProc();
  144.         //                 ModProc()
  145.         //         }
  146.         // }
  147. }
复制代码



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表