View previous topic :: View next topic |
Author |
Message |
Christian Olsson
Joined: 08 Mar 2005 Posts: 9 Location: Sweden, Gothenburg

|
Posted: Mon Mar 21, 2005 7:52 pm Post subject: Problem with Timer 1 and mega88 |
|
|
Hi all,
I have a problem when I changed the AT90S4433 to a Mega88
The Timer 1 did not work any more.
I am a beginner whith timers.
I have read the datasheet, but i am not getting any cleverer.
And i wonder how to change the led exactly one time per second.
Thanks in advance Christian.
Code: |
' MCU.......: AVR ATmega88-20AI
' Crystal...: 1 MHz
Led Alias Portd.1
Dim Blink As Bit
$regfile = "m88def.dat"
$crystal = 1000000
Config Portd = Output
Portd = 255
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Const Reload = 125000
Config Timer1 = Timer , Prescale = 8
Stop Timer1
Ocr1ah = High(reload)
Ocr1al = Low(reload)
Tccr1a = 0
Set Tccr1b.3
On Compare1a Timer1_isr
Enable Compare1a
Enable Interrupts
Start Timer1
'
'------[ Blink ]----------------------------------------------------------------
'
Do
Led = Blink
Loop
'
'------[ Interrupt services rutines ]-------------------------------------------
'
Timer1_isr:
Blink = Not Blink
Return
End
|
|
|
Back to top |
|
 |
DToolan
Joined: 14 Aug 2004 Posts: 1384 Location: Dallas / Fort Worth, Texas (USA)

|
Posted: Thu Mar 31, 2005 12:18 am Post subject: |
|
|
Christian,
I don't know why your code used to work and doesn't now... but timer / counters can be fairly simple. Timers and counters both do the same thing (count). The only variables are how fast and how high. How high is obviously determined by the use of 8 or 16-bit counters. How fast is the more tricky part. This is determined by 1. the system clock (crystal) and 2. the prescale value. Configuring timers as counters gives a lot more options (count up / down / trailing edge, etc) which only confuse the simplicity of timer / counters. In the simplest of configurations, a counter always counts up, overflows to zero after reaching it's max count and can trigger an overflow interrupt (this is considered "normal mode"). We'll do that first.
Since you have said that you want a 1 second interval and you are using a 16-bit timer, selecting a prescale value is determined by the calculation...
PScale = Crystal / (DesiredTimerOverflow * MaxCountOfTimer)
PScale = 1,000,000 / (1 sec * 2^16)
PScale = 1,000,000 / 65,536
PScale = 15.25 (select the next available Pscale value... not one that is lower)
PScale = 64
Now that we have determined a prescale value, we can see how many times per second (the frequency) that this timer will overflow (TOV).
TOV = (Crystal / PScale) / MaxCountOfTimer
TOV = (1,000,000 / 64) / 2^16
TOV = 15,625 / 65,536
TOV = .238
Since this is roughly .25, we can quickly see the timer will take approximately 4 seconds to overflow... or the exact time is determined by...
Time = 1 / frequency (TOV)
Time = 1 / .238
Time = 4.19
Obviously, this more time then you want. To create a 1 second overflow, you'll have to pre-load the timer with some value so it overflows faster than 4.19 seconds. Since it will take 4.19 seconds to count the full range to overflow (65,536), we can figure out how much time (at what time interval) each count takes place.
Time4EachCount = Time / MaxCountOfTimer
Time4EachCount = 4.19 / 65,536
Time4EachCount = .000064 or 64. us
You want a one second overflow so (1 sec / Time4EachCount) tells us that it will take 15,625 counts to equal 1 second. Let's subtract 15,625 from the MaxCount to tell us what our pre-load value should be.
PLoad = MaxCountOfTimer - 15,625
PLoad = 2^16 - 15,625
PLoad = 65,536 - 15,625
PLoad = 49,911 (Hex C2F7)
Ok, so now if you pre-load your timer with 49,911... there will be 15,625 counts left until overflow which will equate to the one second you desire. This probably seems like a whole lot to do in order to figure these numbers out (or at least I think so). Fortunately, there is a handy utility that does all of these calculations for you. It looks like this and it can be downloaded here.
Code: | ' MCU.......: AVR ATmega88-20AI
' Crystal...: 1 MHz
Led Alias Portd.1
Dim Blink As Bit
$regfile = "m88def.dat"
$crystal = 1000000
Config Portd = Output
Portd = 255
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Config Timer1 = Timer , Prescale = 64
TCNT1H = &HC2 : TCNT1L = &HF7
On Timer1 Timer1_isr
Enable Timer1
Enable Interrupts
Start Timer1
'
'------[ Blink ]----------------------------------------------------------------
'
Do
Led = Blink
Loop
'
'------[ Interrupt services routines ]-------------------------------------------
'
Timer1_isr:
Blink = Not Blink
Stop Timer1
TCNT1H = &HC2 : TCNT1L = &HF7
Start Timer1
Return
End
|
This second example uses the same timing calculations we performed above but operates the timer in "CTC" mode (clear timer on compare). This is the mode that you had attempted. Instead of pre-loading the timer with a count that leaves 15,625 left over, we will fill output compare registers with 15,625 (Hex 3D09) and set interrupts to occur on a compare match. We will also set the counter to clear itself upon match (so it will start over again from zero). Your method of setting TCCR1B.3 to clear the counter on compare was being undone by BASCOM when the counter was started.
Code: | ' MCU.......: AVR ATmega88-20AI
' Crystal...: 1 MHz
Led Alias Portd.1
Dim Blink As Bit
$regfile = "m88def.dat"
$crystal = 1000000
Config Portd = Output
Portd = 255
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1
Ocr1ah = &H3D : Ocr1al = &H09
On Compare1a Timer1_isr
Enable Compare1a
Enable Interrupts
Start Timer1
'
'------[ Blink ]----------------------------------------------------------------
'
Do
Led = Blink
Loop
'
'------[ Interrupt services routines ]-------------------------------------------
'
Timer1_isr:
Blink = Not Blink
Return
End |
In this example, we will attatch the output compare pin for Timer1 (OC1A) to the LED which you want to blink. We will tell Bascom to have Timer1 automatically toggle this pin on a compare match. The pin will automatically toggle at a 1Hz rate. This negates the need for an interrupt, interrupt service routine, port configuration and variable useage.
Code: | ' MCU.......: AVR ATmega88-20AI
' Crystal...: 1 MHz
$regfile = "M88def.dat"
$crystal = 1000000
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1 , Compare A = Toggle
Ocr1ah = &H3D : Ocr1al = &H09
Start Timer1
'
'------[ Blink ]----------------------------------------------------------------
'
Do
'do nothing... Timer1 will blink the LED using the OC1A pin (PortB.1 on the mega88)
Loop
'
'------[ Interrupt services routines ]-------------------------------------------
'
'none needed
End |
Finally, if none of these work for you then you need to search your datasheet for notes like this that I came across regarding the mega88...
Quote: | The PRTIM1 bit in ”Power Reduction Register - PRR” on page 40 must be written to zero to enable Timer/Counter1 module. |
|
|
Back to top |
|
 |
Christian Olsson
Joined: 08 Mar 2005 Posts: 9 Location: Sweden, Gothenburg

|
Posted: Mon Apr 04, 2005 8:20 pm Post subject: |
|
|
First and foremost thank you very much, I really learned a lot about timers.
I have read the datasheet and trying to write to the Power Reduction Register - PRR with (Prr.3 = 0) but it doesn't seem to work.
The portd.1 is constant low.
I don’t know if this is the right way to write to the register.
Code: |
Led Alias Portd.1
Dim twinkle As Bit
$regfile = "m88def.dat"
$crystal = 1000000
Config Portd = Output
Portd = 255
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1 : Stop Timer1
Ocr1ah = &H3D : Ocr1al = &H09
On Compare1a Timer1_isr
Enable Compare1a
Enable Interrupts
Start Timer1
Prr.3 = 0 '???
'
'------[ twinkle ]--------------------------------------------------------------
'
Do
Led = twinkle
Loop
'
'------[ Interrupt services routines ]------------------------------------------
'
Timer1_isr:
twinkle = Not twinkle
Return
End |
Blink = reserved BASCOM statement!
/Christian |
|
Back to top |
|
 |
DToolan
Joined: 14 Aug 2004 Posts: 1384 Location: Dallas / Fort Worth, Texas (USA)

|
Posted: Tue Apr 05, 2005 10:15 pm Post subject: |
|
|
Christian,
Yes, that is the right way to write the register. I've found though that the default state for the PRR register is all zeros (no power reductions enabled), so you probably won't need to change it. What you have been fighting is a Bascom bug and not some mis-coding or lack of knowledge on your part.
BASCOM is supposed to take the line, "Enable Compare1a" and with that it should set TIMSK1.1 (OCIE1A). Instead, it is mistakingly setting TIMSK0.1 (OCIE0A for the 8-bit timer/counter 0). It is also making the same mistake with "Enable Timer1" (setting TIMSK0.0 instead of the correct TIMSK1.0). The following should fix your problem until Mark corrects it (you might want to email him to let him know of the problem).
Code: | $regfile = "m88def.dat"
$crystal = 1000000
Led Alias Portd.1
Dim twinkle As Bit
Config Portd = Output
Portd = 255
'
'------[ Timer 1 ]--------------------------------------------------------------
'
Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1
Ocr1ah = &H3D : Ocr1al = &H09
On Compare1a Timer1_isr
'Enable Compare1a <-- Bascom bug for the mega88
SET TIMSK1.1 ' this is the output compareA interrupt enable bit for Timer1
Enable Interrupts
Start Timer1
'
'------[ twinkle ]--------------------------------------------------------------
'
Do
Led = twinkle
Loop
'
'------[ Interrupt services routines ]------------------------------------------
'
Timer1_isr:
twinkle = Not twinkle
Return
End |
|
|
Back to top |
|
 |
Christian Olsson
Joined: 08 Mar 2005 Posts: 9 Location: Sweden, Gothenburg

|
Posted: Thu Apr 07, 2005 6:01 pm Post subject: |
|
|
With a thing like that I could have fought for ever...
Now it works just fine, Thank you.
/Christian |
|
Back to top |
|
 |
RickB
Joined: 27 Jan 2005 Posts: 29 Location: Eugene, Oregon USA

|
Posted: Fri Apr 08, 2005 3:57 am Post subject: |
|
|
Which version(s) of Bascom is this bug in?
Rick |
|
Back to top |
|
 |
Christian Olsson
Joined: 08 Mar 2005 Posts: 9 Location: Sweden, Gothenburg

|
Posted: Fri Apr 08, 2005 5:07 pm Post subject: |
|
|
I am using BASCOM-AVR Compiler: Version 1.11.7.7
I don’t know if there is a bug in older versions.
The Mega88 is only a year old I think,
So for that reason BASCOM versions older then a year might not have support for Mega88.
/Christian |
|
Back to top |
|
 |
DToolan
Joined: 14 Aug 2004 Posts: 1384 Location: Dallas / Fort Worth, Texas (USA)

|
Posted: Fri Apr 08, 2005 11:04 pm Post subject: |
|
|
Because of the similarities between the mega48 and mega88, I figured this bug would also appear when $regfile = "m48def.dat" (and it does). Just a heads-up for anyone working with the mega48 as well. |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|