Help achieving a low freq. pwm signal using assembly

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm wanting to generate two pwm signals (125Hz @ 25% Duty Cycle) and (250Hz @ 25% Duty Cycle) continuously on two pins in a assembly program. I'm having trouble figuring out the prescaler I need to achieve these low frequencies and the values needed to set the OCRx register for my duty cycle. I've been trying to run some calculations using the following formula but I can't seem to achieve 125Hz with any of the prescalers listed in the datasheet for the timers (8,64,256,1024). I have a 16MHz external clock coming into my 328P chip. Am I going about determining these values the wrong way? How do I solve for these values to set the registers for the timers? Also do I need to be careful about which pins I choose if I want pwm signals emitting continuously at the same time from two pins?  

 

Frequency I need = Freq_Osc / 256*N

N = Presacler

Freq_Osc = Frequency of Oscillator or External Clock in my case

 

 

 

 

This topic has a solution.

~regnar86

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your spec's don't make sense. 

 

First, you will not easily get two different output frequencies from a single timer. Normally, you would get 125Hz from one and 250Hz from a different timer.

 

At that low a frequency, it may be easier to do it in software. Just make "ticks" from a timer overflow at 1ms. I suggest 1ms because 250Hz has a period of 4ms and a 250Hz signal with 25% on time is on for 1ms. Then, that on is on for 1 tick and off for 3. Your 125Hz is simply on for 2 ticks and off for 6. As long as you don't need edges to be perfectly coincident, software will do just fine.

 

Then, your problem is to figure out how to make a timer to generate 1ms / 1KHz overflow events.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I follow you. Can you answer one more question...

 

Can I use separate prescalers for the timers? I've read several tutorials on this but I'm somewhat confused. I know that I can use a prescaler to step down the frequency for the actual External Clock to the CPU. Like for example since my chip is being supplied a 16MHz signal from an external clock I know I can step this down via commands in my program (1,2,4,8,16,32,64,128,256). However, I'm confused about prescalers for the timers "counters". Am I able to prescale the timers as well separately without altering the External Clock going into the CPU. I know in my datasheet in the section Timer/Counter0 and Timer/Counter1 prescalers under External Clock it says I cannot use prescalers. I'm attaching a screenshot of that. Therefore, from reading all this i'm confused. Can you provide some clarity. 

 

Attachment(s): 

~regnar86

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can use different taps from the prescaler, but on the 328P TIMER0 and TIMER1 share the same prescaler.

 

The reference to external clock in the datasheet section on timers refers to the external clock you can apply to T0 and T1 to clock TIMER0 and TIMER1.  When selecting the external clock for a given timer, you cannot prescale that clock.  Indeed, selecting the external clock input for a timer bypasses the timer's prescaler altogether.  However these external clocks (T0, T1) are not the external system clock you would apply to XTAL1 to clock the entire device.

 

 

 

Note how the multiplexer for TIMER0 uses the 3 bits in CS0[2:0] to select one of 8 clock sources.  The first source is permanently low ('0'), which keeps the timer stopped.  The second source is the I/O clock (same frequency and phase as the CPU clock) and runs the timer without any prescaler.  The next 4 sources are the various taps from the prescaler common to TIMER0 and TIMER1.  The last 2 sources come from the external clock on the T0 pin.  One is inverted w.r.t. to the other, so one acts as a rising-edge trigger while the other acts as a falling-edge trigger.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Jan 27, 2015 - 02:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try this:

// F_CPU = 16 MHz
.include "m328pdef.inc"
.include "macros.inc"  ; setb , store


.org 0
jmp start

start:
      ;init ports
      sbi   DDRB, PB1        ;OC1A 
      sbi   DDRB, PD3        ;OC2B  

      ;init timer1
      ;set mode 14, fast pwm, TOP=ICR1
      setb   TCCR1A, WGM11, r16
      setb   TCCR1B, WGM12, r16
      setb   TCCR1B, WGM13, r16
      
      ;prescaler 8
      setb   TCCR1B, CS11, r16    

      ;non-inverting output OC1A
      setb   TCCR1A, COM1A1, r16

      ;set pwm freq to 125 Hz
      ;ICR1 = (F_CPU    / (freq * prescaler)) - 1
      ;ICR1 = (16000000 / (125  * 8))         - 1 = 15999
      ldi   r16, high(16000) 
      store ICR1H, r16
      ldi   r16, low(16000) 
      store ICR1L, r16

      ;set duty 25%
      ;OCR1A = ICR1 * 0.25 = 4000
      ldi   r16, high(4000) 
      store OCR1AH, r16
      ldi   r16, low(4000) 
      store OCR1AL, r16
      

;SIMILARY TIMER2:

      ;set mode 7, fast pwm, TOP=OCR2A
         ;code
      ;prescaler 256
         ;code
      ;non-inverting output OC2B
         ;code
      
      ;set pwm freq to 250 Hz
      ;OCR2A = (F_CPU / (freq * prescaler)) - 1
      ldi   r16, 249
      store OCR2A, r16   
      
      ;duty = 25%
      ldi   r16, 249 * 25/100
      store OCR2B, r16   
      
main:
      jmp main

 

Attachment(s): 

Last Edited: Tue. Jan 27, 2015 - 09:11 AM