PDA

View Full Version : If Then Array Oddity



atillotson
- 30th June 2005, 05:33
I have a small piece of code That acts very unusual, I got from Bruce, I Believe. Anyway if you look at the label "ThisDoesnt" and compare it to the Label "ThisWorks" you may be able to spot the problem. However, I cant find any reason why this shouldnn't work. But it will not work for me.
I'm using PBP 2.46 and a lovely 18f2620.


DEFINE OSC 4
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Automatically clear over-run errors
DEFINE HSER_RCSTA 90h ' Enable USART receive
DEFINE HSER_TXSTA 24h ' TXSTA=%00100100. TX enable, BRGH=1 for high-speed

GP VAR BYTE ' GP variable
BytesIn var byte[5] ' 0 thru 4 bytes
ByteCnt var byte ' Indicates number of bytes in buffer

OERR VAR RCSTA.1 ' Alias USART over-run bit
CREN VAR RCSTA.4 ' Alias USART continuous receive enable bit
RCIF VAR PIR1.5 ' Alias USART received character interrupt flag bit
INTCON = 0 ' Disable interrupts
ByteCnt = 0 ' Zero counter
ADCON1 = 7 ' A/D off, all digital
OSCCON=%01100000 ' Set internal osc to 4MHZ

Main:
IF oerr then
cren=0
cren=1
endif
IF RCIF THEN ' If RCIF=1 there's a new character in RCREG
BytesIn[ByteCnt]=RCREG ' Yes. Then store it in array
IF ByteCnt = 4 THEN ThisWorks ' IF BytesIn[ByteCnt]=EOM THEN OutMsg
ByteCnt=ByteCnt+1 ' Increment array index pointer
ENDIF
GOTO Main

ThisWorks:

if bytesin[0]= $80 then Weird
Weird:
HSEROUT ["up",str BytesIn\ByteCnt ,13,10]
FOR GP=0 TO ByteCnt ' Clear array bytes 0 to ByteCnt
BytesIn[GP]=0 '
NEXT gp '
ByteCnt=0 ' Reset index pointer back to first element
WHILE RCIF ' Keep reading until RCIF is clear to flush buffer
GP=RCREG ' after EOM is received
WEND
GOTO Main

ThisDoesnt:

if bytesin[0]= $80 then

HSEROUT ["up",str BytesIn\ByteCnt ,13,10]
endif

FOR GP=0 TO ByteCnt ' Clear array bytes 0 to ByteCnt
BytesIn[GP]=0 '
NEXT gp '
ByteCnt=0 ' Reset index pointer back to first element
WHILE RCIF ' Keep reading until RCIF is clear to flush buffer
GP=RCREG ' after EOM is received
WEND
GOTO Main

Also I have replaced this line (if bytesin[0]= $80 then) with a "> 7F and <81" and it works fine. But as soon as I use the "=" to i get nothing.
Could some someone please explain this to me?

thanks ash

Bruce
- 30th June 2005, 06:44
This will work no matter what bytesin[0] is.

ThisWorks:

if bytesin[0]= $80 then Weird
Weird: '<--- fall through to here regardless
HSEROUT ["up",str BytesIn\ByteCnt ,13,10]

Change it to something like;

if bytesin[0]= $80 then Weird
Goto SomeWhereElse ' Jump over weird if bytesin[0] not = $80

Weird:
HSEROUT ["up",str BytesIn\ByteCnt ,13,10]

atillotson
- 30th June 2005, 12:52
Thanks Bruce, But what i need to understand is why this statement below doesn't produce a result.
________________________________________
if bytesin[0]= $80 then
HSEROUT ["up",str BytesIn\ByteCnt ,13,10]
endif
________________________________________

I can use (if bytesin[0]> $7f then) and (if bytesin[0]< $81 then)
in any combination of nested (IF THEN) statements and it works as long as i dont ask it to "=". See code Below, This it what i need to work but doesn't.
If I send the same code from my serial display to my PC I can see that bytesin[0] is infact = to $80.
I also got this code to work using a select case statement.
Basically what im saying is my IF THEN doesn't like "=" if using an array for comparison. But will Compare if using Greater than or less than.
I KNOW, its not logical, thats why i really need your help.

thanks ash

DEFINE OSC 4
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Automatically clear over-run errors
DEFINE HSER_RCSTA 90h ' Enable USART receive
DEFINE HSER_TXSTA 24h ' TXSTA=%00100100. TX enable, BRGH=1 for high-speed

GP VAR BYTE BytesIn var byte[5]
ByteCnt var byte
OERR VAR RCSTA.1
CREN VAR RCSTA.4 RCIF VAR PIR1.5 INTCON = 0
ByteCnt = 0
ADCON1 = 7 '
OSCCON=%01100000

Main:
IF oerr then
cren=0
cren=1
endif
IF RCIF THEN
BytesIn[ByteCnt]=RCREG
IF ByteCnt = 4 THEN MsgOut
ByteCnt=ByteCnt+1
ENDIF
GOTO Main

MsgOut:

if bytesin[0]= $80 then
HSEROUT ["up",str BytesIn\ByteCnt ,13,10]
endif

FOR GP=0 TO ByteCnt
BytesIn[GP]=0
NEXT gp
ByteCnt=0
WHILE RCIF
GP=RCREG
WEND
GOTO Main

Bruce
- 30th June 2005, 14:58
My guess would be it never = $80. Standard ASCII is from $00 to $7F. Extended ASCII starts at $80.

atillotson
- 30th June 2005, 16:43
That was what i thought as well, However I have used 3 different Communication capture programs and am able to determine that it is infact $80 Even PBP will say its $80 as long as I use a different way to compare than the one shown. again if its > $7f and < $81 - it will work. Or i can use select case and that works fine as well
But it doesn't work if I compare with the = sign with an array in my If Then condition.
ash

Bruce
- 1st July 2005, 00:42
And what happens if you do something like this?


Main:
hserin 5000,Waiting,[hex serdata[0],hex serdata[1]]
IF serdata[0] = $80 then
hserout ["Got ",ihex serdata[0]," ",ihex serdata[1],13,10]
ENDIF
goto Main

Waiting:
hserout ["Waiting",13,10]
Goto Main

atillotson
- 1st July 2005, 15:56
It did work.
Hi Bruce,
I do have some difficulty in this logic that I think is due to too much info comming from my serial display or a lack of complete understanding of the onboard eusart. Just FYI Im communicating to a Crystal Fonts 633 serial display. " http://www.crystalfontz.com/products/633/index.html " I have no problems talking to it, although the crc routine that it requires was a bit of a bugger. But only because Im used to LRC. So every time I send the display any Information like (display data), (Contrast Values), (Backlight Values) or anything else, it sends my an acknologment. Normally this is fine, and easy to deal with. But if you look at the Their specs you will find that their Packets have little "common" structure. Their is no (start Byte Char) or (end Byte Char) in the packet and their is no (standard packet length). Some packets are as little as 5 bytes in total packet size and some are as great as 20 bytes in total packet size. The only thing that i have to work with is the 2nd Byte (length of data) and the last 2 bytes are the crc. But screw the receive CRC, I dont think that i have enough time for the added calculations even though the crc routine is easily usable. Not to mention the display is only 1 inch away from my 18f2620. I just feel like i hardly need soo much structure when im not cableing my communication across a room. The part Im currently working on is the built in keypad in the display, Its really Cool!
So Basically the keypad receive packets look like this:
(Command,Length of data,Data,CrcLo,CrcHi) so if I press and release the (down key) on the display keypad I get
Down Key Pressed ($80,$01,[dont care],CrcLo,Crchi) Im trying to ignore this Packet when down
Down Key Released ($80,$01,$08,CrcLo,Crchi) Only care if released.

My controler is very busy with Pid algorithems plus Im communicating with a PC on seperate pins as well as a few I2C devices on my i2c bus.
Because of all of this activity I'm attempting to use my Hardware serial input without a pause for the LCD.

I have thought about using a seperate 12f683 As my "LCD Menu controller" and then using my 18f2620 to communicate via i2c with my own simple protocol. That way the 12f683 can work its butt off parsing whats needed and taking the necessary time to do so.

From your experience, do you have any suggestions as to the best way to parse this data?
Do you like or favor the idea of a seperate pic like the 12f683 do to my requirements?

Your Ideas will be graciously appreciated.

thanks Ash Tillotson

Bruce
- 1st July 2005, 17:46
Hi Ash,

If you have that much going on, your best option short of a dedicated keypad controller is probably a state machine type approach with prioritized tasks.

I know it's not BASIC, but have a look at the logic in this C example of a simple multitasking state machine, and how he prioritizes individual tasks with different time slices. The technique itself applies to any compiler.

http://www.microchipc.com/Hi-Tech_C_multitask.htm

The hardware USART will buffer up to 2 characters in the background. You just have to unload this buffer before the stop bit of the 3rd byte is received.

You have the time it takes to receive several bytes of data before servicing or removing the data from the USART buffer.

If you have the option of slowing the data rate, that may help if other tasks need more time before servicing the USART.

You also have the RCIF flag that indicates there is data in the USART buffer, so an occasional test of this bit can be used to extend time in other task sub-routines & let you know there is data waiting in the buffer.

Then you have the option of interrupts. MeLabs has a couple USART routines http://www.microengineeringlabs.com/resources/samples.htm that will buffer data in the interrupt service routine.

If interrupts just are not an option, and you don't have the time to manage all tasks with a single controller, then the dedicated keypad buffer just might be the best route. Especially if your PID routine is eating up all your overhead.