Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC18F2580 program not working

Status
Not open for further replies.

Cantafford

Member
Hello,

I'm trying to interface a 4x3 keypad with the PIC18F2580. I wrote this piece of code:
Code:
/*
* File:   main.c
* Author: Paul
*
* Created on October 1, 2015, 2:00 PM
*/

#include <stdio.h>
#include <stdlib.h>
#include "config.c"


#define row1 PORTBbits.RB0;
#define row2 PORTBbits.RB1;
#define row3 PORTBbits.RB2;
#define row4 PORTBbits.RB3;
#define col1 PORTBbits.RB4;
#define col2 PORTBbits.RB5;
#define col3 PORTBbits.RB6;

void InitKeypad(void);
char GetKey(void);
char READ_SWITCHES(void);

void main(void)
{

    char Key = 'n'; // Variable to store the pressed key value
    InitKeypad();
    // REMEMBER YOU HAVE TO DISPLAY THE **** ON THE 7SEGMENT DISPLAY

    while(1)
    {
        Key = GetKey();
        if(Key=='1')
        {
            PORTA = 0b00000001;
        }
        // here put some code to display the key on the lcd
        // :D
    }
}

// Function: InitKeypad: Initialize Keypad pins(also make 7segment display)
void InitKeypad(void)
{
TRISA = 0; // make portA output(the 7led display is here)
TRISB = 0b01110000; // R(0-3) outputs(rows) | R(4-60 inputs(columns)
INTCON2bits.NOT_RBPU = 1; // pull-ups disabled
}

// Function: GetKey: Get pressed key from keypad
char GetKey(void)
{
    char Key = 'n'; // Asume no key was pressed
    while(Key == 'n'); // Wait untill a key is pressed
        Key = READ_SWITCHES(); // Scan the keys again and again
    return Key; // when key's pressed return it's value
}

// Function: READ_SWITCHES
char READ_SWITCHES(void)
{
    row1=0; row2=1; row3=1; row4=1; // Test ROW1
    if(col1==0) {__delay_ms(250); while (col1==0) return '1';}
    if(col2==0) {__delay_ms(250); while (col2==0) return '2';}
    if(col3==0) {__delay_ms(250); while (col3==0) return '3';}

    row1=1; row2=0; row3=1; row4=1; // Test ROW2
    if(col1==0) {__delay_ms(250); while (col1==0) return '4';}
    if(col2==0) {__delay_ms(250); while (col2==0) return '5';}
    if(col3==0) {__delay_ms(250); while (col3==0) return '6';}

    row1=1; row2=1; row3=0; row4=1; // Test ROW3
    if(col1==0) {__delay_ms(250); while (col1==0) return '7';}
    if(col2==0) {__delay_ms(250); while (col2==0) return '8';}
    if(col3==0) {__delay_ms(250); while (col3==0) return '9';}

    row1=1; row2=1; row3=1; row4=0; // Test ROW4
    if(col1==0) {__delay_ms(250); while (col1==0) return '0';}
    if(col2==0) {__delay_ms(250); while (col2==0) return '0';}
    if(col3==0) {__delay_ms(250); while (col3==0) return '0';}

    return 'n'; // Means no key has been pressed
}

When I try to run it these errors occur:
w045ys.png

the errors are "syntax errors" at char READ_SWITCHES(void) function(last one).
Can someone please explain me how to correct that error? Since it's a simple syntax error I suppose it should be easy to correct it but thus far I wasn't able to figure out what that syntax error was(I'm no god of programming). Thank you for reading!
 
Remember to #include <xc.h>
Didn't help. Can you please tell me what's wrong in this code? It says syntax error but I can't figure out what the syntax error is:

Hello, thank you for answering. Adding that didn't help much. It still says some bs about syntax error. Can you please tell me if there is a syntax error in this sequence because I honesty can't see one.

Code:
row1=0; row2=1; row3=1; row4=1; // Test ROW1
    if(col1==0) {__delay_ms(250); while (col1==0) return '1';}
    if(col2==0) {__delay_ms(250); while (col2==0) return '2';}
    if(col3==0) {__delay_ms(250); while (col3==0) return '3';}
 
Check your colx and rowx macros. Remember that the preprocessor is only text substitution. With that in mind, your ifs become if(PORTBbits.RBx;==0) ...
 
Yes I have deleted the #define's at the beginning of my code and used the port names and therefore I have no more syntax errors. I have uploaded the source in proteus and unfortunatlly the code does not do what I want it to do :D. I will have to work on it some more will post questions if there will be any. Thank you.
 
The only thing wrong with your #define statements are the semi-colon at the end. #define statements do not use a semi-colon at the end. Data type declarations do require it, but not #define statements. Just FYI.
 
The only thing wrong with your #define statements are the semi-colon at the end. #define statements do not use a semi-colon at the end. Data type declarations do require it, but not #define statements. Just FYI.
Spot on!! If you re-edit putting those values back in WITHOUT the semi colon's it will work!!
 
Hello again :D,

I have written the following code and I think I'm almost there.
Again this is my schematic from the simulator:
2eq6frb.png

And this is the code that I've written:
Code:
/*
* File:   keypad.c
* Author: Paul
*
* Created on October 12, 2015, 10:51 AM
*/

#include <stdio.h>
#include <stdlib.h>
#include "keypad.h"
#include <xc.h>

char readKeyboard();
char findKey(unsigned int a, unsigned int b);

void main()
{
    int a;
    TRISA = 0b11110000; // port A is used to display
    TRISB = 0b11110000;

   while(1)
   {

    LATBbits.LATB0 = 1; // first row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 0;


    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 1;}       // a will be 1 if the first button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 2;}   // a will be 2 if the second button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 3;}   // a will be 3 if the third button of the first row is pressed

    LATBbits.LATB0 = 0; // second row made 0
    LATBbits.LATB1 = 1;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 0;
   
    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 4;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 5;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 6;}

    LATBbits.LATB0 = 0; // third row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 1;
    LATBbits.LATB3 = 0;

    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 7;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 8;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 9;}

    LATBbits.LATB0 = 0; // third row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 1;
    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 0;}

 
    // DCD AND 7 SEGMENT DISPLAY
    if(a==1)      LATA = 0b11110001;
    else if(a==2) LATA = 0b11110010;
    else if(a==3) LATA = 0b11110011;
    else if(a==4) LATA = 0b11110100;
    else if(a==5) LATA = 0b11110101;
    else if(a==6) LATA = 0b11110110;
    else if(a==7) LATA = 0b11110111;
    else if(a==8) LATA = 0b11111000;
    else if(a==9) LATA = 0b11111001;
    else if(a==0) LATA = 0b11110000;
   }

}

Basically what I want to do is display on the 7segment display the key which is pressed on the keypad.
The program works (almost) fine for keys 2,3,5,6,8,9 0, #. These keys are display on the 7 segment display when pressed. The ones on the 1st column however(1,4,7 and *) are not. I do not understand why these keys do not appear on the 7 segment display as I've used the same logic for all the keys.

My logic was: Make each row 0. If for example row 1 is 0 and we press on 1 column 1 should be in 1 and so the element on row 0 and column 1(in this case '1') will be pressed and therefore displayed.

And there is another problem. On some keys(especially the ones on last column: 3,6,9 and # sometimes when they are pressed the column remains in 1 logic, it doesn't go back to 0 like the other columns do and so those keys remain displayed on the 7 segment even if I press another key.

I'm sorry if I did not explain it very well I explained it the best I could. I want to make this work with no problems at all.
If someone could tell me how to get rid of those problems that'd be great.

Thank you for reading and sorry if the explanation was not very good.

I have uploaded all the files of the projects here as well:
 

Attachments

  • keypad.rar
    170.2 KB · Views: 237
Another note...if you're not using anti-backfeed diodes, don't drive the LAT bits on the row driving pins. Set all the LAT bits to 1, then switch the TRIS bits instead.

Without anti-backfeed diodes in the circuit, driving the LAT bits poses the potential for a short between the output driving pins if two buttons on different row busses happen to be pressed simultaneously...whether intentionally or by accident. Using my method will instead tristate the pin when set to 1 instead of pulling it fully high, eliminating the possibility of a fatal short between row pins as well as eliminating the need for anti-backfeed diodes.

Also...here is a much simpler way of running your row drivers...using my recommendation -

Code:
void main()
{
    int a;
    TRISA = 0b11110000; // port A is used to display
    LATB = 0b11111111;
    TRISB = (TRISB & 0xF0) + b;


   while(1)
   {
        TRISB = (TRISB & 0xF0) + 14;  //reset cycle

        if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 1;}       // a will be 1 if the first button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 2;}   // a will be 2 if the second button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 3;}   // a will be 3 if the third button of the first row is pressed

    TRISB = (TRISB & 0b11111101) + 1;  //shift left
  
    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 4;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 5;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 6;}

    TRISB = (TRISB & 0b11111011) + 2; //shift left

    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 7;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 8;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 9;}

    TRISB = (TRISB & 0b11110111) + 4;  //shift left

    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 0;}

    // DCD AND 7 SEGMENT DISPLAY
    if(a==1)      LATA = 0b11110001;
    else if(a==2) LATA = 0b11110010;
    else if(a==3) LATA = 0b11110011;
    else if(a==4) LATA = 0b11110100;
    else if(a==5) LATA = 0b11110101;
    else if(a==6) LATA = 0b11110110;
    else if(a==7) LATA = 0b11110111;
    else if(a==8) LATA = 0b11111000;
    else if(a==9) LATA = 0b11111001;
    else if(a==0) LATA = 0b11110000;
   }

}
 
Last edited:
I have added two delays which solved my short-circuit problem. Now keys don't stay pressed and so it works fine(almost).
The program still has the problem where the keys on the first COLUMN won't show up on the lcd no matter what I do :(. Can you please tell me what to modify in my code in order for the keys on first column('1', '4', '7', '#') to show up on the lcd? I can't figure it out. Thank you.

This is the code now I just added 2 delay statements:
Code:
/*
* File:   keypad.c
* Author: Paul
*
* Created on October 12, 2015, 10:51 AM
*/

#include <stdio.h>
#include <stdlib.h>
#include "keypad.h"
#include <xc.h>

char readKeyboard();
char findKey(unsigned int a, unsigned int b);

void main()
{
    int a;
    TRISA = 0b11110000; // port A is used to display
    TRISB = 0b11110000;

   while(1)
   {

    LATBbits.LATB0 = 1; // first row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 0;

    for(int delay=0; delay<2; delay++) __delay_ms(5);
    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 1;}       // a will be 1 if the first button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 2;}   // a will be 2 if the second button of the first row is pressed
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 3;}   // a will be 3 if the third button of the first row is pressed
    for(int delay=0; delay<2; delay++) __delay_ms(5);

    LATBbits.LATB0 = 0; // second row made 0
    LATBbits.LATB1 = 1;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 0;

    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 4;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 5;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 6;}

    LATBbits.LATB0 = 0; // third row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 1;
    LATBbits.LATB3 = 0;

    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 7;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 8;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 9;}

    LATBbits.LATB0 = 0; // third row made 0
    LATBbits.LATB1 = 0;
    LATBbits.LATB2 = 0;
    LATBbits.LATB3 = 1;
    if(PORTBbits.RB4==1 && PORTBbits.RB5==0 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==1 && PORTBbits.RB6==0) {a = 0;}
    else if(PORTBbits.RB4==0 && PORTBbits.RB5==0 && PORTBbits.RB6==1) {a = 0;}


    // DCD AND 7 SEGMENT DISPLAY
    if(a==1)      LATA = 0b11110001;
    else if(a==2) LATA = 0b11110010;
    else if(a==3) LATA = 0b11110011;
    else if(a==4) LATA = 0b11110100;
    else if(a==5) LATA = 0b11110101;
    else if(a==6) LATA = 0b11110110;
    else if(a==7) LATA = 0b11110111;
    else if(a==8) LATA = 0b11111000;
    else if(a==9) LATA = 0b11111001;
    else if(a==0) LATA = 0b11110000;
   }

}
 
OK what happened to this forum's ability to maintain indentations and tabs in copy/pasted code?
 
Try this code -

Code:
void main(void){
    PORTA = 0x00;           //clear PORTA output latch
    PORTB = 0xFF;           //PORTB output latch all high
    PORTC = 0x00;           //clear PORTC output latch

    ADCON1 = 0xFF;          //all port pins digital I/O mode

    TRISA = 0xF0;           //RA0-RA3 output drivers enabled

    TRISB = 0b11110111;
    while(1){
        if(PORTBbits.RB1){
            PORTA = 0;
        }
        TRISB = 0b11111110;
        for(char i = 0; i < 3; i++){
            switch((PORTB / 16) & 0x07){
                case 1:
                    PORTA = 1 + (i * 3);
                    break;
                case 2:
                    PORTA = 2 + (i * 3);
                    break;
                case 4:
                    PORTA = 3 + (i * 3);
                    break;
            }
            TRISB = (TRISB * 2) + 1;
            while(((PORTB / 16) & 0x07) > 0);
            delay_ms(50);

        }
    }
}
 
Last edited:
Have you set the config bit PBADEN to off????
That solved my problem. I did not expect it to do but it totally solved it. Now the keypad works fine. Thank you!

I read in the datasheet that that bit was configuring the ports to analog inputs on reset so I guess that's why it wasn't working. Thank you again.
 
You can also leave that config bit defaulted to on and just clear ANSELB.
 
You can also leave that config bit defaulted to on and just clear ANSELB.
Not quite!!! That chip still has adcon1 control of the ADC inputs as they still fit in it!!! ANSEL registers came later... This is the same as the normal pic18f4xxxx series!!! The only way to disable ADC 8, 9 and 10 is to switch them off..
Even in your code you use ADCON1 = 0xFF;
 
Ah yes the legacy method...oversight on my part. But yeah you can disable PORTB analog mode in code instead of turning off PBADEN. That was my main point.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top