Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Problem with Timer 1 and mega88

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive
View previous topic :: View next topic  
Author Message
Christian Olsson

Bascom Member



Joined: 08 Mar 2005
Posts: 9
Location: Sweden, Gothenburg

sweden.gif
PostPosted: Mon Mar 21, 2005 7:52 pm    Post subject: Problem with Timer 1 and mega88 Reply with quote

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
View user's profile
DToolan

Bascom Member



Joined: 14 Aug 2004
Posts: 1384
Location: Dallas / Fort Worth, Texas (USA)

blank.gif
PostPosted: Thu Mar 31, 2005 12:18 am    Post subject: Reply with quote

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
View user's profile Yahoo Messenger
Christian Olsson

Bascom Member



Joined: 08 Mar 2005
Posts: 9
Location: Sweden, Gothenburg

sweden.gif
PostPosted: Mon Apr 04, 2005 8:20 pm    Post subject: Reply with quote

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
View user's profile
DToolan

Bascom Member



Joined: 14 Aug 2004
Posts: 1384
Location: Dallas / Fort Worth, Texas (USA)

blank.gif
PostPosted: Tue Apr 05, 2005 10:15 pm    Post subject: Reply with quote

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
View user's profile Yahoo Messenger
Christian Olsson

Bascom Member



Joined: 08 Mar 2005
Posts: 9
Location: Sweden, Gothenburg

sweden.gif
PostPosted: Thu Apr 07, 2005 6:01 pm    Post subject: Reply with quote

With a thing like that I could have fought for ever...
Now it works just fine, Thank you.
/Christian
Back to top
View user's profile
RickB

Bascom Member



Joined: 27 Jan 2005
Posts: 29
Location: Eugene, Oregon USA

blank.gif
PostPosted: Fri Apr 08, 2005 3:57 am    Post subject: Reply with quote

Which version(s) of Bascom is this bug in?

Rick
Back to top
View user's profile
Christian Olsson

Bascom Member



Joined: 08 Mar 2005
Posts: 9
Location: Sweden, Gothenburg

sweden.gif
PostPosted: Fri Apr 08, 2005 5:07 pm    Post subject: Reply with quote

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
View user's profile
DToolan

Bascom Member



Joined: 14 Aug 2004
Posts: 1384
Location: Dallas / Fort Worth, Texas (USA)

blank.gif
PostPosted: Fri Apr 08, 2005 11:04 pm    Post subject: Reply with quote

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
View user's profile Yahoo Messenger
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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