| Swordfish Code Snippet - Multi Tasking |
|
|
| Saturday, 04 April 2009 10:18 | ||||||||||||||||
|
Who ever said PIC's can't do more than one thing at the same time was right, that's because they have a single instruction pointer that executes one command at a time. But what if one function took 1mS, and another took 3mS (and so on). Instead of waiting forever servicing the one function/waiting for a condition, why not allocate a time interval for each task, eg
Sounds a little tricky, the truth of the matter is that it is. Consider the following code and the video below;
Device = 18F452 Clock = 20 #option LCD_DATA = PORTD.4 #option LCD_RS = PORTE.0 #option LCD_EN = PORTE.1 Include "LCD.bas" Include "utils.bas" Include "convert.bas" Dim TMR2_Int_Enable As PIE1.1, // TMR2 interrupt enable TMR2_Overflow As PIR1.1, // TMR2 overflow flag TMR2_On As T2CON.2, // Enables TMR2 to begin incrementing mS As Word, // Time Registers S As Byte, // M As Byte, // H As Byte, // Task_1_Timer As Word, // Task 1 = Check if button pressed Task_2_Timer As Word, // Update Time on LCD Task_3_Timer As Word, // Frequency output 1 Task_4_Timer As Word, // Frequency output 2 Task_1 As Boolean, // Task service request bits Task_2 As Boolean, // Task_3 As Boolean, // Task_4 As Boolean, // Example_Counter As Byte, // Counter register for the button Button As PORTA.0 // Assing the button Pin Const Task_1_Interval = 500, // mS interval for button check Task_2_Interval = 1000, // mS interval between LCD time display updates Task_3_Interval = 100, // mS interval for frequency generator output 1 Task_4_Interval = 5 // mS interval for frequency generator output 2 Interrupt TMR2_Interrupt() Save(0) If TMR2_Overflow = 1 And TMR2_Int_Enable = 1 Then TMR2_Overflow = 0 // Reset TMR2 Overflow flag mS = mS + 1 If mS = 1000 Then // Code for current time mS = 0 S = S + 1 If S = 60 Then S = 0 M = M + 1 If M = 60 Then M = 0 H = H + 1 If H = 24 Then H = 0 EndIf EndIf EndIf EndIf Task_1_Timer = Task_1_Timer + 1 // Increment all Task handlers Task_2_Timer = Task_2_Timer + 1 Task_3_Timer = Task_3_Timer + 1 Task_4_Timer = Task_4_Timer + 1 If Task_1_Timer = Task_1_Interval Then // Check if a task interval is Task_1_Timer = 0 // ready to be flagged Task_1 = True EndIf If Task_2_Timer = Task_2_Interval Then Task_2_Timer = 0 Task_2 = True EndIf If Task_3_Timer = Task_3_Interval Then Task_3_Timer = 0 Task_3 = True EndIf If Task_4_Timer = Task_4_Interval Then Task_4_Timer = 0 Task_4 = True EndIf EndIf Restore End Interrupt Sub TMR2_Initialize() TMR2_On = 0 // Disbale TMR2 TMR2_Int_Enable = 0 // Turn off TMR2 interrupts INTCON.6 = 1 // Peripheral Interrupts Enabled T2CON.0 = 1 // 00 = Prescaler is 1 T2CON.1 = 0 // 01 = Prescaler is 4 // 1x = Prescaler is 16 PR2 = 249 // TMR2 Period register PR2 T2CON.3 = 0 // 0000 = 1:1 postscale T2CON.4 = 0 // 0001 = 1:2 postscale T2CON.5 = 1 // 0010 = 1:3 postscale T2CON.6 = 0 // 1111 = 1:16 postscale TMR2 = 0 // Reset TMR2 Value TMR2_Int_Enable = 1 // Enable TMR2 interrupts TMR2_On = 1 // Enable TMR2 to increment Enable(TMR2_Interrupt) End Sub Sub Check_Button() If Button = 1 Then Example_Counter = Example_Counter + 1 WriteAt(1,11,DecToStr(Example_Counter,3)) EndIf End Sub Sub Update_Time() WriteAt(2,7,DecToStr(H,2), ":", DecToStr(M,2), ":", DecToStr(S,2)) End Sub Sub Freqency_Output_1() PORTB.0 = 1 PORTB.0 = 0 End Sub Sub Freqency_Output_2() PORTB.1 = 1 PORTB.1 = 0 End Sub DelayMS(200) // Allow LCD to warm up SetAllDigital // Make all pins digital I/O's Cls // Clear the LCD screen WriteAt(1,1,"Counter = 000") // Send text that only needs to be sent once WriteAt(2,1,"Time:") // to the LCD mS = 0 // Reset all registers S = 0 // M = 30 // H = 12 // Example_Counter = 0 // Task_1_Timer = 0 // Task_2_Timer = 0 // Task_3_Timer = 0 // Task_4_Timer = 0 // Task_1 = False // Task_2 = False // Task_3 = False // Task_4 = False // Input(Button) // Make the button an input Low(PORTB.0) // Make frequency 1 signal an output and low Low(PORTB.1) // Make frequency 2 signal an output and low TMR2_Initialize // Turn on TMR2 (with settings for 1mS interrupt) While 1 = 1 // Main program loop that is multi-tasked If Task_1 = True Then // Waits for each service request bit to go high Task_1 = False // then services the task as required Check_Button EndIf If Task_2 = True Then Task_2 = False Update_Time EndIf If Task_3 = True Then Task_3 = False Freqency_Output_1 EndIf If Task_4 = True Then Task_4 = False Freqency_Output_2 EndIf Wend
Notice that the interrupt contains only simple flag setting and variable increments. The actual tasks are performed outside the interrupt, so one task could be doing its thing, an interrupt occurs mid way through, "flagging" a task if its intervals elapses. This ensures that the task is serviced when the previous task is complete, easy!
Comments (3)
Joomla components by Compojoom
|
||||||||||||||||
| Last Updated ( Monday, 27 April 2009 10:40 ) | ||||||||||||||||
Whos Online
- ta1dr
- andyo
- Jon Chandler
Forum Activity
the LCD demo hello world - jon chandler Tuesday, 09 March 2010 23:48 - [28 replies]
USB problem - jon chandler Tuesday, 09 March 2010 11:31 - [3 replies]
Servo Module - andyo Tuesday, 09 March 2010 03:39 - [3 replies]
pic to ps2 communication - roshan Friday, 05 March 2010 01:30 - [7 replies]
Way Off Topic: Worldwide Ignite Week - jon chandler Wednesday, 03 March 2010 20:33 - [4 replies]
PIC USB with C and Visual C++ Project - hop Tuesday, 02 March 2010 21:49 - [0 replies]
Function generator help - magic Tuesday, 02 March 2010 16:37 - [10 replies]
Recent Comments
- 2010-03-09 13:27:12 air j...
link:http://www.b2c2u.com/ [air jordan] [url=http://www.handba...
- 2010-03-05 13:24:23 mrpse...
I was thinking of battery with powered routers or powered for every...
- 2010-03-05 12:17:40 andyo
50 rooms - wow. The XBee modules are very easy to use but I'm not ...
- 2010-03-05 11:46:37 mrpse...
Thanks AndyO. What I have to do is design a device to monitor temp...
- 2010-03-05 03:08:58 andyo
The circuit used for the remote sensor can be found here: [url]http...
- 2010-03-04 07:19:06 renno
plz i need help do u know from where i could download it or how cou...
- 2010-03-04 07:16:05 renno
hello everyone i'm trying to finish my final project and i want to ...
- 2010-03-04 02:49:38 Saira...
Thanks that was helpful




Hi Friend,
my name is Sérgio, the guy who is trying to adapat your code to my new on-board computer !
Well, my doubt is :
My original source code was written in PicBasicPro using a 16F877, and I was using 3 different interrupts provided by the Darrel taylor´s interrupt lib.
a) Timer2 for the Time-base (500ms)
b) Timer0 to read the Speed sensor
c) Timer1 (CCP1) to read the Injector´s on-time to calculet the fuel consumption.
Analyzing your code, I did start trying to read the TMR0, configuring it as follows :
Sub TMR0_Initialize()
T0CON.7 = 0 'stop timer0 if its running
T0CON.4 = 0 'increment on rising edge
T0CON.5 = 1 'Put Timer0 in counter mode
T0CON.6 = 0 '16 bit mode
T0CON.3 = 1 'no prescaler
TMR0H = 0 'clear the high byte of the count register
TMR0L = 0 'clear the low byte of the count register
T0CON.7 = 1 'start timer
End Sub
After that, I have another sub to read the TMR0 value :
Sub TMR0_Read()
PulseCount.Byte1 = TMR0H 'get high byte first
PulseCount.Byte0 = TMR0L 'get low byte next
TMR0H = 0 'clear high byte
TMR0L = 0 'clear low byte
GLCD.WriteAt(1,25,DecToStr(PulseCount,3))
End Sub
Modifying your code, the button has been modified to call TMR0_Read :
If Task_1 = True Then // Waits for each service request bit to go high
Task_1 = False // then services the task as required
TMR0_Read()
EndIf
after some tests, I could note get any success.
My doubt is : Do I have to create another interrupt functions to read each timer and/or CCP or My TMR0 routine is enough ?
Regards !
Sérgio