发新帖我要提问
12
返回列表
打印

被一个简单的功能程序搞蒙了

[复制链接]
楼主: LKC134
手机看帖
扫描二维码
随时随地手机跟帖
21
叶春勇| | 2019-5-18 18:32 | 只看该作者 回帖奖励 |倒序浏览
定时器中断时间缩短。
定义一个变量,不断累加。
例如1ms。
这样1ms扫描次键盘。
累加10次,扫描数码管。

使用特权

评论回复
22
LKC134|  楼主 | 2019-5-19 13:16 | 只看该作者
叶春勇 发表于 2019-5-18 18:32
定时器中断时间缩短。
定义一个变量,不断累加。
例如1ms。

明白,加了保存EEPROM设置还是会影响的,按键按一下就闪一下

使用特权

评论回复
23
xch| | 2019-5-19 19:29 | 只看该作者
void delayxms(uint z)
{
uint y,x;
for(y=z;x>0;x--)        //使用x之前未初始化。for(x=z;x>0;x--)?
    for(y=110;y>0;y--);
   }

这个明显错误

使用特权

评论回复
24
LKC134|  楼主 | 2019-5-19 19:45 | 只看该作者
xch 发表于 2019-5-19 19:29
void delayxms(uint z)
{
uint y,x;

是的,我已改回来了,thanks!

使用特权

评论回复
评论
xch 2019-5-19 20:12 回复TA
这个函数多余。给你修改好程序了。楼下 
25
xch| | 2019-5-19 20:06 | 只看该作者
本帖最后由 xch 于 2019-5-19 20:10 编辑
LKC134 发表于 2019-5-17 19:08
附图是原理图,请各位指点迷津。

include"STC15W.H"
#include"intrins.h"
#define uchar unsigned char  
#define uint unsigned int
void digplay(uint hig);
void key();
sbit PWM=P1^7;
sbit LED1=P5^5;
sbit up=P1^4;
sbit down=P1^5;
sbit ba=P1^1;
sbit sh=P1^0;
sbit ge=P1^2;
sbit dn=P1^3;
uint hig=250;
uchar code LED[]={0xCF,0x81,0xEA,0xE3,0xA5,0x67,0x6F,0xC1,0xEF,0xE7,0x5e};
/************延时子程序*************/
void delayxms(uint z)
{
uint y,x;
for(y=z;x>0;x--)        //使用x之前未初始化。for(x=z;x>0;x--)?
    for(y=110;y>0;y--);
}

void KeyScan(void)//按键扫描
{
   static uchar key1_lock=0;//自锁标志
  static uint count1=0;//计数延时
  static uchar key2_lock=0;//
   static uint count2=0;//
   
        if(up==0)        //p1.4,s1,被按住
        {
                if((count1++>=5)&&(key1_lock==0))
                {
                        key1_lock=1;
                        LED1=~LED1;        //按键翻转LED1显示
                }
    }
   else
    {
            key1_lock=0;         
            count1=0;
    }        //end of up
        
        
    if(down==0)        //p1.5,s2
    {
        if((count2++>=5)&&(key2_lock==0))
        {
            key2_lock=1;
            LED1=~LED1;
                }
    }
    else
    {
        key2_lock=0;
        count2=0;
    }
}
                  
void Init2()//定时器2初始化
{
AUXR&=0x04;        //12T
    T2L=0x78;        //定时5MS
    T2H=0xec;        //
   
    IE2|=0x04;
    AUXR|=0x10;        //开始计时
   EA=1;
    }        

void digplay(uint hig)//数码管动态扫描
{

         static uchar i=0;

           P3=0x00;        //显示消隐
          switch(i)
          {
           case 0:

                         P1=0x02;        //点亮最高位
                         //P1=0x00;        //错误地立即关闭显示,应该删除
                                                 P3=LED[hig/100];
                         break;
           case 1:

                         P1=0x01;
                        // P1=0x00;//错误地立即关闭显示,应该删除
                                                        P3=LED[hig/10%10];
                         i++;
                         break;
           case 2:
                 P3=LED[hig%10];
                         P1=0x04;
                        // P1=0x00;//错误地立即关闭显示,应该删除
                                                P3=LED[hig/10%10];
                         i++;
                         break;
                 case 3:

                         P1=0x08;         
                        // P1=0x00;//错误地立即关闭显示,应该删除
                                                P3=0x5e;
                         i=0;
                         break;
                         }
                         //delayxms(5); //不该长时间延时,T2定时器将overflow
}

void main()//主程序
{
Init2();
P5M0=0xff;
   P5M1=0x00;
   P3M0=0xff;
   P3M1=0x00;
   P1M0=0xff;
   P1M1=0xf0;
while(1)
   {

     //digplay(hig); //不该在此调用显示函数,应该转到T2中断服务函数之中调用,改成idle操作为好
    }
}
void t2int() interrupt 12
{
        digplay(hig); //T2中断服务函数之中调用显示
    KeyScan();
}


改成这样

使用特权

评论回复
26
LKC134|  楼主 | 2019-5-20 09:46 | 只看该作者
xch 发表于 2019-5-19 20:06
include"STC15W.H"
#include"intrins.h"
#define uchar unsigned char  

多谢这位大神热心回复,我现在改成这样,请看下面,另外EERPOM这样放在按键任务后面不知合不合理?
void digplay(void)//数码管显示
{
  static uchar i=0;

        switch(i)
            {
           case 0:
                 P3=0x00;
                 P1=LED[hig/100];
                         P3=0x10;
                         i=1;
                         break;
           case 1:
                 P3=0x00;
                 P1=LED[hig/10%10];
                         P3=0x40;
                         i=2;
                        break;
          case 2:
                P3=0x00;
                P1=LED[hig%10];
                        P3=0x20;
                        i=3;
                        break;
          case 3:
                P3=0x00;
                       
                P1=0xe5;  //单位C
                        P3=0x80;
                       
                        i=0;
                        break;
                        default:
                        i=0;
                        break;
                   }
/**********按键扫描**************/
void KeyScan(void)
{
  static uchar key1_lock=0;//按键自锁标志
  static uint count1=0;//计数变量
  static uint key_contin_Cnt1=0; //连击计数

  static uchar key2_lock=0;//按键自锁标志
  static uint count2=0;//计数变量
  static uint key_contin_Cnt2=0;        //连击计数

  if(0!=up)//检测按键如果没有按下就清零 ,《 按键加》
  {
   key1_lock=0;          //解锁
   count1=0;          //延时计数清零
   key_contin_Cnt1=0;//连击计数清零
   }
   else  if(0==key1_lock)         //按键被按下
         {
          count1++;
          if(count1>=key_short_time)          //消抖(20ms)
          {
            
                key1_lock=1;  //自锁标志
                key_sec=1;         //短按触发序号         
                count1=0;
                 }
                }
else
      if(count1<key_encont_time) //按住不松手累中到1000MS
            {
           count1++;
           }
        else
           {
             key_contin_Cnt1++;           //连击计数开始累加
           if(key_contin_Cnt1>=key_continu_time)        //按住不松手,每0.3秒触发一次
           {
            key_contin_Cnt1=0;
                 key_sec=2;                //连击触发序号
                }
        }

if(0!=down)          //按键减
  {
    key2_lock=0;
        count2=0;
        key_contin_Cnt2=0;
        }
  else        if(0==key2_lock)
        {
          count2++;
         if(count2>=key_short_time)
         {

            count2=0;
          key2_lock=1; //按键自锁标志置1
          key_sec=3;  
          }
        }
else
           if(count2<key_encont_time)
           {
            count2++;
          }

        else
     {
    key_contin_Cnt2++;
    if(key_contin_Cnt2>=key_continu_time)
          {
           key_contin_Cnt2=0;
           key_sec=4;
           }
        }
}
void key_with(void)//按键处理
{
   if(0==key_sec)
  {
    return;
        }
  switch(key_sec)
  {
    case 1:
           hig++;
          count++;;
         if(hig>=510)
            hig=510;
         if(count>=99)
            count=99;
      key_sec=0;
                break;

    case 2:
                     hig+=10;
                        count+=3;
                        if(hig>=510)
                          hig=510;
                        if(count>=99)
                          count=99;
                          key_sec=0;
                         break;
         case 3:
       
          hig--;
          count--;
         if(hig<=250)
            hig=250;
         if(count<=25)
            count=25;
               
                key_sec=0;
                break;
     case 4:
                  
                    hig-=10;
                        count-=3;
                        if(hig<=250)
                          hig=250;
                        if(count<=15)
                          count=15;
                            key_sec=0;
                          break;
                          }
        digplay();
        IapEraseSector(IAP_ADDRESS);
        IapProgramByte(IAP_ADDRESS,hig);
               IapProgramByte(0x0002,count)
                }
void IapIdle()//关闭IAP
{
IAP_CONTR = 0;//关闭IAP功能
IAP_CMD = 0;//清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80;//将地址设置到非IAP区域
IAP_ADDRL = 0;
}
uchar IapReadByte(uint addr)//从ISP/IAP/EEPROM区域读取一字节
{
uchar dat;//数据缓冲区
IAP_CONTR = ENABLE_IAP;
IAP_CMD = CMD_READ;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
dat = IAP_DATA;//读ISP/IAP/EEPROM数据
IapIdle(); //关闭IAP功能
return dat;//返回
}

void IapProgramByte(uint addr, uchar dat)//写一字节数据到ISP/IAP/EEPROM区域
{
IAP_CONTR = ENABLE_IAP;//使能IAP
IAP_CMD = CMD_PROGRAM; //设置IAP命令
IAP_ADDRL = addr;//设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat;//写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
IapIdle();
}
void IapEraseSector(uint addr)//扇区擦除
{

IAP_CONTR = ENABLE_IAP;//使能IAP
IAP_CMD = CMD_ERASE;//设置IAP命令
IAP_ADDRL = addr;//设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
IapIdle();
}
void main()//主程序
{
  delayxms(100);
count= IapEraseSector(IAP_ADDRESS);//读出输出数据
hig= IapProgramByte(0x0002);//读出显示
PWM=count;//输出
digplay(hig);
  Init2();
P5M0=0xff;
    P5M1=0x00;
    P3M0=0xff;
    P3M1=0x00;
    P1M0=0xff;
    P1M1=0xf0;
while(1)
    {
    key_with();
}
}
void Init2()//定时器2初始化
{
AUXR&=0x04;        //12T
     T2L=0x78;        //定时5MS
     T2H=0xec;        //
     
     IE2|=0x04;
     AUXR|=0x10;        //开始计时
   EA=1;
     }
void t2int() interrupt 12
{
  digplay(); //T2中断服务函数之中调用显示
    KeyScan();
}     

使用特权

评论回复
27
LKC134|  楼主 | 2019-5-20 09:50 | 只看该作者
延时函数改成这样:
void delayxms(uint z)
{
  uint y,x;
for(y=0;y<z;y++)
for(x=0;x<120;x++);
}

使用特权

评论回复
28
xch| | 2019-5-20 10:57 | 只看该作者
LKC134 发表于 2019-5-20 09:46
多谢这位大神热心回复,我现在改成这样,请看下面,另外EERPOM这样放在按键任务后面不知合不合理?
void  ...

可以。一点小毛病更改

void key_with(void)//按键处理
{
   if(0==key_sec)
  {
    return;
        }
               
                EA=0;        //在下方修改全局变量hig必须关闭定时器中断
  switch(key_sec)
  {
    case 1:
           hig++;
          count++;;
         if(hig>=510)
            hig=510;
         if(count>=99)
            count=99;
      key_sec=0;
                break;

    case 2:
                     hig+=10;
                        count+=3;
                        if(hig>=510)
                          hig=510;
                        if(count>=99)
                          count=99;
                          key_sec=0;
                         break;
         case 3:
        
          hig--;
          count--;
         if(hig<=250)
            hig=250;
         if(count<=25)
            count=25;
               
                key_sec=0;
                break;
     case 4:
                  
                    hig-=10;
                        count-=3;
                        if(hig<=250)
                          hig=250;
                        if(count<=15)
                          count=15;
                            key_sec=0;
                          break;
                          }
//        digplay();                         //不该在此使用

                EA =1;
        IapEraseSector(IAP_ADDRESS);
        IapProgramByte(IAP_ADDRESS,hig);
               IapProgramByte(0x0002,count)
                }

使用特权

评论回复
29
LKC134|  楼主 | 2019-5-20 11:43 | 只看该作者
xch 发表于 2019-5-20 10:57
可以。一点小毛病更改

void key_with(void)//按键处理

多谢!我测试下先。

使用特权

评论回复
30
叶春勇| | 2019-5-20 13:25 | 只看该作者
代码吓人呀。有些功能可以写成函数的。

使用特权

评论回复
31
叶春勇| | 2019-5-20 13:27 | 只看该作者
编写个软件上升沿判断,下降沿判断。

使用特权

评论回复
32
LKC134|  楼主 | 2019-5-20 15:32 | 只看该作者
叶春勇 发表于 2019-5-20 13:25
代码吓人呀。有些功能可以写成函数的。

没办法呀菜鸟一个,只能边学边优化。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则