PDA

View Full Version : pic18f887 event timer



cpayne
- 19th October 2010, 20:00
I am using a PIC18F887 with the internal oscilator set @ 8MHz. I have a subroutine I need to fire off at a routine basis (nominally every 22ms although I want it a constant that I can tune). Can someone give me a crash course (with as much details so I don't have to ask a bunch of follow on dummy questions) on how I set this up as some sort of timer on an interupt, preferably without using assembly, but if that is the only way, I am willing to try. I have no available IO pins remaining if that matters. I am using no other interupts, but future versions may entail a serial interupt. I only want it to fire after a complete line is executed, which I think is by default, then return to the next line after it runs the routine. I suspect its fairly easy, but I am not sure where to start.

Thanks,
Charlie

mackrackit
- 19th October 2010, 23:04
http://www.picbasic.co.uk/forum/showthread.php?t=3251
Be sure to read the first eight post.

cpayne
- 26th October 2010, 02:35
OK. This looks good. Thanks.

I think the overkill blinking light is the right for me to use. I am unlear what to change to get timer 1 to fire off every 22ms.

I assume it starts with this seting
T1CON = $31 ; Prescaler = 8, TMR1ON

I have two different harware setups I am trying to put it in. Both use the PIC16F887, one with an external 20MHz Osc, the other with an internal 8MHz. It looks like a prescaler of 1:8 is the max, so I suspect I need to do a counter in the interupt routine that only fires my event every nth time to acheive the 22ms event? Is this a big burden or is there a simpler way? Can someone show me some examples of how to do the math to get the event to fire off properly with the two oscillator speeds?


Thanks,
Charlie

aratti
- 26th October 2010, 09:51
Can someone show me some examples of how to do the math to get the event to fire off properly with the two oscillator speeds?

Charlie, play with the attached little tool to find out.

How to use it: click on the box enter the new value and press enter.

Cheers

Al.

mackrackit
- 26th October 2010, 11:23
Timer 1 is 16 bit.
At 8 Mhz with a prescale of 1 and a peload of 21537 will give 22.0 mSec
At 20 Mhz with a prescale of 2 and a peload of 10536 will give 22.0 mSec

http://www.picbasic.co.uk/forum/content.php?r=159-New-PIC-Utility.-PICMultiCalc
http://www.picbasic.co.uk/forum/showthread.php?t=3251&p=23259#post23259

cpayne
- 26th October 2010, 17:27
I am not sure if I shoudl reply to this thread or the main interupt thread.

Anyways, I am getting errors when compiling. It looks like its all with the includes files.

I have attached a screenshot showing the errors and my code

Can anyone let me know what I am doing wrong?

Thanks,
Charlie

Darrel Taylor
- 26th October 2010, 18:02
The answers are in the errors. They tell you what you need to do.

cpayne
- 26th October 2010, 18:33
...perhaps the errors mean something to those who know, but I am not smart enough to know (hence the reason I am for asking for help). A little more guidance would be appreciated. am I suposed to edit pbppic14.lib, if so how and where, its a huge file. Or am I suposed to change the includes file for the PIC16F887?

Thanks,
Charlie

Darrel Taylor
- 26th October 2010, 18:44
Add ...

wsave VAR BYTE $70 SYSTEM

to your program.

cpayne
- 26th October 2010, 20:12
OK. Thanks, Compiles now and have a blinking LED. Back to the timing... Sorry I am so dense with this.

How do I go about setting the timer for prescale of 1 and a peload of 21537

I have been looking at previous posts and the datasheet for the 16f887, but not really sure what I need to do.

I assume I have to set T1CON and perhaps OPTION_REG

Also would I be better off using Timer2 since its 8bit (would it be less resources, etc?). As the timer is tripping along, there is no issue with timing of other things like serial commands, I2C timing, etc?

mackrackit
- 26th October 2010, 21:50
http://www.picbasic.co.uk/forum/showthread.php?t=3251&p=17472#post17472
Has the example to set the pre-scaler.
Then in your code for the pre-load.

PreLoad VAR WORD
PreLoad = 21537
TMR1L = PreLoad.LowByte
TMR1H = PreLoad.HighByte
Then in the interrupt routine

TMR1L = PreLoad.LowByte ' Load the timer with preload value.
TMR1H = PreLoad.HighByte
Maybe....

cpayne
- 26th October 2010, 22:03
cool. I had it in the begining, did not have it in the interupt. Firing every 22ms on the scope.

So, this will not mess up anything as far as I2C or serial? or is that dependent on what I do during the interupt? (The final interupt will take about 10-14ms and fire off every 22ms)

mackrackit
- 26th October 2010, 23:02
So, this will not mess up anything as far as I2C or serial? or is that dependent on what I do during the interupt? (The final interupt will take about 10-14ms and fire off every 22ms)
You need to get in and out of an interrupt routine as quick as possible.
So if the I2C and serial stuff is handled out side then you should be good.

cpayne
- 27th October 2010, 02:15
In order to get in and out quick I will need to use another timer I guess. I need to fire off serries of 8 pulses every 22ms. The high pulses will range from 400us to 1800us with a 400uslow pulse/pause between each one. So I am looking for some advise as to the best approach. Would be the best approach it with a second timer or the same one? I guess if I use the same one I can add up all the small pulses and then wait the difference of 22ms and repeat, but I am not sure if that is as reliable as using two timers, perhaps simpler though. If two timers, should I use timer1 (the 16 bit one for the shorter pulses since their accuracty is more critical than the 22ms) and timer0 or timer2 for the 22ms event. Is there any big deal with changing the preload value for the shorter pulses each time?

In either approach, can I use a case select inside the interupt routine to remember where I am in the interupt pulse train each time I return, or is there something I have to do to pass variables in and out of the interupt routine.

Thanks,
Charlie

mackrackit
- 27th October 2010, 06:41
I probably worded that wrong. Just make sure you finish before the next period and/or leave enough time to do whatever else you need to do.

cpayne
- 27th October 2010, 20:27
I have finished puting the original non interupt code into the new program. any reason why PORTB.2 is all of a sudden reading high all the time. I can ground it out with a switch and it will not change state. I when back to the old program and the pin funtions fine, so I assume its something to do with the new interupt, since that is all that has changed, but I can't figure out what. Any suggestions. Thanks

mackrackit
- 27th October 2010, 20:46
Just for giggles can you post your current code? Preferably in code tags...

cpayne
- 27th October 2010, 21:08
here is the entire front end...




@ __config _CONFIG1, _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF

OSCCON = $70 'sets the oscillator speed
DEFINE OSC 8 'Oscillator speed in MHz

'http://www.picbasic.co.uk/forum/showthread.php?t=3251
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts

PORTA = %00000000 ' output logic at power-up
PORTB = %00000000 ' output logic at power-up
PORTC = %00000000 ' output logic at power-up
PORTD = %00000000 ' output logic at power-up
PORTE = %00000000 ' output logic at power-up

' Set up serial UART
define HSER_RCSTA 90H ' Set Receive Status and control register
DEFINE HSER_TXSTA 24H ' set transmit status and control register
DEFINE HSER_BAUD 19200 ' baud setting 19200 115200
define HSER_CLROERR 1 ' reset on serial buffer overflow

' Define Analog parameters
ADCON1 = %10000000 'Right Justify
ANSEL = %11111111 'Analog on for AN0-AN7
ANSELH = %00000000 'AN8-13 off

Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 10 ' Set sampling time in uS

' Alias pins (0=Output, 1=Input)
L1 VAR PORTC.5 :TRISC.5 = 0
L2 VAR PORTD.2 :TRISD.2 = 0
L3 VAR PORTD.1 :TRISD.1 = 0
L4 VAR PORTD.0 :TRISD.0 = 0
L5 VAR PORTC.1 :TRISC.1 = 0

Sp var PORTC.2 :TRISC.2 = 0 'pulsed signal

S2 var PORTD.5 :TRISD.5 = 1 'mode switch - LCD Select Mode
S3 var PORTD.4 :TRISD.4 = 1 'mode switch - LCD Light
S1 var PORTD.7 :TRISD.7 = 1 'mode switch - Plus
S5 var PORTD.6 :TRISD.6 = 1 'mode switch - Minus

S8 var PORTB.4 :TRISB.4 = 1 'Pelco-D board - Zoom
S11 var PORTB.5 :TRISB.5 = 1 'Peclo-D board - Zoom

S7 var PORTB.1 :TRISB.1 = 1 'RC board - Mast
S10 var PORTB.3 :TRISB.3 = 1 'RC board - Mast

S6 var PORTB.2 :TRISB.2 = 1 'Video Select

'Define RAM
i var byte
j var byte
RC_Mode var Bit 'Flag to switch back and forth from arm and drive funtions
S2_Rel var BIT 'flag to see if switch is realsed
S6_Rel var BIT 'flag to see if switch is realsed
Mode_Debug var bit 'Flag for LCD Debug Mode
Mode_Debug1 var bit 'Flag for LCD Debug Mode
LCD_msg var byte 'Counter to reset LCD message Display
wsave VAR BYTE $70 SYSTEM 'value required for interupt
PreLoad VAR WORD 'Preload value for timer interupt
PreLoad = 21537

JOY1X var word ' Analog Values
JOY1Y var word
JOY2X var word
JOY2Y var word
P1 var word
Battery var word ' Battery voltage analog
Battery_r var word ' battery voltage remainder
Batt_div con 660 ' scaling value to get Volts
Batt_Alarm con 480 ' approx 7.2V
Batt_Stop con 430 ' approx 6.5V
Batt_stop1 var byte
Batt_beep var byte
Lights_Last var BIT
Video_Mode var BYTE
Video_Changed VAR BYTE

JOY1X_Trim var Byte 'trim value 128 = neutral trim, 0=-128, 256=128
JOY1Y_Trim var Byte
JOY2X_Trim var Byte
JOY2Y_Trim var Byte
Temp_Trim var BYTE

JOY1X_GainH con 6 'Gain for High end of stick 50-130% (5-13)
JOY1X_GainL con 6 'Gain for Low end of stick 50-130% (5-13)
JOY1Y_GainH con 6
JOY1Y_GainL con 6
JOY2X_GainH con 6
JOY2X_GainL con 6
JOY2Y_GainH con 6
JOY2Y_GainL con 6
P1_GainH con 10
P1_GainL con 10

JOY1X_Max con 1400 'pan
JOY1X_Min con 800 'pan
JOY1Y_Max con 1400 'tilt
JOY1Y_Min con 800 'tilt
JOY2X_Max con 1400
JOY2X_Min con 800
JOY2Y_Max con 1400
JOY2Y_Min con 800
P1_Max con 1850 'Aux Tilt
P1_Min con 450 'Aux Tilt

Pulse_Start con 400 '400us - fudge: Pulse Start (high) + chan pulse (low) = Total chan pulse
chan_adj con 9 'fudge factor for pulses (used a scope to come up with value)
Chan_Ctr con 1100
Chan1 var word 'Aile
Chan2 var word 'Elev
Chan3 var word 'Thro
Chan4 var word 'Rudd
Chan5 var word 'Gear
Chan6 var word 'Aux1
Chan7 var word 'Aux2
Chan8 var word 'Aux3
Chan1f var word 'Aile
Chan2f var word 'Elev
Chan3f var word 'Thro
Chan4f var word 'Rudd
Chan5f var word 'Gear
Chan6f var word 'Aux1
Chan7f var word 'Aux2
Chan8f var word 'Aux3

'Reverse Bits, Channel , Mode 1 (0=Normal, 1=Reverse)
Chan1_1R con 0 'Drive Turn
Chan2_1R con 1 'Drive Speed
Chan3_1R con 0 'Camera Tilt
Chan4_1R con 0 'Camera Pan
Chan5_1R con 1 'Aux Camera Tilt

'LCD Constants
LCD_CLR con 88 'clear
LCD_INSTR CON 254 'instruction command
LCD_L con 71 'move curser to position 71 [column] [row]
LCD_H CON 72 'move curser home
LCD_BL1 con 66 'backlight on, follow by minutes
LCD_BL0 con 70 'backlight off

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _RC_Pulse, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %00000001 ; Prescaler = 1:1, TMR1ON
TMR1L = PreLoad.LowByte
TMR1H = PreLoad.HighByte ; preload to give 22mS interrupts (at 1:1)

' /////////////////////////////////////////////////////////////////////////////
' Begin
' /////////////////////////////////////////////////////////////////////////////

high l1: pause 50: high l2: pause 50: high l3: pause 50: high l4: pause 50: high l5: pause 50
low l1: pause 50: low l2: pause 50: low l3: pause 50: low l4: pause 50: low l5: low 50

'trim values retreived from eeprom
gosub Sub_Read_EEprom

if JOY1X_Trim = 255 and JOY1Y_Trim = 255 then 'means things are zeroed out (reprogrammed), so set defaults
High L5: pause 250: low L5
JOY1X_Trim = 128
JOY1Y_Trim = 128
JOY2X_Trim = 128
JOY2Y_Trim = 128
gosub Sub_Write_EEprom
endif

@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts

' /////////////////////////////////////////////////////////////////////////////
' Main Loop
' /////////////////////////////////////////////////////////////////////////////
mainloop: ' Main program loop

mackrackit
- 27th October 2010, 21:50
PORTA = %00000000 ' output logic at power-up
PORTB = %00000000 ' output logic at power-up
PORTC = %00000000 ' output logic at power-up
PORTD = %00000000 ' output logic at power-up
PORTE = %00000000 ' output logic at power-up
Try setting the TRIS registers here
TRISA = xxx
TRISB = xxx
_ _ _ _ _ _