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.

Data model for sending commands to PIC through Serial

Status
Not open for further replies.

bpmelo

New Member
Hi guys, this is not a 100% PIC/Hardware question, it's more of a doubt in how to efficiently send commands to a PIC through the serial interface.

My first approach, which I'm NOT happy with it, is to use a two bytes array like this :

Code:
volatile unsigned char receive_buffer[2];
volatile unsigned char *p_receive_buffer = receive_buffer;
volatile unsigned char char_count = 0;

void serialinterrupt_handler(void) {
	RCIF = 0;
	*p_receive_buffer = (unsigned char)RCREG;
	p_receive_buffer++;
	char_count++;
}

void clear_receive_buffer(void) {
	p_receive_buffer = receive_buffer;
	*p_receive_buffer = '\0';
	p_receive_buffer++;
	*p_receive_buffer = '\0';
	p_receive_buffer = receive_buffer;
	char_count = 0;
}

unsigned char get_char_count(void) {
	return(char_count);
}

unsigned char get_command(void) {
	return(receive_buffer[0]);
}
unsigned char get_command_data(void) {
	return(receive_buffer[1]);
}

As you can see, I save two byte read from serial into receive_buffer[2], and use it in the COMMAND-DATA form.

Like most of my codes, this started just to control a servo from serial, but now I attached a LCD also, and also want to write some info on it, like CPU temp, Wireless signal strength and so on.

I soon realized that wasn't the way of doing it, so how do you guys do it ?

Thanks in advance.
 
I don't write in C (I use ASM) but here is how I do it.

1. Define using CBLOCK a 16 byte buffer (or whatever length you want).
2. Set FSR to first variable location
3. Receive data byte (I'm actually using a PWM variation on my current project and the CCP to translate the byte bit by bit)
4. Store in FSR
5. Incement FSR
6. Repeat until all 16 bits are filled
7. Execute code

I have a checksum as my last byte and all my data is pulled out of a continous stream so if any of the 16 bytes are corrupt, it just waits until the next data packet comes along and pulls the data again from that. My routine transmits a long start on the data line so every device on the bus "syncs" (i.e. sets FSR to first byte) when it sees it.

Seems to be working ok so far for me - should be easily adaptable for use on the normal serial port as well.
 
my data is pulled out of a continous stream so if any of the 16 bytes are corrupt

By this you mean using the CREN (Continuous Receive Enable bit) mode ?

7. Execute code

How exactly do you set the string where you put your command and data information ?

Is it something like :
Code:
COMMAND (7 bytes) + DATA (8 bytes) + Checksum (1 byte) ?
 
The way I would normally implement something like this is to use escape characters (27). I would then do something like,
Code:
    while(1){
        num=GetFifo();              //get character
        if(num==27){                //is it escape
            num=GetFifo();          //yes, so get next char
            switch(num){       
                case('S'):          //is it esc S
                    servo=GetFifo();
                    break;
                case('L'):
                    led=GetFifo();  //esc L
                    break;
            }
        }
        else{
            PutLCD(num);            //not escape sequence so print it
        }
    }

With the above code I would send esc,"S",127 to set the servo to mid position, esc,"L",32 to turn LED 5 on and "Hello world" to print to the LCD.

The GetFifo routine simply fetches the next character from the serial port.

Mike.
 
By this you mean using the CREN (Continuous Receive Enable bit) mode ?



How exactly do you set the string where you put your command and data information ?

Is it something like :
Code:
COMMAND (7 bytes) + DATA (8 bytes) + Checksum (1 byte) ?

I'm not actually using the serial port for this product. I designed my own one wire bidirectional protocol using PWM.

I.e.

If the pulse of the data on the dataline > 200us then this is a reset (sync)pulse
If the pulse of the dataline >20us and <60us then this is a 1 bit
If the pulse of the dataline >100us and <140us then this is a 0 bit

My product addresses up to a couple of hundred slaves on the data bus so my data format is more along the lines:

<ADDR1><ADDR2><COMMAND1:12><CHECKSUMH><CHECKSUML>

If the ADDR1:ADDR2 don't match up with the device ID on the dataline it still grabs the rest of the code but will not act on it.

If the ADDR1:ADDR2 match up and the checksum is fine, the uC dumps the buffer into its "working" registers and the internal code then translates what is in there to do whatever it has to do.

If the commands/data are telling the slave device that it needs a response, the master waits for a predetermined time for a reply changing its transmit pin to a receive pin and waits for a response. If it doesn't receive it, it tries again. If it still doesn't receive a reply, it carries on with addressing the rest of the slaves and has another go next time round.

I capture all data using the CCP register and use interrupts to allow the rest of the code to run in a multitasking type of manner.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top