PDA

View Full Version : interrupt handling faster than if's?



mbw123
- 21st October 2006, 02:33
I am using two 16F628A's and trying to get them to communicate serially that have ports turn on when a button is pressed. My code is listed below, but when I run the program it responds VERY SLOWLY. I am wondering if there is a way to make it respond faster by using interrupts, or some other way. Thank you for your time and patience...

PS: the pauses below the hserout commands are to prevent buffer overflow problems (thanks mister_e)

-Mike

Transmitter Code:
-----------------

define HSER_TXSTA 20h
define HSER_BAUD 2400

cmcon = 7

sone var byte
sone = 0
stwo var byte
stwo = 0
sthree var byte
sthree = 0
sfour var byte
sfour = 0
Synch var byte
Synch = "~"
Pre var byte
Pre = $A5

Main:

if (PORTA.0 = 0) AND (sone = 0) then
hserout [Pre,Synch,"1"]
sone = 1
pause 200
endif
if (PORTA.0 = 1) AND (sone = 1) then
hserout [Pre,Synch,"2"]
sone = 0
pause 200
endif


if (PORTA.1 = 0) AND (stwo = 0) then
hserout [Pre,Synch,"3"]
stwo = 1
pause 200
endif
if (PORTA.1 = 1) AND (stwo = 1) then
hserout [Pre,Synch,"4"]
stwo = 0
pause 200
endif


if (PORTA.2 = 0) AND (sthree = 0) then
hserout [Pre,Synch,"5"]
sthree = 1
pause 200
endif
if (PORTA.2 = 1) AND (sthree = 1) then
hserout [Pre,Synch,"6"]
sthree = 0
pause 200
endif


if (PORTA.3 = 0) AND (sfour = 0) then
hserout [Pre,Synch,"7"]
sfour = 1
pause 200
endif
if (PORTA.3 = 1) AND (sfour = 1) then
hserout [Pre,Synch,"8"]
sfour = 0
pause 200
endif

goto Main

Receiver code
-------------
define HSER_CLROERR 1
define HSER_RCSTA 90h
define HSER_BAUD 2400

Msg Var BYte
cmcon = 7

Main:
hserin [WAIT("~"),Msg]


if (Msg = "1") then
high PORTA.0
goto main
endif
if (Msg = "2") then
low PORTA.0
goto main
endif

if (Msg = "3") then
high PORTA.1
goto main
endif
if (Msg = "4") then
low PORTA.1
goto main
endif

if (Msg = "5") Then
high PORTA.2
goto main
endif
if (Msg = "6") then
low PORTA.2
goto main
endif

if (Msg = "7") Then
high PORTA.3
goto main
endif
if (Msg = "8") then
low PORTA.3
endif
goto main

sayzer
- 21st October 2006, 03:48
Hi mbw123,

Providing a timeout to "HSerin" would be one way.

Also, why don't you send Decimal digits? Take a look at DEC modifier.

Lastly, in receiver code, "Select Case" could be handy.


--------------------------------

keithdoxey
- 21st October 2006, 10:56
How are the PICs connected together ? by a wire or by radio/IR link

Do you really need the PRE and SYNCH values to be sent ?

If there is only ever going to be the actual values sent between the PICs then just send the actual values and constantly loop the receiver program like this



Main:
hserin 20,Main [Msg]

Select Case Msg
Case "1"
high PORTA.0
Case "2"
low PORTA.0
Case "3"
high PORTA.1
Case "4"
low PORTA.1
Case "5"
high PORTA.2
Case "6"
low PORTA.2
Case "7"
high PORTA.3
Case "8"
low PORTA.3
end select
goto main



When no data is being received your program will sit at the Hserin command and return to Main every 20mS if nothing is recevied. Because you are constantly waiting for the Msg the reponse will be instant and because you are only sending one character there should be no possibility of overflow unless three messages are sent in very quick succession but even then it should process them fast enough.

You can then reduce the pause in your transmit program to get a very fast response. Currently you have 200*8 mS of pause in the transmit program so it will take a minimum of 1.6 seconds to complete one loop.

You could also speed up the send program by changing



if (PORTA.0 = 0) AND (sone = 0) then
hserout [Pre,Synch,"1"]
sone = 1
pause 200
endif
if (PORTA.0 = 1) AND (sone = 1) then
hserout [Pre,Synch,"2"]
sone = 0
pause 200
endif


to


if (PORTA.0 = sone) then ' input state has changed
if PORTA.0 = 0 then ' port has gone low
hserout ["1"] ' send the command
sone = 1 ' record the state
else
hserout ["2"] ' port has gone high so send the command
sone = 0 ' record the state
end if
pause 10 ' may not even need a pause
endif


That way with no switches being changed you only perform 4 tests each program loop and if a switch has changed you perform an additional test. Can probably be optimised further but brain is not fully functional yet... need more coffee :)

Out of curiosity, why are you storing values opposite to the current state of the pin ?

Personally I would store the current value and detect when it was different. eg



if (PORTA.0<>sone) then ' state has changed
sone = PORTA.0 ' store new state
{ do all the other stuff }
endif

keithdoxey
- 21st October 2006, 11:25
Thinking about this further, and assuming you are only using the pin values to send to the other end then

TRANSMITTER



PORTSTATE var Byte
LASTSTATE var Byte


Main:
PORTSTATE= PORTA & $0F ' mask Port A to retrieve lower 4 pins
If PORTSTATE <> LASTSTATE then ' something has changed
LASTSTATE = PORTSTATE
Hserout [PORTSTATE]
Endif
Pause 10
Goto Main


RECEIVER


Main:
Hserin 20,Main, [PortState]
PortState = PortState ^ $0F ' EOR to invert pin states (omit this line if you want normal state)
PORTA = Portstate ' Set the pins
Goto Main


That would save loads of program space provided you did not need individual pin states for any other purpose.

Dont forget the set the TRISA registers to configure pins as Inputs and outputs.

NB: There might be slight errors above as I rarely get it right first time!!!!

mbw123
- 21st October 2006, 14:01
Thanks for the many responses. I am going to eventually hook it up to a radio link so I will probably need the Pre and Synch values. Using your code previously posted, I should be able to just add those variables in, right? Thanks again (I will test the code right now)...

-Mike

mbw123
- 21st October 2006, 16:12
One last thing. Will the code (your most recent post before this one) work when two or more buttons are pressed at the same time? Thank you for the help.

-Mike

keithdoxey
- 21st October 2006, 21:41
One last thing. Will the code (your most recent post before this one) work when two or more buttons are pressed at the same time? Thank you for the help.

-Mike

Hi Mike, multiple keypresses shouldnt be a problem as it takes the value of all switches as a 4 bit binary value eg 0110 and sends that to the distant end where you write 1001 (or 0110 if you dont invert) to the output port.

LASTPORT gets set as 0110 ( or 6 if you prefer) and the next time it looks at the port if the value is any different the new value will be sent and stored.

It doesnt matter whether it has changed to 0100, 0111, 1010 etc because all of them are different to 0110 and the entire port value will be replicated at the distand end with just a single command string.

mbw123
- 22nd October 2006, 01:02
Hmmmm....the code isn't working. Maybe I am missing something out of the code. Could you post both of the entire programs to make sure I wrote them correctly? Thank you.

-Mike

keithdoxey
- 22nd October 2006, 10:29
I dont have the programs, I just wrote that as a reply.
I did say there might be a mistake in there.

Have you set the TRISA register for inputs on the tranmitter PIC and outputs on the receiver PIC.

Have you disabled the comparators on both PICs

mbw123
- 22nd October 2006, 16:14
I'll check that today. Again, thanks for the responses!

-Mike

mbw123
- 24th October 2006, 01:12
Would this work as the full code (forgive my ignorannce: I'm a newbie)?

Transmitter:
------------

define HSER_TXSTA 20h
define HSER_BAUD 2400

cmcon = 7

PORTSTATE var Byte
LASTSTATE var Byte
input PORTA.0
input PORTA.1
INput PORTA.2
input PORTA.3

Main:
PORTSTATE = PORTA & $0F
If (PORTSTATE <> LASTSTATE) then
LASTSTATE = PORTSTATE
Hserout [PORTSTATE]
Endif
Pause 10
Goto Main


Receiver
--------

define HSER_CLROERR 1
define HSER_RCSTA 90h
define HSER_BAUD 2400

cmcon = 7
PortState VAR byte
output PORTA.0
output PORTA.1
output PORTA.2
output PORTA.3
low PORTA.0
low PORTA.1
low PORTA.2
low PORTA.3

Main:
Hserin 20,Main, [PortState]
PortState = PortState ^ $0F
PORTA = Portstate
Goto Main

mbw123
- 25th October 2006, 02:12
keithdoxey,

what if I wanted to change

"hserout [PORTSTATE]"

to

"hserout [WAIT("~"),PORTSTATE)"

Would that work with the same code?

Thank you.

-Mike

keithdoxey
- 26th October 2006, 23:51
keithdoxey,

what if I wanted to change

"hserout [PORTSTATE]"

to

"hserout [WAIT("~"),PORTSTATE)"

Would that work with the same code?

Thank you.

-Mike

Hi Mike, sorry for the delay replying, been on holiday for a few days :)

The above should be "Hserout["~",PORTSTATE]

Wait is only applicable for Hserin.

In your previous post, instead of all the input and output commands just use the following

Transmitter

TRISA = %11111111 ' all pins as inputs

Receiver

TRISA = %11110000 ' A3-A0 as outputs
PORTA = 0 ' turn off all ports

HTH

Keith

mbw123
- 27th October 2006, 01:25
Thank you very much for the reply.

"Wait is only applicable for Hserin."

Sorry. Stupid mistake by me. I meant

HSERIN [WAIT("~"),PORTSTATE]

Also would that slow down the code a lot?

Thanks.

-Mike