[PIC] Storing a sequence of hex values in register

Status
Not open for further replies.

vilfred

Member level 1
Joined
Mar 21, 2018
Messages
37
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
368
I am using pic18f,uart,led in my program(xc8 compiler). Here i wish to introduce a control to on off led, for that i use a sequence of hex value
02 03 01 - led on
02 03 02 - led off

if i type 02(ctrl+b-keyboard entry) 03(ctrl+c) 01(ctrl+a) in virtual terminal i need the return value of again 02 03 01 to on my led - this is my concept.
I thought this can be achieved in embedded c program by storing this sequence of values in array. My question is how can i compare the sequence of values in receive register?.
if i receive 02 03 01 value then i transmit the same and made led on, but during simulation in proteus if i press ctrl+a i.e. 02 hex value itself led begin to on and return some garbage value. I feel sorry if iam not clear.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
int dc[5] = {0x02,0x03,0x01};//storing sequence in dc[5] array
 
 dc[5] = UART_rx();             // assigning received value as dc[5]
        
        if (dc[0] == 0x02 && dc[1] == 0x03 && dc[2] == 0x01)        
        {
 
            TRISB = 0x00;       //port pin direction as ouput
            PORTB = 0x01;     // led on in portb 0th pin
            UART_send(dc[5]);     // returning the transmitted value
            UART_tx(10);                // length of trasnmit value
            
        }

 
Last edited by a moderator:

You are only storing dc[5] and the values of dc[0],dc[1] and dc[3] are fixed in the initialization.

You need to loop the program so that each time a character is received, it goes into the next dc[] position. You also need some method to detect which is the first byte and to ensure the array doesn't overflow.

If all your data starts with 0x02, when you detect it, set an index counter to zero, then as each new byte arrives, save it in the next index location. You can then either use dc[5] when the index == 5 or, use some other character to mark the end of the data block.

Brian.
 
Also...
You declare 'int dc[5]' but that means that 'dc' has valid indices at 'dc[0]', 'dc[1]', 'dc[2]', 'dc[3]', and 'dc[4]'. Your reference to 'dc[5]' actually points to some other location which indicates that this is a logical error in your program.
To pick up on a point that betwixt makes at the end of his post, having a sequence that you must send to perform some action is fine, but you also need to consider how you will handle errors, especially as the characters are being typed on a keyboard by a person. What should you do when the user types an unexpected character etc.? Should the characters be typed within a given period of time? Even if the ultimate goal is to have some other device send these characters, then you need to think about these things in case of communications failures, noise generating wrong characters and so on.
Susan
 
Try this code.

I am a little busy. I will explain the working in the morning.

Code:
#define ON  1
#define OFF 0

#define Led PORTBbits.RB0
#define Led_Direction TRISBbits.TRISB0

char uart_read[3] = {0, 0, 0};
char i = 0;
char dataReceivedFlag = 0;

 
void interrupt isr() {
    static char uart_rd;

    uart_rd = UART_RX();
    uart_read[i++] = uart_rd;
    if(i >= 3) {
       i = 0;
       dataReceivedFlag = 1;
    }
}

void main() {
   
	Led_Direction = 0;

	while(1) {
		if(dataReceivedFlag) {
			if((uart_read[0] == 0x02) && (uart_read[1] == 0x03) && (uart_read[2] == 0x01)) {
				Led = ON;
			}
			else if((uart_read[0] == 0x02) && (uart_read[1] == 0x03) && (uart_read[2] == 0x02)) {
				Led = OFF;
			}

                        dataReceivedFlag = 0;			
		}
	}
}

Don't use Proteus Virtual Terminal to send data. It sends data as ascii characters. You should use a Serial Terminal software which can send data as hex value that is numerical and without \r and \n. You should sent 2, 3, 1, and 2, 3, 2.
 

baileychic - that code will work but also exhibits the problem I mentioned above: how to correct from an error. For example, say the first character is picked up as something other than a 0x02 (noise etc.) or you realise that you typed the wrong key. You (as the sender) need to determine that some error has occurred and how many character the code thinks it has received and then type however many other characters are needed to bring the counter (the 'i' variable) back to 0 so you can start the sequence again.
I would suggest that you add in some 'reset' character such as (in this situation) any character that is not a 0x01, 0x02 or 0x03 will reset the counter.
That way you have a way of re-synchronising the communication if you need to.
Susan
 

Ok Susan.

Here is the modified code.

Code:
void interrupt isr() {
    static char uart_rd;

    uart_rd = UART_RX();
    uart_read[i++] = uart_rd;
    if((i >= 3) || (uart_read[i - 1] == 'E')) {
       i = 0;
       dataReceivedFlag = 1;
    }
}
 

Hi,

I agree.
02 03 01 - led on
02 03 02 - led off
in your case "02" can be the first ot the third line. Avoid this.
Try to use some unique "End Of Line codes"
I'd use "N" for "oN" and "F" for "oFf". No capital letters in the other columns.
"l1N" could be ("l" = lower case "L") --> Led 1 On
"l2F" --> Led 2 Off.
During receive ... just shift all incoming data through a three stage circular buffer.....start to parse the buffer only when you receive a capital letter.

Usual delimiters are "CrLf" for windows systems or "Lf" for Unix systems.

Klaus
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…