PDA

View Full Version : 16f877A and tmr1 external crystal question



comwarrior
- 10th July 2009, 02:58
This might be a stupid question... but i'll ask anyways...

Does the external crystal for TMR1 have to be a crystal or is their other options?
For example, could i run it from one of the PWM lines... or perhaps an RC method... or some sort of TTL gates....

Also what about those ceramic resonators... they have 3 pins, how do you connect them? and can i use one on TMR1 (datasheet only briefly says to consult the manufacturers datasheet for caps with resonators, doesn't say you can use them)

Thanks

Melanie
- 10th July 2009, 08:53
There are no stupid questions... just stupid answers... and I'll attempt one now... (oops if you read my reply prior to 09:35 just ignore it... Melanie must remember to read the damn Datasheet before giving advice!!!!!!!!)...

TMR1 DOES have a crystal input capability.

You can have a CRYSTAL which requires loading Capacitors (connected as per the Datasheet schematic), or you can use a RESONATOR - the three pin types are neat because the middle pin is connected to Ov (Vss) and the outer pins connect to your OSC pins (polarity irrelevant). On those Resonators, the Capacitors are built-in and you don't need any further components.

You can have any (hopefully) square-wave input as a Counter for TMR1. Any external circuit that is giving pulses... (you want for eample TMR1 to tick at exactly 1Hz, then you can feed it from the output of a DS1307). Yes, you can feed-back a PWM signal as an external counting source for TMR1, but it's too early in the morning and I've had insufficient coffee to attempt to guess why you would want to do this.

comwarrior
- 11th July 2009, 01:09
lol, your post time was 9am... my post time was 3am... can you tell i was up late scouring the datasheet... lol

right... using the onboard PWM means i can set the frequency to what i want and not to the nearest xtal i can find, plus if for any reason i need to change it it's simple to do rarther than look for another xtal... and it makes floating point maths a little easyer!
To be completely honest, i skipped the section on using the tmr1 as a counter, and now realise i can link the PWM output into TMR1's COUNTER (not clock) input... so efectively, it was a stupid question...

resonators... cool, thanks for the info... i have one sat in a salvage draw I think it's 4MHz... and yes, i strip componants of dead boards, test then and re-use when needed...
anyone know what frequency the xtal is for the CMOS on PC motherboards?
I have a couple of these too but their no markings on them...

I suppose i could use one of my PICs to do a TMR0(20MHz) - TMR1(unknown xtal) compair, provided the xtals run TMR1...

Thanks Mell

comwarrior
- 13th July 2009, 00:40
hi everyone, i'm back again...
I'm still having trouble with my RPM counter... it's still giving me stupid readouts...

i've got PWM1 linked straight into RC0/T1CKI and runing at 50% duty and 1KHz.
TMR1 is therefor set to counter mode and 1:1 prescaler...

However, it hapily runs my pulse motor so the control side is fine... but the RPM counter seems to stay at 5727 or 6136 which i don't understand... even when i slow the rotor down by hand it stays at those readings...

I just don't get why it's doing that... Can someone take a look at my program?

Thanks


include "bs1defs.bas"
Define CONF_WORD = 0x3F3A
Define OSC 24 ' Set clock speed
SEROUT2 PORTB.5,16390,[10,13,10,13]
DEFINE SER2_BITS 8 ' Ser2 number of data bits
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
ADCON0.7 = 0 ' ADC clock set to Fosc/2
ADCON0.6 = 0 ' ADC clock set to Fosc/2
ADCON1.6 = 0 ' ADC clock set to Fosc/2
INTCON = 0 ' Disable all interupts
'RCSTA = %10010000 ' Enable serial port and continuous receive
'TXSTA = %00100100 ' Enable transmit and asynchronous mode with BRGH 1
'SPBRG = 20 ' Set baud rate to 57600 with 20mhz clock (BRGH = 1)
ADT1 var word ' Create ADT1 to store curent ad conversion for AD channel 0
ADT1MAX var word ' Create ADT1MAX to store curent ADC0 max val
ADT1MAX = 0
ADT1VAL var word
ADT1VAL = 0
ADV1 var word
VOLT1H var word
VOLT1L var word
C1N var bit
C1N = 0
C1S var bit
C1S = 0
PCOUNTER var byte
PCOUNTER = 0
PTICK var bit
PTICK = 0
RPM var word
RPM = 0
TMR1_VAL var word
TMR1_VAL = 0
cycle var word
'aveadc1 var word
'averpm var word
TMR1EXT var byte
rpm0 var bit
rpm0 = 0
'datalog var word
'datalog = 0

'TRISE = 255 ' Set PortE to all inputs
TRISD = 0 ' Set PortD to all outputs
TRISC = 0 ' Set PortC to all outputs
TRISB = 0 ' Set PortB to all outputs
TRISA = 255 ' Set PORTA to all input
ADCON1 = 0 ' PORTA is analog

PORTB = 0
PORTC = 0
PORTD = 0

HPWM 1,127,1000
SEROUT2 PORTB.5,16390,["INITIALISED",10,13]
gosub TMR1setup

goto main

TMR1setup:
PIE1.0 = 0 ' Disable TMR1 interupt (double check)
T1CON.5 = 0 ' Setup TMR1 timings
T1CON.4 = 0 ' Setup TMR1 timings
T1CON.3 = 1
T1CON.1 = 1
T1CON.0 = 1
return

main:
FOR cycle = 1 to 3000
gosub getadc
gosub control
gosub backemfreuse
gosub rpmcounter
'gosub avecounter
NEXT cycle
gosub adcvonvert
gosub telemetry
goto main

getadc:
ADCIN 0, ADT1
ADT1 = ADT1 / 64
'write datalog, adt1.highbyte
'write datalog+1, adt1.lowbyte
'datalog=datalog+2
'if datalog > 255 then
'datalog = 0
'endif
return

adcvonvert:
VOLT1H = ((48 * ADT1) / 10000) ' calculate voltage above decimal place using FP
VOLT1L = ((48 * ADT1) - (((48 * ADT1) / 10000) * 10000)) / 100 ' calculate voltage below decimal place using FP
return

'avecounter:
'aveadc1 = (aveadc1/2) + (ADT1/2)
'return

rpmcounter:
if PCOUNTER = 4 then ' wait for 4 pulses befor doing RPM calc
T1CON.0 = 0 ' Pause TMR1
if PIR1.0 = 1 then ' if TMR1 has overflowed we set the RPM to 0
TMR1L = 0
TMR1H = 0
rpm0 = 1 ' Set RPM overide
PIR1.0 = 0
ENDIF
TMR1_VAL.lowbyte = TMR1L ' Load TMR1 Low end byte
TMR1_VAL.Highbyte = TMR1H ' Load TMR1 High end byte
if rpm0 = 1 then ' RPM overide
RPM = 0 ' if RPM overide set RPM to 0
'averpm = 0 ' if RPM overide set aveerage RPM to 0
rpm0 = 0 ' if RPM overide RESET rpm OVERIDE
ELSE ' If their is no RPM overide...
RPM = ((100 / TMR1_VAL) * 60) / 10 ' RPM calculation using simple floating point calculations
'averpm = (averpm/2) + (RPM/2) ' calculate average RPM
ENDIF
PCOUNTER = 0 ' reset pulse counter to 0
TMR1L = 0 ' reset TMR1 low to 0
TMR1H = 0 ' reset TMR1 high to 0
gosub TMR1setup
T1CON.0 = 1 ' restart TMR1
endif
return

telemetry:
'HSEROUT ["V1:",DEC5 VOLT1H,".",DEC5 VOLT1L," RPM:", DEC5 RPM,10,13]

SEROUT2 PORTB.5,16390,["V1:",DEC VOLT1H,".",DEC VOLT1L," RPM:",DEC RPM,10,13]
rpm = 0 ' reset average RPM
RETURN

control:
IF ADT1 > 128 then ' wait for positive voltage from trigger coil
LOW PORTD.7 ' make sure backemf re-use is off
high PORTB.0 ' commence pulse
C1N = 1
IF PTICK = 0 then ' if this is the first run to power the dirve coil
PCOUNTER = PCOUNTER + 1 ' increment the pulse counter
PTICK = 1 ' makes the tick 1 to stop pcounter being incremented untill drive turns off
endif
endif
IF ADT1 < 128 then ' if trigger voltage is low
LOW PORTB.0 ' turn off drive puls
C1N = 0
IF PTICK = 1 then ' if pulse tick is high
PTICK = 0 ' set pulse tick to low
endif
endif
return

backemfreuse:
if C1N = 0 then
High PORTD.7
Else
LOW PORTD.7
endif
return

end