找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1389|回复: 6
收起左侧

想做手电驱动 stc8g1k单片机这个代码有点问题

[复制链接]
ID:1062408 发表于 2023-8-2 11:56 | 显示全部楼层 |阅读模式
我的要求是接通电源led1先亮然后按一下开关en亮再按都不亮电流ua睡眠模式再按开关回到开头led1亮
现在问题是接通电源led1亮,按一下开关en亮,再按一下睡眠都不亮,然后再按几下开关(快速按十下左右或慢按十下左右)才能回到led1亮的状态
本来想搞手电断电换挡,搞不定先搞这个不断电开关换挡要求关掉电流要ua,断电换挡有没有大神有代码也给个
手电驱动.jpg
单片机代码如下
  1. #include "STC8G.H"
  2. #include<intrins.h>
  3. #define MAIN_Fosc                12000000L
  4. typedef unsigned char uchar;
  5. typedef unsigned int uint;


  6. sbit LED=P5^4;
  7. //sbit LED2=P5^5;
  8. sbit EN=P5^5;
  9. sbit key=P3^2;
  10. sbit INT0=P3^2;
  11. uchar count=0,count1=0;
  12. uint num=0;
  13. bit i=0,j=0;


  14. /*void  delay_ms(uint a)
  15. {
  16.         unsigned int i;
  17.         do
  18.         {
  19.                 i = MAIN_Fosc / 10000L;
  20.                 while(--i)        ;
  21.         }while(--a);
  22. }
  23. /**************中断服务程序*****************/
  24. void delay(uint a)
  25. {
  26.         uint i,j;
  27.         for(i=0;i<a;i++)
  28.                 for(j=0;j<500;j++);
  29. }


  30. void INT0_Isr() interrupt 0
  31. {
  32. //P32 = !P32;                                 //测试端口


  33.                      EA=1;
  34.                 IT0=1;
  35.                 EX0=1;
  36.                 PCON=0x00;                             
  37. }
  38. void Timer0Init()        //500微秒@12.000MHz
  39. {
  40.         TMOD |= 0x01;                //设置定时器模式
  41.         TL0 = 0x0C;                //设置定时初值
  42.         TH0 = 0xFE;                //设置定时初值
  43.         TR0 = 1;                //定时器0开始计时
  44.         EA = 1;
  45.         ET0 = 1;
  46. }


  47. void main()
  48. {
  49.         P1M0 = 0x00; P1M1 = 0x00;
  50.        //P1口设置为准双向口
  51.             P3M0 = 0x00; P3M1 = 0x04;
  52.     //P3M0 = 0x00; P3M1 = 0x00;
  53.         //P3口设置为准双向口
  54.             P5M0 = 0x00; P5M1 = 0x00;
  55.         
  56.          //LED2=1;
  57.         Timer0Init();
  58.         while(1)
  59.         {
  60.                 if(key==0)
  61.                 {
  62.                         delay(20);
  63.                         if(key==0)
  64.                         {
  65.                                 count++;
  66.                                 if(count>2)
  67.                                         count=0;
  68.                                 while(!key);
  69.                         }
  70.                 }
  71.                                                                     
  72.      
  73.                      
  74.                        
  75.      
  76.         }
  77. }
  78. /**************中断服务程序*****************/
  79. void timer0() interrupt        1        //500微秒@12.000MHz
  80. {
  81.         TL0 = 0x0C;                //设置定时初值
  82.         TH0 = 0xFE;                //设置定时初值
  83.         i=~i;
  84.         if(count==0){LED=0;EN=1;}
  85.         /*if(count!=0)
  86.         {
  87.                 num++;
  88.                 if(num<=9600)
  89.                         j=1;
  90.                 else j=0;
  91.                 if(num>=10000)
  92.                         num=0;
  93.         }*/
  94.         if(count==1){LED=1;EN=0;}
  95.         if(count==2)
  96.                                         {  
  97.                                                      EN=1;
  98.                  IT0 = 1;                //INT0 下降沿中断               
  99.                 IE0 = 0;                //清除外中断0标志位
  100.                 _nop_();
  101.                 _nop_();
  102.                 EX0 = 1;                //INT0 允许中断
  103.                 _nop_();
  104.                 _nop_();
  105.                 PCON |= 0x02;        //Sleep
  106.                 _nop_();
  107.                 _nop_();
  108.                 _nop_();
  109.                   
  110.          }
  111. }                  
复制代码

      

回复

使用道具 举报

ID:155785 发表于 2023-8-11 23:50 | 显示全部楼层
大佬搞定没,最近也在做这个玩
回复

使用道具 举报

ID:1062408 发表于 2023-8-2 18:57 | 显示全部楼层
lkc8210 发表于 2023-8-2 16:22
可能是因为在定时中断里睡眠然后外中断唤醒引起中断冲突
可参考以下代码

搞定了要p3.2要设置准双向口,这里高手就是多,非常感谢,接下来自己研究下断电换挡
回复

使用道具 举报

ID:213173 发表于 2023-8-2 17:12 | 显示全部楼层
这个示例与你的需求非常接近,稍改一下即可满足。
一键开关机(掉电唤醒).rar (12.61 KB, 下载次数: 13)
回复

使用道具 举报

ID:161164 发表于 2023-8-2 16:22 | 显示全部楼层
可能是因为在定时中断里睡眠然后外中断唤醒引起中断冲突
可参考以下代码
  1. #include "STC8G.H"
  2. #include<intrins.h>
  3. #define MAIN_Fosc                12000000L
  4. typedef unsigned char uchar;
  5. typedef unsigned int uint;
  6. sbit LED=P5^4;
  7. //sbit LED2=P5^5;
  8. sbit EN=P5^5;
  9. sbit key=P3^2;
  10. sbit INT0=P3^2;
  11. uchar count=0,count1=0;
  12. uint num=0;
  13. bit i=0,j=0;
  14. /**************中断服务程序*****************/
  15. void delay(uint a)
  16. {
  17.         uint i,j;
  18.         for(i=0; i<a; i++)
  19.                 for(j=0; j<500; j++);
  20. }
  21. void INT0_Isr() interrupt 0
  22. {
  23.         EX0=0;
  24.         PCON=0x00;
  25.         count = 3;
  26. }
  27. void Timer0Init()        //500微秒@12.000MHz
  28. {
  29.         TMOD |= 0x01;                //设置定时器模式
  30.         TL0 = 0x0C;                //设置定时初值
  31.         TH0 = 0xFE;                //设置定时初值
  32.         TR0 = 1;                //定时器0开始计时
  33.         EA = 1;
  34.         ET0 = 1;
  35. }
  36. void main()
  37. {
  38.         P3M0 = 0x00;
  39.         P3M1 = 0x04;
  40.         //P3M0 = 0x00; P3M1 = 0x00;
  41.         //P3口设置为准双向口
  42.         P5M0 = 0x00;
  43.         P5M1 = 0x00;
  44.         //LED2=1;
  45.         Timer0Init();
  46.         IT0 = 1;                //INT0 下降沿中断
  47.         while(1)
  48.         {
  49.                 if(count==0)
  50.                 {
  51.                         LED=0;
  52.                         EN=1;
  53.                 }
  54.                 if(count==1)
  55.                 {
  56.                         LED=1;
  57.                         EN=0;
  58.                 }
  59.                 if(count==2)
  60.                 {
  61.                         EN=1;
  62.                         IE0 = 0;                //清除外中断0标志位
  63.                         _nop_();
  64.                         _nop_();
  65.                         EX0 = 1;                //INT0 允许中断
  66.                         _nop_();
  67.                         _nop_();
  68.                         PCON |= 0x02;        //Sleep
  69.                         _nop_();
  70.                         _nop_();
  71.                         _nop_();
  72.                 }
  73.         }
  74. }
  75. /**************中断服务程序*****************/
  76. void timer0() interrupt        1        //500微秒@12.000MHz
  77. {
  78.         static uint delay_xd= 0;
  79.         TL0 = 0x0C;                //设置定时初值
  80.         TH0 = 0xFE;                //设置定时初值
  81.         if(key)
  82.         {
  83.                 if(delay_xd)
  84.                 {
  85.                         delay_xd--;
  86.                         if(!delay_xd)
  87.                         {
  88.                                 count++;
  89.                                 if(count>2)count=0;
  90.                         }
  91.                 }
  92.         }else{
  93.                 delay_xd= 40;
  94.         }
  95. }
复制代码



回复

使用道具 举报

ID:1062408 发表于 2023-8-2 15:19 | 显示全部楼层
count = 0有了,这个程序就是一键循环改的,就是按一下开关1个io口亮,再按下另一个io口亮,再按下都不亮,循环,现在就是再按下都不亮这第三个状态加入睡眠低功耗模式使电流降到ua,但现在问题就是睡眠后要按十次左右按键才能回到第一个状态led1,这个感觉有点无法理解,为什么要按十次
回复

使用道具 举报

ID:1087948 发表于 2023-8-2 14:45 | 显示全部楼层
根据您提供的代码,我看到你已经实现了按一下开关EN后LED1亮,并按一下EN后进入睡眠模式。但是你遇到了一些问题:再按一下EN时不亮,需要按几下EN才能回到LED1亮的状态。

首先,让我们来看一下你的代码中的一些问题:

在INT0_Isr()函数中,你设置了EA=1和IT0=1以及EX0=1。这些设置应该在main()函数中进行,而不是在中断服务程序中。

在timer0()中断服务程序中,你使用了if(count==2)条件来处理EN亮的情况。但是你没有给count重新赋值的语句,导致当count为2时,无法执行任何操作。你可以添加类似count = 0;的语句来重新初始化count变量。

在timer0()中断服务程序中,你使用了PCON |= 0x02;来使芯片进入睡眠模式。但是在STC8系列单片机中,要进入睡眠模式,还需要设置PCON寄存器的其他位。例如,你可以使用PCON |= 0x03;来设置Power-down模式。

解决这些问题后,你可以尝试以下步骤来实现你的要求:

将EA=1,IT0=1和EX0=1的设置放在main()函数中。

在timer0()中断服务程序中,添加count = 0;来重新初始化count变量。

修改timer0()中断服务程序中的PCON |= 0x02;为PCON |= 0x03;来设置Power-down模式。

请注意,在睡眠模式下,所有的IO口都会被禁止,所以你需要确保EN引脚在进入睡眠模式前已经被拉低。

另外,如果你希望在按一下EN后再按也能回到LED1亮的状态,你可能需要在INT0_Isr()中加入相关的逻辑来实现这个功能。你可以使用一个状态变量来记录当前的状态,根据按下EN的次数进行切换。

最后,关于手电断电换挡的问题,这涉及到更复杂的电路设计和控制算法,可能超出了这个问题的范围。建议您参考相关的电路设计资料或咨询专业人士来获取更详细的帮助。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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