Sorry, I can't do this all for you now. I have work and only find little time in helping.
You have to store the keypresses in an array and add a keypress counter which the keys are stored in the array and the counter incremented each time a key is press.Then if "hash" is pressed, decrease the keypress counter if >0.If "asterisk" is pressed, send the array up to the the number of chars in the keypress counter.
...#define MAX_KEYS 8char key_buffer[MAX_KEYS + 1];unsigned char key_counter = 0;void main (void){ unsigned char i; .... .... while (1) { .... .... .... if (scanned_key1 != 0xFF) { /* debounce */ DelayMs(50); scanned_key2 = scan_keypad() if (scanned_key2==scanned_key1) { decoded_key = decode_key(scanned_key2); display_key(decoded_key); /* putch(decoded_key); */ } /* wait for button release */ while (scan_keypad() != 0xFF) { rx_poll(); } switch (decoded_key) { case '*': key_counter = 0; key_buffer[key_counter++] = decoded_key; break; case '#': for (i=0;i<key_counter) putch(key_buffer[i]); putch('#'); key_counter = 0; break; default: if (key_counter<MAX_KEYS) { key_buffer[key_counter++] = decoded_key; } } } .... .... }}
........const unsigned char led_map[8] = { 0b00000000, 0b00000001, 0b00000011, 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b00111111 /* extra, to prevent overflow */};void main(){ ADCON1 = 0x07; // Configure AN pins as digital init_UART(); //initialize UART Connection init_LED(); //initialize PORTB<3:0>, 4 LEDS connected init_KEYPAD(); //initialize PORTD; //PORTD<3:0> as output //PORTD<6:4> as input /* make RB0-RB5 as outputs for LEDs*/ TRISB &= 0xC0; /* clear LEDs */ PORTB = 0; .... .... scanned_key1 = scan_keypad(); if (scanned_key1 != 0xFF) { /* debounce */ DelayMs(50); scanned_key2 = scan_keypad(); if (scanned_key2==scanned_key1) { decoded_key = decode_key(scanned_key2); display_key(decoded_key); // putch(decoded_key); } /* wait for button release */ while (scan_keypad() != 0xFF) { rx_poll(); } switch (decoded_key) { case '*': /* key_counter = 0; key_buffer[key_counter++] = decoded_key; */ if (key_counter) { --key_counter; } break; case '#': for (i=0;i<key_counter;i++) { putch(key_buffer[i]); } puts("\r\n"); key_counter = 0; break; default: if (key_counter<MAX_KEYS) { key_buffer[key_counter++] = decoded_key; } } /* show LED bargraph */ PORTB = led_map[key_counter & 0x07]; } .... ....
char getch(void){ char c; /* * Clear any receive errors */ if(OERR) //check if there is error { CREN = 0; //clear CREN = 1; //re-enable } while(!RCIF) //wait while no character is received ; c = RCREG; return c;}
The function you posted above is blocking.You should not use this.If you have noticed on the code I posted i create a new function "recv()" which does not wait for the uart for any char but quits immediately if none is found. I don't use getc() anymore.http://www.electronicslab.ph/forum/index.php/topic,15025.msg262219.html#msg262219Serial comms receive characters one at a time only. If you want to receive a string of characters, you have to store them in an array.If you follow the logic on how the keypresses are stored, you will have the idea on how it is done.But to be simpler, I suggest to stick to a single character response from the PC/uart.Why you need to send strings of data to the MCU btw?
void rx_poll(void){char rx;TRISA0 = 0; RA0 = 0; /* OK LED */TRISA1 = 0; RA1 = 0; /* STANDBY LED */TRISA2 = 0; RA2 = 0; /* ERROR LED */TRISA5 = 0; RA5 = 0; /* ALARM PIN */TRISE0 = 0; RE0 = 0; /* DOOR LOCK */TRISE1 = 0; RE1 = 0; /* TIME ENDS */TRISE2 = 0; RE2 = 0; /* TIME ALARM */init_UART();RA1 = 1; if (recv(&rx)) { if (rx == 'G') /* received message from PC that key sequence is good */ { RA0 ^= 1; /* toggle OK LED INDICATOR */ puts("PIN CODE is CORRECT"); RA5 ^= 0; /* toggle Security ALARM ON/OFF */ puts("Room Security ALARM Deactivated"); RE0 ^= 1; /* toggle Door Lock ON/OFF ("Pin should be HIGH TO DISABLE DOOR LOCK") */ puts("Room Lock is Dis Engage"); RE1 ^= 1; /* toggle BULB 10mins before Time ENDS */ RE2 = 1; delay(); RE2 = 0; /* toggle Time END ALARM with .5 seconds Delay */ /*do stuff for OK confirmation ... turn on OK LED ... */ } else if (rx=='B') /* received message from PC that key sequence is BAD */ { RA2 = 1; delay(); RA2 = 0; /* toggle ERROR LED INDICATOR */ puts("PIN CODE is INCORRECT"); /*do stuff for NOT OK confirmation ... turn ON NT OK LED ... */ } }}
void main(){ init_UART(); /*initialize UART Connection*/ TRISA1 = 0; RA1 = 0; /*initialize PORTA1*/ init_KEYPAD(); /*initialize PORTD*/ /*PORTD<3:0> as KEYPAD OUTPUT*/ /*PORTD<6:4> as KEYPAD INPUT*/ RA1 = 1; /*STANDBY LED INDICATOR*/ TRISB &= 0xC0; /* make RB0-RB5 as outputs for LEDs*/ PORTB = 0; /* clear LEDs */{ unsigned char i; while(1) { scanned_key1 = scan_keypad(); if (scanned_key1 != 0xFF) { /* debounce */ DelayMs(50); scanned_key2 = scan_keypad(); if (scanned_key2==scanned_key1) { decoded_key = decode_key(scanned_key2); display_key(decoded_key); } /* wait for button release */ while (scan_keypad() != 0xFF) { rx_poll(); } switch (decoded_key) { case '*': key_counter = 0; break; case '#': for (i=0;i<key_counter;i++) putch(key_buffer[i]); puts("\n"); key_counter = 0; break; default: if (key_counter<MAX_KEYS) { key_buffer[key_counter] = decoded_key; key_counter++; } } PORTB = led_map[key_counter & 0x3F]; /* show LED bargraph */ }} }}
void rx_poll(void){char rx; ADCON1 = 0xC0; // Configure AN pins as digital TRISA0 = 0; RA0 = 0; /* OK LED */ TRISA1 = 0; RA1 = 0; /* STANDBY LED */ TRISA2 = 0; RA2 = 0; /* ERROR LED */ TRISA5 = 0; RA5 = 0; /* ALARM PIN */ TRISE0 = 0; RE0 = 0; /* DOOR LOCK */ TRISE1 = 0; RE1 = 0; /* TIME ENDS */ TRISE2 = 0; RE2 = 0; /* TIME ALARM */RA1 = 1; /* STANDBY LED ALWAYS ON */RA5 ^= 1; /* active when system is lock */ if (recv(&rx)) { if (rx == 'G' ) /* received message from PC that key sequence is good */ { RA0 ^= 1; /* toggle OK LED INDICATOR */ // puts("PIN CODE is CORRECT"); RA5 ^= 0; /* toggle Security ALARM ON/OFF */ // puts("Room Security ALARM Deactivated"); RE0 ^= 1; /* toggle Door Lock ON/OFF ("Pin should be HIGH TO DISABLE DOOR LOCK") */ // puts("Room Lock is Dis Engage"); RE1 ^= 1; /* toggle BULB 10mins before Time ENDS */ RE2 = 1; delay(); RE2 = 0; /* toggle Time END ALARM with .5 seconds Delay */ /*do stuff for OK confirmation ... turn on OK LED ... */ } if (rx== 'B' ) /* received message from PC that key sequence is BAD */ { RA2 = 1; delay(); RA2 = 0; /* toggle ERROR LED INDICATOR */ // puts("PIN CODE is INCORRECT"); /*do stuff for NOT OK confirmation ... turn ON NT OK LED ... */ } }}
void main(){ init_UART(); /*initialize UART Connection*/ TRISA1 = 0; RA1 = 0; /*initialize PORTA1*/ init_KEYPAD(); /*initialize PORTD*/ /*PORTD<3:0> as KEYPAD OUTPUT*/ /*PORTD<6:4> as KEYPAD INPUT*/ RA1 = 1; TRISB &= 0xC0; /* make RB0-RB5 as outputs for LEDS*/ PORTB = 0; /* clear LEDS */ { unsigned char i; while(1) { scanned_key1 = scan_keypad(); if (scanned_key1 != 0xFF) { /* debounce */ DelayMs(50); scanned_key2 = scan_keypad(); if (scanned_key2==scanned_key1) { decoded_key = decode_key(scanned_key2); // display_key(decoded_key); } /* wait for button release */ while (scan_keypad() != 0xFF) { rx_poll(); } switch (decoded_key) { case '*': key_counter = 0; break; case '#': for (i=0;i<key_counter;i++) putch(key_buffer[i]); puts("\n"); key_counter = 0; break; default: if (key_counter<MAX_KEYS) { key_buffer[key_counter] = decoded_key; key_counter++; } } /* show LED bargraph */ PORTB = led_map[key_counter & 0x3F]; } rx_poll(); } }}
There are still errors:- rx_poll() on main() is placed under the "if (scanned_key1 != 0xFF)" which should NOT be. Please check again my original code.- you should not use blocking functions on this app because it should service immediately characters received from the uart.
void main(){ init_UART(); /*initialize UART Connection*/ TRISA1 = 0; RA1 = 0; /*initialize PORTA1*/ init_KEYPAD(); /*initialize PORTD*/ /*PORTD<3:0> as KEYPAD OUTPUT*/ /*PORTD<6:4> as KEYPAD INPUT*/ TRISB &= 0xC0; /* make RB0-RB5 as outputs for LEDS*/ PORTB = 0; /* clear LEDS */ RA1 = 1; { unsigned char i; while(1) { scanned_key1 = scan_keypad(); if (scanned_key1 != 0xFF) { /* debounce */ DelayMs(50); scanned_key2 = scan_keypad(); if (scanned_key2==scanned_key1) { decoded_key = decode_key(scanned_key2); // display_key(decoded_key); } /* wait for button release */ while (scan_keypad() != 0xFF) { rx_poll(); } switch (decoded_key) { case '*': key_counter = 0; break; case '#': for (i=0;i<key_counter;i++) putch(key_buffer[i]); puts("\n"); key_counter = 0; break; default: if (key_counter<MAX_KEYS) { key_buffer[key_counter] = decoded_key; key_counter++; } } /* show LED bargraph */ PORTB = led_map[key_counter & 0x3F]; } } rx_poll(); }}
How did you know that the rx_poll() or the reception of data from the UART is not working?By the LEDs?Take note the on the rx_poll() routine, you added some codes that TURNs OFF the LEDs everytime this is called.These codes were not on my original code.Quote from: zer0w1ng on February 16, 2010, 08:56:06 AMHow did you know that the rx_poll() or the reception of data from the UART is not working?By the LEDs?Take note the on the rx_poll() routine, you added some codes that TURNs OFF the LEDs everytime this is called.These codes were not on my original code.rx_poll() is always called within the main loop thus the all the LEDs are OFF always.rx_poll() is always called within the main loop thus the all the LEDs are OFF always.
How did you know that the rx_poll() or the reception of data from the UART is not working?By the LEDs?Take note the on the rx_poll() routine, you added some codes that TURNs OFF the LEDs everytime this is called.These codes were not on my original code.rx_poll() is always called within the main loop thus the all the LEDs are OFF always.
TRISA0 = 0; RA0 = 0; /* OK LED */ TRISA1 = 0; RA1 = 0; /* STANDBY LED */ TRISA2 = 0; RA2 = 0; /* ERROR LED */ TRISA5 = 0; RA5 = 0; /* ALARM PIN */ TRISE0 = 0; RE0 = 0; /* DOOR LOCK */ TRISE1 = 0; RE1 = 0; /* TIME ENDS */ TRISE2 = 0; RE2 = 0; /* TIME ALARM */
This will turn the LEDs OFF every time rx_poll() is called.Code: [Select] TRISA0 = 0; RA0 = 0; /* OK LED */ TRISA1 = 0; RA1 = 0; /* STANDBY LED */ TRISA2 = 0; RA2 = 0; /* ERROR LED */ TRISA5 = 0; RA5 = 0; /* ALARM PIN */ TRISE0 = 0; RE0 = 0; /* DOOR LOCK */ TRISE1 = 0; RE1 = 0; /* TIME ENDS */ TRISE2 = 0; RE2 = 0; /* TIME ALARM */Move this before the main loop or maybe everytime you will press '*'.Turning off the status LEDs must be on a separate routine, for example on TIME ALARM, which turns ON at the alarm time.But this needs to be OFF, for example the alarm length is 30 seconds only, so you need to devise a non-blocking timer which will turn OFF the ALARM LED after 30 seconds.IMHO, this type of application needs multitasking engine such as tthread (as my initial advice) to be simpler.The example code is using a simplified state machine using "scanned_key1 != 0xFF" (keypad pressed) or the recv() function (uart data received) that has active an non-active states which is only serviced when TRUE.For non-blocking timers, you need to add a timer interrupt and decrements a timer value inside and only service the timeout when the value is 0.This will become complicated when you have additional tasks/states to be serviced as well such as DOOR, ALARM pin, TIME END etc.