找回密码
 立即注册

QQ登录

只需一步,快速开始

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

求大神帮忙看一下单片机程序,为什么按下keyK后不开始倒数

[复制链接]
跳转到指定楼层
楼主
ID:816162 发表于 2020-9-20 23:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
150黑币
#include <reg51.h>
#include <math.h>
#include <intrins.h>
#define uchar unsigned char                                      
#define uint unsigned int                              
#define ulong unsigned long
#define CH451_NOP              0x0000                                   // 空操作
#define CH451_RESET     0x0201                                   // 复位
#define CH451_LEVEL              0x0100                                   // 加载光柱值,需另加7位数据
#define CH451_CLR_BIT       0x0180                                   // 段位清0,需另加6位数据
#define CH451_SET_BIT       0x01C0                                   // 段位置1,需另加6位数据
#define CH451_SLEEP              0x0202                                   // 进入睡眠状态
#define CH451_LEFTMOV   0x0300                          // 设置移动方式-左移
#define CH451_LEFTCYC   0x0301                          // 设置移动方式-左循环
#define CH451_RIGHTMOV  0x0302                          // 设置移动方式-右移
#define CH451_RIGHTCYC  0x0303                          // 设置移动方式-右循环      
#define CH451_SELF_BCD       0x0380                                   // 自定义BCD码,需另加7位数据
#define CH451_SYSOFF    0x0400                                   // 关闭显示、关闭键盘
#define CH451_SYSON1    0x0401                                   // 开启显示
#define CH451_SYSON2    0x0403                                   // 开启显示、键盘
#define CH451_SYSON2W   0x0423                                   // 开启显示、键盘, 真正2线接口
#define CH451_NO_BCD    0x0500                                   // 设置默认显示方式,可另加3位扫描极限
#define CH451_BCD       0x0580                                   // 设置BCD译码方式,可另加3位扫描极限
#define CH451_TWINKLE   0x0600                          // 设置闪烁控制,需另加8位数据
#define CH451_GET_KEY       0x0700                                   // 获取按键,返回按键代码
#define CH451_DIG0      0x0800                                   // 数码管位0显示,需另加8位数据
#define CH451_DIG1      0x0900                          // 数码管位1显示,需另加8位数据
#define CH451_DIG2      0x0a00                          // 数码管位2显示,需另加8位数据
#define CH451_DIG3      0x0b00                          // 数码管位3显示,需另加8位数据
#define CH451_DIG4      0x0c00                          // 数码管位4显示,需另加8位数据
#define CH451_DIG5      0x0d00                                   // 数码管位5显示,需另加8位数据
#define CH451_DIG6      0x0e00                                   // 数码管位6显示,需另加8位数据
#define CH451_DIG7      0x0f00                          // 数码管位7显示,需另加8位数据1
sbit   CH451_DCLK = P2^4;                      // 串行数据时钟上升沿激活
sbit   CH451_DIN = P2^5;                        // 串行数据输出,接CH451的数据输入
sbit   CH451_LOAD = P2^6;                     // 串行命令加载,上升沿激活
sbit   CH451_DOUT = P2^7;                     // INT1,键盘中断和键值数据输入,接CH451的数据输出
sfr P5          =   0xC8;   //xxxx,1111 端口5
sfr P4          =   0xC0;   //1111,1111 端口4
sbit sp=P4^5;  //蜂鸣器
uint Data=9999;      // 显示初值,Data的值决定开机显示数值
uchar count = 0;
uint  z = 0;
uint temp = 0;
uchar  ch451_key=0;                 // 存放键盘中断中读取的键值
uchar  key=0x00;
code uchar table[]={0xBD,0x18,0xD5,                 //0,1,2,
                       0xD9,0x78,0xE9,                //3,4,5,
                       0xED,0x98,0xFD,0xF9};  //6,7,8,9
void speaker(void)//蜂鸣器响起
{
uint i,j;
for(j=0;j<250;j++)
{
  for(i=0;i<2000;i++)
  {
    sp=0;
  }
  for(i=0;i<3000;i++)
  {
    sp=1;
  }
}
  
   sp=1;
}
void delayms(uint xms)  //延时子程序
{
   uint i,j;
   for(i=xms;i>0;i--)
   for(j=110;j>0;j--);        //延时
}
/*****************写命令时序************************************/
void CH451_write(uint command) //定义一无符号整型变量存储12字节的命令字
{
  uchar i;     
  CH451_LOAD=0;   
    for(i=0;i<12;i++)
         {                             
            CH451_DIN = command&1;                                
            CH451_DCLK =0;
            command>>=1;
            CH451_DCLK=1;                             
            delayms(10);
         }
    CH451_LOAD=1;
}
/*****************初始化子程序************************************/
void CH451_init()     
{
    CH451_write(CH451_RESET);    //CH451复位
    CH451_write(CH451_SYSON2 );//开启显示、键盘
    CH451_write(CH451_NO_BCD);// 设置默认显示方式
    CH451_write(CH451_TWINKLE);            //设置闪烁控制--正常显示
}
/*****************显示数码管************************************/
void display()        
{
temp = Data / 1000;
CH451_write(CH451_DIG4 | table[temp]);
temp = (Data / 100)%10;
CH451_write(CH451_DIG5 | table[temp]);
temp = (Data / 10)%10;
CH451_write(CH451_DIG6 | table[temp]);
temp = Data % 10;
CH451_write(CH451_DIG7 | table[temp]);
}
/********************读取按键中断子程序*****************************/

void gerkey()            
{   
  uchar i;                                                                   //定义循环变量
  uchar command,keycode;                                         //定义控制字寄存器,和中间变量定时器
  command=0x07;                                                    //读取键值命令的高4位0111B
  CH451_LOAD=0;                                                    //命令开始
  for(i=0;i<4;i++)
   {
    CH451_DIN=command&1;                                        //低位在前,高位在后
    CH451_DCLK=0;
    command>>=1;                                                          //右移一位
    CH451_DCLK=1;                                                   //产生时钟上升沿锁通知CH451输入位数据
   }
    CH451_LOAD=1;                                                   //产生加载上升沿通知CH451处理命令数据
    keycode=0;                                                           //清除keycode
    for(i=0;i<7;i++)
     {
    keycode<<=1;                                                   //数据作移一位,高位在前,低位在后
    keycode|=CH451_DOUT;                                          //从高到低读入451的数据
    CH451_DCLK=0;                                                   //产生时钟下升沿通知CH451输出下一位
    CH451_DCLK=1;
     }
  ch451_key=keycode;                                                 //保存上次的键值
}
/********************按键扫描子程序*****************************/
void keyscan()  //键盘扫描子程序
{   
   while(1)
     {
       gerkey();
       switch(ch451_key)//按键判断
            {
                 case 0x47://keyG
                  {
                       Data++; //Data+1
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                       display();
                      while(ch451_key==0x47) gerkey();
                   }break;      
                case  0x46://keyS
                  {
                       Data=Data+10; //Data+10
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                        display();
                       while(ch451_key==0x46) gerkey();
                   }break;   
               case  0x45://keyB
                  {
                       Data=Data+100; //Data+100
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                        display();
                       while(ch451_key==0x45)gerkey();
                   }break;   
             case 0x44://keyQ
                  {
                       Data=Data+1000; //Data+1000
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                       display();
                       while(ch451_key==0x44)gerkey();
                   } break;  
             case 0x4c://keyF
                  {
                     Data=0;   //复位,显示0000
                     display();
                     while(ch451_key==0x4c)gerkey();
                  }break;
              case 0x4d://keyU
                {
                z=1;
                while(ch451_key==0x4e)gerkey();
                } break;
              case  0x4e://keyK
                  while(ch451_key==0x4e)gerkey();
            break;
         }
    }
}
void start_timer0()                     //开中断子程序
{
    TMOD=0x01;                         //定时器0工作方式1     
    EA = 1;  //开启中断总开关
    TR0 = 1;//开启T0
    ET0 = 1;//打开T0中断开关
}
void stop_timer0()                     //关中断子程序
{
    TR0 = 0;
    ET0 = 0;
    TF0 = 0;//定时器/计数器0的溢出中断标志位,当T0从初值开始加一计数到产生溢出时,由硬件使TF0置1,直到CPU响应中断由硬件复位
}

void timer0() interrupt 1    //倒计时中断程序timer0,不用调用stop_timer0函数,TF0会自动置0,interrupt 后面的数字表示使用的寄存器组
{
      TH0=(65536-9216)/256;  //50ms产生一次中断   
      TL0=(65536-9216)%256;   
      while (Data!=0)
            {
    if(z==1)//单位为分
      {
          display();
                         count++;
                         if(count==1200)
                            {
                                count=0;
                 Data--;
              }
       }
    else//默认单位为秒
        {
            display();
                           count++;
                           if(count==20)
                               {
     count=0;
     Data--;   
                 }
        }
            }
}

void main()
{     
      CH451_init();                         //数码管中断初始化
       display();
      while(1)
          {
              gerkey();
              keyscan();        //键盘输入初值
              stop_timer0();
              start_timer0();
              TR0=0;
              if(Data == 0)
                  {
      speaker();  
                    }
          }
}

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

使用道具 举报

沙发
ID:213173 发表于 2020-9-21 06:18 | 只看该作者
由于按键函数里用了死循环while(1)就再也出不来了。
回复

使用道具 举报

板凳
ID:342822 发表于 2020-9-21 07:27 | 只看该作者
把大量的中文“;”替换为英文";"
以下已替换:
/* Main.c file generated by New Project wizard
*
* Created:   周日 9月 20 2020
* Processor: AT89C52
* Compiler:  Keil for 8051
*/

#include <reg51.h>
#include <math.h>
#include <intrins.h>
#define uchar unsigned char                                      
#define uint unsigned int                              
#define ulong unsigned long
#define CH451_NOP              0x0000                                   // 空操作
#define CH451_RESET     0x0201                                   // 复位
#define CH451_LEVEL              0x0100                                   // 加载光柱值,需另加7位数据
#define CH451_CLR_BIT       0x0180                                   // 段位清0,需另加6位数据
#define CH451_SET_BIT       0x01C0                                   // 段位置1,需另加6位数据
#define CH451_SLEEP              0x0202                                   // 进入睡眠状态
#define CH451_LEFTMOV   0x0300                          // 设置移动方式-左移
#define CH451_LEFTCYC   0x0301                          // 设置移动方式-左循环
#define CH451_RIGHTMOV  0x0302                          // 设置移动方式-右移
#define CH451_RIGHTCYC  0x0303                          // 设置移动方式-右循环      
#define CH451_SELF_BCD       0x0380                                   // 自定义BCD码,需另加7位数据
#define CH451_SYSOFF    0x0400                                   // 关闭显示、关闭键盘
#define CH451_SYSON1    0x0401                                   // 开启显示
#define CH451_SYSON2    0x0403                                   // 开启显示、键盘
#define CH451_SYSON2W   0x0423                                   // 开启显示、键盘, 真正2线接口
#define CH451_NO_BCD    0x0500                                   // 设置默认显示方式,可另加3位扫描极限
#define CH451_BCD       0x0580                                   // 设置BCD译码方式,可另加3位扫描极限
#define CH451_TWINKLE   0x0600                          // 设置闪烁控制,需另加8位数据
#define CH451_GET_KEY       0x0700                                   // 获取按键,返回按键代码
#define CH451_DIG0      0x0800                                   // 数码管位0显示,需另加8位数据
#define CH451_DIG1      0x0900                          // 数码管位1显示,需另加8位数据
#define CH451_DIG2      0x0a00                          // 数码管位2显示,需另加8位数据
#define CH451_DIG3      0x0b00                          // 数码管位3显示,需另加8位数据
#define CH451_DIG4      0x0c00                          // 数码管位4显示,需另加8位数据
#define CH451_DIG5      0x0d00                                   // 数码管位5显示,需另加8位数据
#define CH451_DIG6      0x0e00                                   // 数码管位6显示,需另加8位数据
#define CH451_DIG7      0x0f00                          // 数码管位7显示,需另加8位数据1
sbit   CH451_DCLK = P2^4;                      // 串行数据时钟上升沿激活
sbit   CH451_DIN = P2^5;                        // 串行数据输出,接CH451的数据输入
sbit   CH451_LOAD = P2^6;                     // 串行命令加载,上升沿激活
sbit   CH451_DOUT = P2^7;                     // INT1,键盘中断和键值数据输入,接CH451的数据输出
sfr P5          =   0xC8;   //xxxx,1111 端口5
sfr P4          =   0xC0;   //1111,1111 端口4
sbit sp=P4^5;  //蜂鸣器
uint Data=9999;      // 显示初值,Data的值决定开机显示数值
uchar count = 0;
uint  z = 0;
uint temp = 0;
uchar  ch451_key=0;                 // 存放键盘中断中读取的键值
uchar  key=0x00;
code uchar table[]={0xBD,0x18,0xD5,                 //0,1,2,
                       0xD9,0x78,0xE9,                //3,4,5,
                       0xED,0x98,0xFD,0xF9};  //6,7,8,9
void speaker(void)//蜂鸣器响起
{
uint i,j;
for(j=0;j<250;j++)
{
  for(i=0;i<2000;i++)
  {
    sp=0;
  }
  for(i=0;i<3000;i++)
  {
    sp=1;
  }
}
  
   sp=1;
}
void delayms(uint xms)  //延时子程序
{
   uint i,j;
   for(i=xms;i>0;i--)
   for(j=110;j>0;j--);        //延时
}
/*****************写命令时序************************************/
void CH451_write(uint command) //定义一无符号整型变量存储12字节的命令字
{
  uchar i;     
  CH451_LOAD=0;   
    for(i=0;i<12;i++)
         {                             
            CH451_DIN = command&1;                                
            CH451_DCLK =0;
            command>>=1;
            CH451_DCLK=1;                             
            delayms(10);
         }
    CH451_LOAD=1;
}
/*****************初始化子程序************************************/
void CH451_init()     
{
    CH451_write(CH451_RESET);    //CH451复位
    CH451_write(CH451_SYSON2 );//开启显示、键盘
    CH451_write(CH451_NO_BCD);// 设置默认显示方式
    CH451_write(CH451_TWINKLE);            //设置闪烁控制--正常显示
}
/*****************显示数码管************************************/
void display()        
{
temp = Data / 1000;
CH451_write(CH451_DIG4 | table[temp]);
temp = (Data / 100)%10;
CH451_write(CH451_DIG5 | table[temp]);
temp = (Data / 10)%10;
CH451_write(CH451_DIG6 | table[temp]);
temp = Data % 10;
CH451_write(CH451_DIG7 | table[temp]);
}
/********************读取按键中断子程序*****************************/

void gerkey()            
{   
  uchar i;                                                                   //定义循环变量
  uchar command,keycode;                                         //定义控制字寄存器,和中间变量定时器
  command=0x07;                                                    //读取键值命令的高4位0111B
  CH451_LOAD=0;                                                    //命令开始
  for(i=0;i<4;i++)
   {
    CH451_DIN=command&1;                                        //低位在前,高位在后
    CH451_DCLK=0;
    command>>=1;                                                          //右移一位
    CH451_DCLK=1;                                                   //产生时钟上升沿锁通知CH451输入位数据
   }
    CH451_LOAD=1;                                                   //产生加载上升沿通知CH451处理命令数据
    keycode=0;                                                           //清除keycode
    for(i=0;i<7;i++)
     {
    keycode<<=1;                                                   //数据作移一位,高位在前,低位在后
    keycode|=CH451_DOUT;                                          //从高到低读入451的数据
    CH451_DCLK=0;                                                   //产生时钟下升沿通知CH451输出下一位
    CH451_DCLK=1;
     }
  ch451_key=keycode;                                                 //保存上次的键值
}
/********************按键扫描子程序*****************************/
void keyscan()  //键盘扫描子程序
{   
   while(1)
     {
       gerkey();
       switch(ch451_key)//按键判断
            {
                 case 0x47://keyG
                  {
                       Data++; //Data+1
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                       display();
                      while(ch451_key==0x47) gerkey();
                   }break;      
                case  0x46://keyS
                  {
                       Data=Data+10; //Data+10
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                        display();
                       while(ch451_key==0x46) gerkey();
                   }break;   
               case  0x45://keyB
                  {
                       Data=Data+100; //Data+100
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                        display();

                       while(ch451_key==0x45)gerkey();
                   }break;   
             case 0x44://keyQ
                  {
                       Data=Data+1000; //Data+1000
                       if(Data>=10000)   //限制Data的取值范围
                            {   
                                Data=9999;  //最大显示9999
                            }
                       display();
                       while(ch451_key==0x44)gerkey();
                   } break;  
             case 0x4c://keyF
                  {
                     Data=0;   //复位,显示0000
                     display();
                     while(ch451_key==0x4c)gerkey();
                  }break;
              case 0x4d://keyU
                {
                z=1;
                while(ch451_key==0x4e)gerkey();
                } break;
              case  0x4e://keyK
                  while(ch451_key==0x4e)gerkey();
            break;
         }
    }
}
void start_timer0()                     //开中断子程序
{
    TMOD=0x01;                         //定时器0工作方式1     
    EA = 1;  //开启中断总开关
    TR0 = 1;//开启T0
    ET0 = 1;//打开T0中断开关
}
void stop_timer0()                     //关中断子程序
{
    TR0 = 0;
    ET0 = 0;
    TF0 = 0;//定时器/计数器0的溢出中断标志位,当T0从初值开始加一计数到产生溢出时,由硬件使TF0置1,直到CPU响应中断由硬件复位
}

void timer0() interrupt 1    //倒计时中断程序timer0,不用调用stop_timer0函数,TF0会自动置0,interrupt 后面的数字表示使用的寄存器组
{
      TH0=(65536-9216)/256;  //50ms产生一次中断   
      TL0=(65536-9216)%256;   
      while (Data!=0)
            {
    if(z==1)//单位为分
      {
          display();
                         count++;
                         if(count==1200)
                            {
                                count=0;
                 Data--;
              }
       }
    else//默认单位为秒
        {
            display();
                           count++;
                           if(count==20)
                               {
     count=0;
     Data--;   
                 }
        }
            }
}

void main()
{     
      CH451_init();                         //数码管中断初始化
       display();
      while(1)
          {
              gerkey();
              keyscan();        //键盘输入初值
              stop_timer0();
              start_timer0();
              TR0=0;
              if(Data == 0)
                  {
      speaker();  
                    }
          }
}
回复

使用道具 举报

地板
ID:584814 发表于 2020-9-21 17:11 | 只看该作者
那么多的中文符号居然能通过编译
回复

使用道具 举报

5#
ID:816162 发表于 2020-9-21 21:44 | 只看该作者
taotie 发表于 2020-9-21 07:27
把大量的中文“;”替换为英文";"
以下已替换:
/* Main.c file generated by New Project w ...

那无法倒数的部分怎么解决啊
回复

使用道具 举报

6#
ID:816162 发表于 2020-9-21 21:45 | 只看该作者
wulin 发表于 2020-9-21 06:18
由于按键函数里用了死循环while(1)就再也出不来了。

那应该是怎么解决啊
回复

使用道具 举报

7#
ID:213173 发表于 2020-9-22 07:05 | 只看该作者
jyhbdhs 发表于 2020-9-21 21:45
那应该是怎么解决啊

楼主的程序硬伤太多,三言两语无法说清,网上示例很多,可自行搜索参考。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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