LCD печатает символ дважды?

See The Image
У меня проблема с моим проектом 8051. Я хочу вводить числа и работать с клавиатурой и распечатывать их на ЖК-дисплее 16x2, а результат - с помощью микроконтроллера 8051. Все работает отлично, я могу делать основные операции и видеть результаты. Но когда я нажимаю символы с клавиатуры, ЖК-дисплей печатает символ дважды. Я не мог видеть, где проблема. Буду очень рад, если вы мне поможете. Спасибо.

#include <reg51.h>

void lcdcmd(unsigned char);
void lcddata(unsigned char);
void MSDelay(unsigned int);
void disp_num(float num);
int get_num(char ch);
void lcdinit();
char scan_key(void);

sfr ldata = 0xA0;
sbit rs = P3^7;
sbit rw = P3^5;
sbit en = P3^6;
sbit r0=P1^0;
sbit r1=P1^1;
sbit r2=P1^2;
sbit r3=P1^3;
sbit c0=P1^4;
sbit c1=P1^5;
sbit c2=P1^6;
sbit c3=P1^7;

void lcdinit(){
    MSDelay(15000);
    lcdcmd(0x30);
    MSDelay(4500);
    lcdcmd(0x30);
    MSDelay(300);
    lcdcmd(0x30);
    MSDelay(600);
    lcdcmd(0x38);
    lcdcmd(0x0F);
    lcdcmd(0x01);
    lcdcmd(0x06);
    lcdcmd(0x80);
}

int main (void)
{
    while(1){
        unsigned int k=0, m=0, n=0;
        int k2, k1;
        char key, key1;
        unsigned char ch2,ch3;

        lcdinit();

        key = scan_key();
        k2 = get_num(key); // sayiya cevirdik. 
        lcddata(key); // lcd de goruntule. 

        ch2 = scan_key();
        lcddata(ch2);

        key1 = scan_key();
        k1 = get_num(key1);
        lcddata(key1);

        ch3 = scan_key();
        lcddata(ch3);
        lcdcmd(0x01);

        switch(ch2)
        {
        case 'A':
            disp_num(k1 + k2);
            break;

        case 'B':
            disp_num(k2 - k1);
            break;

        case 'C':
            disp_num(k2 * k1);
            break;

        case 'D':
            disp_num(k2 / k1);
            break;
        }
        return 0;
    }
}

void lcdcmd(unsigned char value)
{
    ldata = value;      
    rs = 0;
    rw = 0;
    en = 1;            
    MSDelay(50);
    en = 0;
    MSDelay(50);
}

void lcddata(unsigned char value)
{
    ldata = value;  
    rs = 1;
    rw = 0;
    en = 1;          
    MSDelay(50);
    en = 0;
    MSDelay(50);
}

void MSDelay(unsigned int itime)
{
    unsigned int i, j;

    for(i = 0;i < itime; i++)           
        for(j = 0; j < 5; j++);       
}

char scan_key()
{
    unsigned char c;
    c='s';
    while(!(c=='0' && c=='1' && c=='2' && c=='3' && c=='4'
                   && c=='5' && c=='6' && c=='7' && c=='8'
                   && c=='9' && c=='+' && c=='-' && c=='#'
                   && c=='$' && c=='*' && c=='/' ))
    {
      r0 = 0; r1 = 1; r2 = 1; r3 = 1;

      if(c0==0 && r0==0){ lcddata('7'); MSDelay(100000); return c = '7';}
      if(c1==0 && r0==0){ lcddata('8'); MSDelay(100000); return c = '8';}
      if(c2==0 && r0==0){ lcddata('9'); MSDelay(100000); return c = '9';}
      if(c3==0 && r0==0){ lcddata('A'); MSDelay(100000); return c = 'A';}

      r0 = 1; r1 = 0; r2 = 1; r3 = 1;

      if(c0==0 && r1==0){ lcddata('4'); MSDelay(100000); return c= '4';}
      if(c1==0 && r1==0){ lcddata('5'); MSDelay(100000); return c= '5';}
      if(c2==0 && r1==0){ lcddata('6'); MSDelay(100000); return c= '6';}
      if(c3==0 && r1==0){ lcddata('B'); MSDelay(100000); return c= 'B';}

      r0 = 1; r1 = 1; r2 = 0; r3 = 1;

      if(c0==0 && r2==0){ lcddata('1');MSDelay(100000); return c= '1';}
      if(c1==0 && r2==0){ lcddata('2');MSDelay(100000); return c= '2';}
      if(c2==0 && r2==0){ lcddata('3');MSDelay(100000); return c= '3';}
      if(c3==0 && r2==0){ lcddata('C');MSDelay(100000); return c= 'C';}

      r0 = 1; r1 = 1; r2 = 1; r3 = 0;

      if(c0==0 && r3==0){ lcddata('*');MSDelay(100000);return c= '*';}
      if(c1==0 && r3==0){ lcddata('0');MSDelay(100000);return c= '0';}
      if(c2==0 && r3==0){ lcddata('#');MSDelay(100000);return c= '#';}
      if(c3==0 && r3==0){ lcddata('D');MSDelay(100000);return c= 'D';}
    }
    return 0;
}

int get_num(char ch)         //convert char into int
{
    switch(ch)
    {
    case '0': return 0; break;
    case '1': return 1; break;
    case '2': return 2; break;
    case '3': return 3; break;
    case '4': return 4; break;
    case '5': return 5; break;
    case '6': return 6; break;
    case '7': return 7; break;
    case '8': return 8; break;
    case '9': return 9; break;
    }
    return 0;
}

void disp_num(float num)            //displays number on LCD
{
    unsigned char UnitDigit  = 0;  //It will contain unit digit of numb
    unsigned char TenthDigit = 0;  //It will contain 10th position digit of numb
    unsigned char decimal = 0;
    int j;
    int numb;
    j=(int)(num*10);
    numb=(int)num;

    TenthDigit = (numb/10);          // Findout Tenth Digit

    if( TenthDigit != 0)             // If it is zero, then don't display
      lcddata(TenthDigit+0x30);  // Make Char of TenthDigit and then display it on LCD

    UnitDigit = numb - TenthDigit*10;

    lcddata(UnitDigit+0x30);     // Make Char of UnitDigit and then display it on LCD
    MSDelay(2000000);
}

person Berke Kocadere    schedule 02.06.2020    source источник
comment
Вы пытались упростить проблему или выполняли какие-либо отладки, чтобы сузить ее?   -  person lurker    schedule 02.06.2020
comment
В scan_key ваше условие цикла while не имеет смысла. Вы не можете быть равны нескольким значениям одновременно. Также какой смысл присваивать значение локальной переменной c прямо перед возвратом из этой функции?   -  person Gerhardh    schedule 02.06.2020
comment
c=='0' && c=='1' && ...всегда ложно. Вы имели в виду или эти?   -  person Jens    schedule 02.06.2020
comment
В scan_key условие цикла для этого, если клавиша не нажата, оно всегда будет в этом цикле. Как только клавиша нажата, присваивается локальная переменная c, она является одним из условий и выходит из цикла. Нельзя ли это сделать?   -  person Berke Kocadere    schedule 02.06.2020
comment
Нет ни одного из этих условий. Это одно условие в целом. И если первая часть истинна, то все остальные части ложны. В сумме это всегда будет ложно.   -  person Gerhardh    schedule 02.06.2020
comment
Если вы дойдете до любого места, где вы выполняете return c='*'; или подобное, проверка условия цикла больше не выполняется. Вы немедленно возвращаетесь из этой функции. Это то, что делает return. Никакие другие инструкции в этой функции не выполняются после оператора return.   -  person Gerhardh    schedule 02.06.2020
comment
В scan_key() у вас есть не только странное условие while, упомянутое в комментариях ранее, но и вызовы lcddata(). Я думаю, что они остались от отладки и производят ваш двойной вывод.   -  person user5329483    schedule 03.06.2020


Ответы (1)


Я решил проблему, удалив отсюда функции lcddata():

key = scan_key();
    k2 = get_num(key); // sayiya cevirdik. 
    lcddata(key); // lcd de goruntule. 

    ch2 = scan_key();
    lcddata(ch2);

    key1 = scan_key();
    k1 = get_num(key1);
    lcddata(key1);

    ch3 = scan_key();
    lcddata(ch3);
    lcdcmd(0x01);

Я не понял, что вы пытались сказать о while() в функции scan_key(), она отлично работает в симуляции. Но теперь я хочу создать 20-секундную задержку для результата в этой операции, я пробовал это с функцией MSDelay(), но ничего не изменилось.

Редактировать: извините, ребята, теперь я понял ошибку в while(). Это была огромная ошибка, я ее исправлю и всем спасибо.

person Berke Kocadere    schedule 03.06.2020