Thought about using interrupts and doing many things at the same time?
Using the TMR2 on the PIC you can create a very accurate small timed interrupt, say 1mS
Now every 1mS, the program will be interrupted and passed to the ISR (interrupt service routine)
With a couple of flags (Boolean expressions) you can control your outputs easily.
Heres a few snippets that might help (note that this is for use with a 20Mhz crystal, allowing a 20uS interrupt)
Just on that - You could make it faster, but at 20uS, it gives my program 100 lines of code to execute in between interrupts. eg, 10uS interrupt would limit me to 50 lines of code between interrupts - this leads to problems as not all of the program can be "executed/checked for values" between interrupts
Code:
Result = ADIN 0
Select Result
Case 0 To 100
Spkr_uS Delay = 100 ' Create a 5KHz tone later for both speakers
Case 100 To 200
Spkr_uS Delay = 200 ' Create a 2.5Khz tone later for both speakers
.
.
.
EndSelect
Loops = 0
Repeat
mS = 0
Repeat
If uS = Spkr_uS Then
Speaker_1 = 1
Speaker_2 = 1
ElseIf uS = Spkr_uS * 2 Then
uS = 0
Speaker_1 = 0
Speaker_2 = 0
Endif
Until mS = 75
DelaymS 500
Inc Loops
Until Loops = 3
Your ISR would look something like;
Code:
ISR:
GIE = 0
If TMR2_Overflow = 1 And TMR2_Enable = 1 Then
TMR2_Overflow = 0
uS = uS + TMR2_uS
If uS >= 1000 Then
uS = uS - 1000
mS = mS + 1
EndIf
EndIf
GIE = 1
Context Restore
And To setup TMR2, something like this would be needed;
Code:
Initialization:
TMR2_Enable = 0
INTCON.6 = 1 ' Peripheral Interrupts
T2CON.0 = 0 ' 00 = Prescaler is 1
T2CON.1 = 0 ' 01 = Prescaler is 4
'1x = Prescaler is 16
PR2 = 19 ' TMR2 Period ( * Creates a 20uS interrupt with 20Mhz crystal * )
T2CON.3 = 0 ' 0000 = 1:1 postscale
T2CON.4 = 0 ' 0001 = 1:2 postscale
T2CON.5 = 0 ' 0010 = 1:3 postscale
T2CON.6 = 0 ' 1111 = 1:16 postscale
TMR2 = 0 ' Reset TMR2 Value
TMR2_Enable = 1
TMR2_On = 1
GIE = 1