Hi everybody!
I am using PIC18F2550 Mikroc as compiler. My project has a matricial keypad (https://www.arduiner.com/en/tastier...switch-keypad-keyboard-for-arduinoavrpic.html) to get a five digits number that will be a reference to a motor's speed in RPM. At the same time every digit is displayed on an LCD. I want to be able to use one of the key to return( when key '*' is pressed) or advance(when key '#' is pressed) for any digit and replace it in case the user want it. I am trying to use the code below. I have made a function called "print" to print each character. My idea to replace any character was to decrement or increment an integer called "k" so I could know the position of the cursor on the LCD. Then I just printed the new character in the "k" position, but it is not working properly. I can get any digit and print it, but when I press the key "#" or '*' it is not working. Could someone help me with any tips to do it?
Thanks in advance!
Code:
char keypadPort at PORTB;
sbit LCD_RS at RC6_bit;
sbit LCD_EN at RA0_bit;
sbit LCD_D4 at RC0_bit;
sbit LCD_D5 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC6_bit;
sbit LCD_EN_Direction at TRISA0_bit;
sbit LCD_D4_Direction at TRISC0_bit;
sbit LCD_D5_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D7_Direction at TRISC7_bit;
int i, k=0;
char string[5];
void print(){
Lcd_Chr(2, k+1 , string[k]);
}
char menu()
{
Lcd_Init(); // Initialize the LCD
Lcd_Cmd(_LCD_CLEAR);// Clear the LCD
Lcd_Out(1, 1, "RPM"); // Write on LCD
Lcd_Cmd(_LCD_SECOND_ROW);//Move the cursor to the second row
Lcd_Cmd(_LCD_BLINK_CURSOR_ON);// Blink the cursor
while(k<5)
{
while (string[k] == 0) // wait for any key to be pressed
{
string[k] = Keypad_Key_Click();
}
switch(string[k]){
case 1:
string[k]= '1';
print();
k++;
break;
case 2:
string[k]='2';
print();
k++;
break;
case 3:
string[k]='3';
print();
k++;
break;
case 5:
string[k]='4';
print();
k++;
break;
case 6:
string[k]= '5';
print();
k++;
break;
case 7:
string[k]= '6';
print();
k++;
break;
case 9:
string[k]= '7';
print();
k++;
break;
case 10:
string[k]='8';
print();
k++;
break;
case 11:
string[k]='9';
print();
k++;
break;
case 13: // key '*' was pressed
for(i=0;i<1;i++){
Lcd_Cmd(_LCD_MOVE_CURSOR_LEFT);// return the cursor
string[k]=0;
}
break;
case 14:
string[k]='0';
print();
k++;
break;
case 15: //key '#' was pressed
for(i=0;i<1;i++){
Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);//Advance the cursor
string[k]=0;
}
break;
}
}
}
void main(){
ADCON0 = 0; // ADCON0 and ADCON1 registers to enable digital I/O in PORTA (where is an LCD pin)
ADCON1 = 0XFF;
CMCON |= 7;// disable comparators
Keypad_Init();//initialize keypad
menu();//calls the menu function
}
case 13: // key '*' was pressed
if(k){
Lcd_Cmd(_LCD_MOVE_CURSOR_LEFT);
k--;
string[k]=0;
}
break;
case 15: //key '#' was pressed
if(k<5){
Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
k++;
string[k]=0;
}//else, should we terminate user input?
break;
You may want to add an extra position in string[] array for the final NUL terminating, althow there is no reference/problem in the code that you post.
You should also improve the user movement. Let user use #/* but do not delete the indexed character so user could just skip it.
case 13: // key '*' was pressed
if(k){
Lcd_Cmd(_LCD_MOVE_CURSOR_LEFT);
k--;
string[k]=0;
}
break;
case 15: //key '#' was pressed
if(k<5){
Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
k++;
string[k]=0;
}//else, should we terminate user input?
break;
You may want to add an extra position in string[] array for the final NUL terminating, althow there is no reference/problem in the code that you post.
You should also improve the user movement. Let user use #/* but do not delete the indexed character so user could just skip it.
Thanks a lot for the help. This is working now. The only problem I have to fix now is when the user is using the '#' key without finish the 5 digits, because it keeps incrementing my "k" count in the while loop. Because that my keypad stop to work without getting the 5 digits. Do you have any suggestion for this case?
The zip that you uploaded, contains the old code.
In your code, the key '#' increments and then zeroes position. This is a serious problem and may overwrite ram contents with unexpected behavior!!!
The zip that you uploaded, contains the old code.
In your code, the key '#' increments and then zeroes position. This is a serious problem and may overwrite ram contents with unexpected behavior!!!
Xenos, thanks for reply. I get it. You are right. I will put your code and see if it works, ok? About the
Code:
for(i=0;i<1;i++)
I am using that because when I was simulating on Proteus when I pressed the'*' or '#' the cursor started to move without stopping. I'm not sure if it was a problem with my simulator, so when I put this code it worked fine.
I want to be able to use one of the key to return( when key '*' is pressed) or advance(when key '#' is pressed) for any digit and replace it in case the user want it.
What happens when '*' is pressed ? The numbers entered is discarded and it comes out of the keyread process ? What happens if '#' key is pressed after entering a 5 digit number ? The entered number is regsitered and RPM is set ? Are numbers entered always 5 digits or can it be 1 , 2, or 3 digits also ?
Which key you want to use a backspace key to erase the entered digit if it was incorrect ?
What happens when '*' is pressed ? The numbers entered is discarded and it comes out of the keyread process ? What happens if '#' key is pressed after entering a 5 digit number ? The entered number is regsitered and RPM is set ? Are numbers entered always 5 digits or can it be 1 , 2, or 3 digits also ?
Which key you want to use a backspace key to erase the entered digit if it was incorrect ?
I use the '*' key to return the cursor to the last position to replace a wrong digit. I mean, if a digit is incorrect I don't erase it , I just put another digit on his place when another key number is pressed (because the Keypad_Key_Click() keeps running). When the '#' is pressed after entering 5 digits the Keypad_Key_Click() function stops to run and the LCD will show a message, something like this: "press the 'A' key to confirm or the 'B' for correction ( If 'B' is pressed the cursor will blink and the keyread starts again and I will be able to replace the wrong digit). When the 'A' is pressed the number will be registered and I will convert to a integer using the atoi function to set the RPM using a controller that I intend to project. The number will be 5 digits, but if the user wants to run the motor at 500 RPM he has to set 00500 ( I think this way is easier to build my code).
Anyway, if you have any suggest, lemme know, please.