找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1298|回复: 5
收起左侧

单片机按键异常的不灵敏,求各位大佬指教程序

[复制链接]
ID:950769 发表于 2022-8-30 22:49 | 显示全部楼层 |阅读模式
单片机主程序:
#include "reg52.h"   
#include <intrins.h>   
#include<OLED.h>
#include "key.h"
#include"delay.h"
#include"show_num.h"
#include"light.h"

#define uchar unsigned char
#define uint unsigned int

uint key_scan();
void light_time();
void Math_Distance(uint distance);

sbit echo = P2^7;           
sbit trig = P2^3;                                                                              
sbit beep = P2^4;


bit flag = 0;                   //测量成功标志位全局参定义
uint time_H,time_L;           //暂存值,只用来存储定时器的高低八位返回数值
uint time;                           //时间
uint max=2,min=1;                //单位为米

uint cm_table1[2]={0,0};
uint cm_table2[2]={0,0};          //储存距离参数的数组
uint maxnum[2]={0,0};
uint minnum[2]={0,0};

void main()
{
        uint distance = 0;        //参数:距离
        uint save = 0;                //参数:(上一次的)距离保存。用于修正错误值
        uint i = 5;

        beep=0;                                //蜂鸣器上电后不响
        delay(1000);  
        OLED_Init();             // OLED初始化
        OLED_Fill(0x00);   
        trig = 0;                   //先关触发信号               //指示灯

        while(1)
        {
     TMOD = 0x10;           //开定时器1-> 0001_0000  16位工作方式
         TH1 = 0;                   //定时器高八位初填装值清空
         TL1 = 0;                    //定时器低八位初填装值清空
         
         TF1=0;                           //T1溢出中断标志位。可自动由硬件至高/清零
         ET1 = 0;                   //T1中断使能
         EA = 1;                   //开总中断

         flag = 0;                   //标志位清0
         trig = 1;                   //给触发信号
         delay_20us();           //等那么一小段时间
         trig = 0;                   //关触发信号  ————这样就给了一小段高电平触发信号,以至于不会一直触发

         while(!echo);           //等待接收端出现高电平(如果是低,那就一直等)
         TR1 = 1;                   //T1运行控制位,开始计时
         while(echo);           //等待高电平结束(如果是高,那就一直等)
         TR1 = 0;                   //关定时器T1
         
         time_H = TH1;           //把T1的高低八位定时数据取出
         time_L = TL1;           //        ↑
         
          if(flag == 0)                //如果测距成功
        {
          time=time_H*256+time_L;        //将定时器的高低八位返回值赋给时间参数time
          distance = time*0.173;        //来回1/2*时间time*声速346(m/s)*0.001(单位换算:mm)
          save = distance;                        //暂存正确的距离值
          if(distance > max*1000)
          {                  
                beep = 1;
          }
          if(distance <= max*1000 && distance >= min*1000)
          {
                  beep = 0;
                light_time();
          }
          if(distance < min*1000)
          {
                beep = 1;
                delay(50000);
                beep=0;
          }                                
      Math_Distance(distance);        
        }

          else if(flag == 1)        
        {
          distance =  save;                                
        }
        switch(key_scan())
        {
                case 0:
                        break;
                case 1:
                        if(max == 10)
                        {
                                max = 10;
                        }
                        else
                        {
                                max++;
                        }
                        break;
                case 2:
                        if(max == 0)
                        {
                                max = 0;
                        }
                        else
                        {
                                max--;
                        }
                        break;        
                case 3:
                        if(min == 10)
                        {
                                min = 10;
                        }
                        else
                        {
                                min++;
                        }
                        break;
                case 4:
                        if(min == 0)
                        {
                                min = 0;
                        }
                        else
                        {
                                min--;
                        }
                        break;               
                default:
                        break;
        }
         
         OLED_P6x8Str(0,1,"maximums:");
         Show_Number(8,2,maxnum,2);
         OLED_P8x16Str(26,2,"m");
         OLED_P6x8Str(74,1,"minimums:");
         Show_Number(82,2,minnum,2);
         OLED_P8x16Str(100,2,"m");
     OLED_P8x16Str(28,4,"distance:");  
         OLED_P8x16Str(78,6,"dm");                  
         Show_Number(32,6,cm_table1,2);
         OLED_P6x8Str(50,7,".");
         Show_Number(58,6,cm_table2,2);   
         delay(5000);                          

        }
}

/*******************************************************************************
* 函 数 名       : Math_Distance
*******************************************************************************/
void Math_Distance(uint distance)           //距离值数学转换
{
  cm_table1[0]=distance/1000;           
  cm_table1[1]=distance/100;                 
  cm_table2[0]=distance%100/10;           
  cm_table2[1]=distance%100%10;           
  maxnum[0]=max/10;
  maxnum[1]=max%10;
  minnum[0]=min/10;
  minnum[1]=min%10;        
}

按键检测:
#include"key.h"

#define uchar unsigned char
#define uint unsigned int

sbit A4 = P2^0;
sbit A5 = P3^3;
sbit A6 = P2^1;
sbit A7 = P2^2;

/**********************************
* 函数名:  键值函数
**************************************/
uint key_scan()
{
        uint keynum = 0;
        if(A4 == 0)
        {
                keynum = 1;
        }
        if(A5 == 0)
        {
                keynum = 2;
        }
        if(A6 == 0)
        {
                keynum = 3;
        }
        if(A7 == 0)
        {
                keynum = 4;
        }

        return keynum;

}
回复

使用道具 举报

ID:123289 发表于 2022-8-31 08:28 | 显示全部楼层
灵敏:是指在短时间内能响应你的事件。
这里理解为,你按下了键,CPU在短时间就发现了,且响应了一下。
为何不灵敏了呢?因为在这段时间时,CPU【干私活】不理采你的按键了。
查一查,有没有CPU耗时长的程序部分。要想键灵敏,必须保CPU在短时间内能扫键一下。
回复

使用道具 举报

ID:161164 发表于 2022-8-31 09:00 | 显示全部楼层
不要用delay
OLED显示常量只须在初始化时更新一次,如OLED_P6x8Str(0,1,"maximums:");
OLED显示变量可以定时更新或变量有变化时更新
回复

使用道具 举报

ID:59202 发表于 2022-9-1 00:09 | 显示全部楼层
如果main函数里干的事情太多,就会影响到一些要求实时响应的工作,最好就把按键检测放到定时中断函数里去,可以设定个10ms中断检测一次按键情况,就不会有按键不灵敏的感觉了
回复

使用道具 举报

ID:879348 发表于 2022-9-1 08:07 | 显示全部楼层
使用非阻塞编程,或者直接上系统多个while
回复

使用道具 举报

ID:1043674 发表于 2022-9-2 23:36 来自手机 | 显示全部楼层
扫描按键是否按下可以用定时器来扫描,这样可以避免在执行其他耗时操作时,无法扫描按键
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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