Hi All! :-)
I have written a very simple command interpreter that takes commands from the USART. It is working as I expect, but it would be really nice to get your inputs about making it better/cleaner/extendable.
Here's how it works:
For a command, I type # followed by the command name at the hyperterminal. All strings terminate with a / char. e.g. #on/ is a command to turn on an LED, #off/ turns it off.
The # char is to distinguish a command from a normal string. e.g. myname/ is just a string.
(more later on why I chose to terminate with a / instead of a newline or return. Not too relevant, for now).
The code is as follows:
/*cmd.c. implementing a simple command interpreter*/ #include#include #include #include int main(){ DDRC= 0xff; //LEDs on PORTC for debugging sei(); bash_init(); char *tempstr= 0; for(;;){ if(temp==1){//a '/' terminated string received. time to respond! temp=0; PORTC = 0x01;//the outputs are active HIGH. turns on LED 1. if(str[0]=='#'){//first char is a #, so this is a command. PORTC |= 0x02;//turns on LED 2 tempstr= str; //copy the command entered tempstr++;; //minus the # char } if(!strcmp(tempstr,"on")){ PORTC |= 0x04;//turns on LED 3 tempstr= 0; } else if(!strcmp(tempstr,"off")){ PORTC = 0x00; //turns off all LEDs tempstr= 0; } } } } /*bashcom.h: contains declarations of UART functions and macros*/ #define F_CPU 16000000 #define BAUD_RATE 9600 #define BAUD_PRESCALE ((F_CPU/(BAUD_RATE * 16UL)) - 1) volatile char str[15]; volatile int temp; void bash_init(); void putc_to_bash(char char_to_display); void puts_to_bash(char* string_to_display); /*bashcom.c. contains USART funtions*/ #include #include #include /*int main(void) //the main function. just in case I need to test it later... { bash_init(); sei(); for(;;){ if(temp == 1){ puts_to_bash(str); temp= 0; } } }*/ void bash_init(){//init the USART UCSRB |= (1<<RXEN) | (1<<TXEN); UCSRC= 0x00; UCSRC |= (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1);//8 bit mode. UBRRH |= (BAUD_PRESCALE >> 8); UBRRL |= BAUD_PRESCALE; //prescaler set for 9600 baud UCSRB |= (1<<RXCIE); temp= 0; } ISR(USART_RXC_vect){ static int count;//number of chars received char RxByte; RxByte = UDR; if(!(RxByte == '/')){ str[count]= RxByte;//storing characters in str array. count++; } else if((RxByte == '/') || (count==13)){ str[count]= '\0'; count= 0; temp= 1;//got a '/' terminated string. tell anyone who cares to know } } void puts_to_bash(char* string){//writes an entire string to bash while(!((*string) == '\0')){ putc_to_bash(*string); string++; } temp= 0; } void putc_to_bash(char dispchar){//writes single chars to bash while(!(UCSRA & (1<<UDRE))); UDR= dispchar; }
Bit 3 of PORTC turns on when I type #on/ and all bits turn off with #off/. So far so good!:-)
Could you please suggest how can I add more commands and still keep it very organized? One option is to simply use a lot of if else statements, but I think it just may not be as elegant.
Also, if there are any serious mistakes in the code, including BAD code practices, please comment.
All suggestions are most welcome.
Thank you for your time! :-)
Cheers,
Aashish
P.S. The code is for atmega16 running off a 16MHz xtal and a 5V supply.