Go Down

Topic: Timers  (Read 1 time) previous topic - next topic

ted


Can someone help me to understanding this code lines ?

Code: [Select]




  // Set up timer 1.
  // Prescaler = 1, phase correct PWM mode, TOP = ICR1A
/* TCCR1A = (1 << COM1A1) | (1 << WGM11);
  TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10);    // CTC mode, prescaler = 1
  TCCR1C = 0;
  OCR1AH = (TIMER1_TOP/2 >> 8);
  OCR1AL = (TIMER1_TOP/2 & 0xFF);
  ICR1H = (TIMER1_TOP >> 8);
  ICR1L = (TIMER1_TOP & 0xFF);
  TCNT1H = 0;
  TCNT1L = 0;
  TIFR1 = 0x07;      // clear any pending interrupt
  TIMSK1 = (1 << TOIE1); */



MartinL

#1
Jan 15, 2018, 01:22 pm Last Edit: Jan 15, 2018, 01:33 pm by MartinL
Hi ted,

First of all, this is timer code for the Arduino Mega, not the Due.

The code doesn't appear to match the comments. The comments mention "phase correct PWM mode" and "CTC mode", but the code is actually setting up timer 1 for fast PWM mode, (WGM11, WGM12 and WGM13 set to 1).

Fast PWM mode allows for frequency controllable, single slope PWM.

In fast mode the timer counts from 0 to the value in the ICR1 register. When the timer (TCNT1) reaches the ICR1 value, the timer overflows and is reset back to 0. The value of the ICR1 register and the prescaler allow the frequency of the PWM signal to be selected, such that:

PWM Frequency = 16MHz / (prescaler value * (ICR1 + 1))

Setting the COM1Ax bit to 1 causes the output to go high at the start of the timer period, until the timer (TCNT1) matches the compare register OCR1A. When the match occurs the output is cleared to 0 for the remainder of the period. At the end of the period, when the timer overflows the output returns high oncemore. This sets up a non-inverting output.

The TIFR1 (interrupt flag register) overflow and compare bits have been set, to clear interrupt overflow and compare interrupt flags. The TIMSK1 enables the overflow interrupts on timer 1.

Note that it's not necessary to load the ICR and OCR1A register high and low bytes separately. You can just use OCR1A and ICR1 and load them with a 16-bit value instead.

For more information see Atmega2560 datasheet section 17. 16-bit Timer/Counter (Timer/Counter 1, 3, 4 & 5).

ted

Thanks for explanation, how do you recognise that is not a Due ?

MartinL

Quote
hanks for explanation, how do you recognise that is not a Due ?
I mentioned that the code is from the Arduino Mega, although actually it could be from any of the 8-bit AVR microcontrollers.

The AVR based Mega and ARM based Due however use very different microcontrollers, consequently the underlying registers are also different and are specific to each device.

The registers in your example code are found on the AVR microcontrollers, used on the Uno, Micro, Mega etc...

MartinL

Are you using the Arduino Due?

What are type of PWM signal do you need to generate?

ted

#5
Jan 15, 2018, 04:28 pm Last Edit: Jan 15, 2018, 04:32 pm by ted
I ordered MEGA328P for arrive I have to wait, I Have a blue pill stm32 which is ARM.
When I look at timer code it is totally different language from  Mega, they are using DMA.
The question is: can stm32 use the same language as in my sample post #0?
I need to generate 700kHz PWM which can be modulated by signal applied to analoge input pin.

Thanks for any explanation I appreciate that, especially that is it hard to find answers which I have.

MartinL

Hi ted,

Quote
The question is: can stm32 use the same language as in my sample post #0?
Unfortunately it's not possible. The issue with register level programming is that it's often unique to the particular microcontroller you're using, as is the case with the STM32.

The other problem is that 700kHz PWM is very fast with respect to the Atmega328P's 16MHz processor clock. This won't give you much in the way of PWM signal resolution, as the (16MHz) processor clock beats only 22 times between the start of each (700kHz) timer period.

ted

I have a sine wave generator 7kHz program for stm32 - 72MHz processor clock, with sampling rate 100 = 720kHz . for amplitude 100 samples and  for phase 100 samples per period  = 10 000 total samples, 72MHz/10000 = 7.2kHz, for PWM modulation I dont need phase sampling, so for 16MHz processor clock will be 16/100= 160kHz. If my calculations are corect I need not 700kHz but 160kHz PWM frequency.

MartinL

#8
Jan 16, 2018, 09:31 am Last Edit: Jan 16, 2018, 09:38 am by MartinL
Hi ted,

Ok, here's the code to get 160kHz (fast) PWM output on digital pin D9, on the Arduino Uno (Atmega328P):

Code: [Select]
// Output 160kHz single slope (fast) PWM on digital pin D9 (Arduino Uno)

void setup() {   
  pinMode(9, OUTPUT);                                      // Set digital pin 9 as an output
 
  // Initialise timer 1 for single slope (fast) PWM, non-inverting output
  TCCR1A = _BV(WGM11) | _BV(COM1A1);                       // Enable the non-inverting PWM output OCR1A on digital pin 9   
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);            // Set up fast PWM and prescaler of 1 on timer 1 
  ICR1 = 99;                                               // Set the timer 1 PWM frequency to 160kHz
  OCR1A = 50;                                              // Set the PWM duty cycle to 50% (between 0 and 99)   
  //TIMSK1 |= _BV(TOIE1);                                  // Enable the timer 1 overflow (OVF) interrupt
}

void loop() {}

ISR(TIMER1_OVF_vect){
  // Optional overflow interrupt code here...
}

ted

Thank You for giving me a lot of info, it is helping to understand the times..
Thank you for 160 kHz code, to testing it I need to wait for ordered board.
I have a question: it is hard to convert my code post #0 to work with STM32f103 ?


ted

Thanks , great video the second half is it what I was looking for.

Go Up