找回密码
 立即注册

QQ登录

只需一步,快速开始

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

我的这个单片机程序为什么按键按下后没有作用?

[复制链接]
跳转到指定楼层
楼主
ID:521078 发表于 2019-10-19 20:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
25黑币
Keil4编写环境:A/D数模转换和按键应用操作显示到Lcd1602上,子程序Lcd1602.c,keyboard.c,I2C.c程序略,跪求主程序
程序要求实现:按上键查询设定的电压值上下限
                      按下键查询当前的电压值(当前电压值是滑动变阻器所配置的电压值)
                      数据采集器件用的是PCF8591测AIN0的值
为什么我的主函数这样写,在51液晶上按上下键没有任何显示,跪求主函数,开发板是金三角开发板
是Lcd如何通过按键进行翻页操作,这个程序应该怎么写,跪求来个大神,写下这个程序

#include <reg52.h>
sbit BUZZ = P1^6;  
bit flag300ms = 1;
bit enBuzz = 0;
unsigned char T0RH = 0;
unsigned char T0RL = 0;
unsigned int CountDown = 0;
void ConfigTimer0(unsigned int ms);
unsigned char GetADCValue(unsigned char chn);
void ValueToString(unsigned char *str, unsigned char val);
extern void I2CStart();
extern void I2CStop();
extern void KeyScan();
extern void KeyDriver();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void main()
{
    EA = 1;
   ConfigTimer0(10);  
   InitLcd1602();
   LcdShowStr (0, 0, "moli");
while(1)
{
     KeyDriver();
}
}
unsigned char GetADCValue (unsigned char chn)
{
      unsigned char val;
     I2CStart();
    if (!I2CWrite (0x48<<1))
    {
        I2CStop();
        return 0;
    }
I2CWrite (0x40 | chn);
I2CStart();
I2CWrite ((0x48<<1) | 0x01);
I2CReadACK();
val = I2CReadNAK();
I2CStop();
return val;
}
void ValueToString(unsigned char *str, unsigned char val)
{
     
  val = (val * 25) / 55;
  str[0] = (val/10) + '0';  
  str[1] = '.';   //С????
  str[2] = (val%10) + '0';  
  str[3] = 'V';  
  str[4] = '\0';
}
void KeyTaAction()
{
    unsigned char val;
    unsigned char str[10];
    InitLcd1602();
    LcdShowStr (0, 0, "TABANXINHAO");  
     while (1)
    {
         if (flag300ms)
     {
         flag300ms = 0;
           
        val = GetADCValue(0);
        ValueToString(str, val);
        LcdShowStr(0, 1, str);
      if (val >= 200)
      {
         enBuzz = 1;
        if (enBuzz)
           BUZZ = ~BUZZ;
      }
      else
          BUZZ = 1;
   }
  }
}
void KeyAction (unsigned char keycode)
{
   if(keycode == 0x26)
    {
      KeyTaAction();
    }
  else if (keycode == 0x28)
   {
     LcdShowStr (0, 0, "MAX");
     LcdShowStr (0, 1, 2^5);   
     LcdShowStr (6, 0, "MIN");
     LcdShowStr (6, 1, 0^0);
   }
}
void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;  
tmp = 11059200 / 12;
tmp = (tmp * ms) / 1000;
tmp = 65536 - tmp;
tmp = tmp + 12;
T0RH = (unsigned char)(tmp >> 8);
T0RL = (unsigned char)tmp;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = T0RH;
TL0 = T0RL;
ET0 = 1;
TR0 = 1;
}
void InterruptTimer0() interrupt 1
{
    static unsigned char tmr300ms = 0;
TH0 = T0RH;
TL0 = T0RL;
tmr300ms++;
if (tmr300ms >= 30)  
{
     tmr300ms = 0;
  flag300ms = 1;
}
}
LCD程序
#include <reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;

void LcdWaitReady()
{
  unsigned char sta;
  LCD1602_DB = 0xFF;
  LCD1602_RS = 0;
  LCD1602_RW = 1;
  do{
      LCD1602_E = 1;
   sta = LCD1602_DB;
   LCD1602_E = 0;
  }while (sta & 0x80);
}

void LcdWriteCmd (unsigned char cmd)
{
   LcdWaitReady();
   LCD1602_RS = 0;
   LCD1602_RW = 0;
   LCD1602_DB = cmd;
   LCD1602_E = 1;
   LCD1602_E = 0;
}
void LcdWriteDat(unsigned char dat)
{
  LcdWaitReady();
  LCD1602_RS = 1;
  LCD1602_RW = 0;
  LCD1602_DB = dat;
  LCD1602_E = 1;
  LCD1602_E = 0;
}

void LcdSetCursor(unsigned char x, unsigned char y)
{
  unsigned char addr;
  if (y == 0)
     addr = 0x00 + x;
  else
     addr = 0x40 + x;
   LcdWriteCmd(addr | 0x80);
}

void LcdShowStr (unsigned char x, unsigned char y,
                 unsigned char *str)
{
  LcdSetCursor(x, y);  
  while (*str != '\0')   
  {
    LcdWriteDat (*str++);
  }
}

void LcdAreaClear(unsigned char x,unsigned char y, unsigned char len)
{

  LcdSetCursor(x, y);
  while (len--)
  {
    LcdWriteDat(' ');
  }
}

void LcdFullClear()
{
  LcdWriteCmd(0x01);
}
void InitLcd1602()
{
  LcdWriteCmd(0x38);
  LcdWriteCmd(0x0C);  
  LcdWriteCmd(0x06);  
  LcdWriteCmd(0x01);  
}
keyboard程序
#include <reg52.h>
sbit KEY_IN_1 = P2^4;
sbit KEY_IN_2 = P2^5;
sbit KEY_IN_3 = P2^6;
sbit KEY_IN_4 = P2^7;
sbit KEY_OUT_1 = P2^3;
sbit KEY_OUT_2 = P2^2;
sbit KEY_OUT_3 = P2^1;
sbit KEY_OUT_4 = P2^0;
unsigned char code KeyCodeMap[4][4] = {
    { '1',  '2',  '3', 0x26 },
    { '4',  '5',  '6', 0x25 },
    { '7',  '8',  '9', 0x28 },
    { '0', 0x1B, 0x0D, 0x27 }   
};
unsigned char pdata KeySta[4][4] = {
  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
};
extern void KeyAction(unsigned char keycode);

void KeyDriver()
{
    unsigned char i, j;
static unsigned char pdata backup[4][4] = {
  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
};
for (i=0; i<4; i++)
{
    for (j=0; j<4; j++)
    {
    if (backup[ i][j] != KeySta[ i][j])
    {
        if (backup[ i][j] != 0)  
     {
        KeyAction(KeyCodeMap[ i][j]);
     }
     backup[ i][j] = KeySta[ i][j];
    }
    }
}
}
void KeyScan()
{
    unsigned char i;
static unsigned char keyout = 0;
static unsigned char keybuf[4][4] = {
    {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
       {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
};
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
for (i=0; i<4; i++)
{
     if ((keybuf[keyout][ i] & 0x0F) == 0x00)
  {
     KeySta[keyout][ i] = 0;
  }
  else if ((keybuf[keyout][ i] & 0x0F) == 0x0F)
  {
     KeySta[keyout][ i] = 1;
  }
}
keyout++;
keyout &= 0x03;
switch(keyout)  
{
     case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
  case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
  case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
  case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
  default: break;
}
}
I2C程序
#include <reg52.h>
#include <intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;/

void I2CStart()
{
    I2C_SDA = 1;
I2C_SCL = 1;
I2CDelay();
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 0;  
}
void I2CStop()
{
    I2C_SCL = 0;
I2C_SDA = 0;
I2CDelay();
I2C_SCL = 1;  
I2CDelay();
I2C_SDA = 1;  
I2CDelay();
}
bit I2CWrite (unsigned char dat)
{
    bit ack;
unsigned char mask;
for (mask=0x80; mask!=0; mask>>=1)
{
    if ((mask&dat) == 0)
       I2C_SDA = 0;
    else
       I2C_SDA = 1;
  I2CDelay();
  I2C_SCL = 1;
  I2CDelay();
  I2C_SCL = 0;
}
I2C_SDA = 1;
I2CDelay();
I2C_SCL = 1;
ack = I2C_SDA;
I2CDelay();
I2C_SCL = 0;  
return (~ack);
            
}
unsigned char I2CReadNAK()
{
    unsigned char mask;
unsigned char dat;
I2C_SDA = 1;
for (mask=0x80; mask!=0; mask>>=1)
{
     I2CDelay();
  I2C_SCL = 1;
  if(I2C_SDA == 0)
      dat &= ~mask;
     else
      dat |= mask;   
  I2CDelay();
  I2C_SCL = 0;     
}
I2C_SDA = 1;   
I2CDelay();
I2C_SCL = 1;   
I2CDelay();
I2C_SCL = 0;   
return dat;
}
unsigned char I2CReadACK()
{
     unsigned char mask;
  unsigned char dat;
  I2C_SDA = 1;
  for (mask=0x80; mask!=0; mask>>=1)  
     {
      I2CDelay();
   I2C_SCL = 1;
   if (I2C_SDA == 0)
       dat &= ~mask;  
   else
       dat |= mask;   
   I2CDelay();
   I2C_SCL = 0;   
   }
   I2C_SDA = 0;
   I2CDelay();
   I2C_SCL = 1;  
   I2CDelay();
   I2C_SCL = 0;
   return dat;
  
}

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

使用道具 举报

沙发
ID:616759 发表于 2019-10-20 13:17 | 只看该作者
你的KeyScan()函数在主程序中都没有出现,这个函数的意思是按键扫描,一般是用来检测按键是否被按下的,同时一般的按键扫描是放在一个大概1s的for循环中的,当然,写在while循环里就不用这个1s的for循环了。
回复

使用道具 举报

板凳
ID:521078 发表于 2019-10-20 14:25 | 只看该作者
bai_yun_123 发表于 2019-10-20 13:17
你的KeyScan()函数在主程序中都没有出现,这个函数的意思是按键扫描,一般是用来检测按键是否被按下的, ...

嗯嗯,谢谢大哥的解答,我也发现了没写按键扫描了,我把按键扫描加上,现在lcd可以进行翻页操作,电压值都可以查询,但按上键我查当前值的时候,每次进去都进入了KeyTaAction()这个函数的while死循环,但再摁下键查询最大最小值就没有任何反应,我想过把while改成do while 还是实现不了这个电压值每300ms要检测,所以,我想问下这个问题怎么解答,谢谢,万分感谢
回复

使用道具 举报

地板
ID:616759 发表于 2019-10-20 17:30 | 只看该作者
不是while和do while的问题,这两个循环只是执行条件的先后问题,我看了keytaaction的函数,while(1)是个死循环,只要进去了,没有break,continue这种跳出循环的语句,那么就出不来,即死循环。把while括号里的条件改成你需要的条件, 比如:
while (flag300ms)
     {
         flag300ms = 0;
           
        val = GetADCValue(0);
        ValueToString(str, val);
        LcdShowStr(0, 1, str);
      if (val >= 200)
      {
         enBuzz = 1;
        if (enBuzz)
           BUZZ = ~BUZZ;
      }
      else
          BUZZ = 1;
  }
当然,条件不一定对,因为后面有个flag300ms置零,所以这个循环只执行一次,至于执行多少次就得看你的条件了,还有,你的程序很多不对齐,也没有注释,看起来很麻烦
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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