setting counter values in PIT hardware - timer

A PC typically has a special chip called a programmable interval timer
(PIT). The input clock frequency of the PIT chip runs (roughly) at
1.193182 MHz, which is 1/12 the frequency of a
14.31818 MHz oscillator.
Each PIT channel is associated with a hardware counter (divider). Let
us use Counter0 to refer to the counter associated with channel 0.
Every pulse from the PIT input clock causes Counter0 to be decreased.
When Counter0 has reached zero, it is reset and a pulse is generated
on the output. The hardware timer frequency can be changed by setting
Counter0 to a desired value. For instance, if Counter0 is set to
11,931,then the PIT channel 0 output frequency is 100 Hz, and timer
interrupt occurs every 10 ms.
My question is how we can calculate counter0 value?
In this example how author calculated frequency as 100 Hz and timer interrupt occurs every 10 msec by setting counter value to 11931.
Request your help in understanding.

Related

Can I change OCR1B on the fly?

I want to solve a very particular problem with an Arduino, running on a ATmega328
I have timer1 run in fast PWM mode for generating a PWM Signal with given Period an duty cycle. The duty cycle is set by OCR1A: So at timer restart the level of the output pin gets high and after the duty period it gets low. This works.
Additionally I want to carry out an analog measurement exactly some time after the rising signal. So I enabled the OCR1B interrupt and define the time by writing to OCR1B. When the timer reaches the value in OCR1B the interrupt handler is invoked and the measurement done. This works.
Now I want to do this ADC conversion twice at different counter times, say my_OCRB1 and my_OCRB2. But there is only on OCR1B Register I can use. Is it ok to prepare the content of OCR1B to the next value my_OCRB2 after the first ADC conversion at is finished? Will it work and again rise an interrupt, when the timer is still counting up?
Is there a better solution?

Generate a fixed number of pulses on the STM32F4 PWM

I am trying to control a servo motor (link). It is a brushless DC motor with an interface similar to a stepper motor.
The motor rotates for a defined distance based on the number of pulses it receives from the PWM. The speed is determined by the pulse frequency of the PWM, like a stepper motor.
To control this motor I am using a microcontroller STM32F407ZET6. I can easily change the frequency and Duty Cycle of PWM, but my doubt is the following:
How do I generate a fixed number of pulses in the PWM? For example, I want the PWM to send 1000 pulses at a certain time with a frequency of 20KHz and a Duty Cycle of 50%. 20KHz and 50% Duty Cycle are easy to define, but I can't determine how to generate the 1000 fixed pulses.
One of the solutions I tried was to connect the PWM back to a timer in counter mode and stop the PWM when the required number of pulses has been generated. But the number of pulses is not always fixed, sometimes ranging from 998 to 1005 (for example).
Is it possible to do this without the need for feedback?
Simpest way:
UG interrupt = count cycles. After n cycles disable the timer.
In the memory create a buffer with the timer register values and use timer burst mode.
Configure DMA mem-mem with n cycles same source and destination address. After n cycles end of transaction interrupt will be generated - disable the timer.
Use slave timer counting when the PWM is updating (overflowing). Set the overflow interrupt and disable the PWM timer.
many other methods.
This can be easily achieved by combining the so called "One-pulse mode" (reference manual page 551) with the repetition counter (page 529). All you've got to do is enabling this mode (OPM bit in CR1), set the repetition counter (RCR) and start the timer. IIRC you also have to force an update event in order to get RCR loaded. The reference manual will have more information on that.

ARMv7 stm32-L476G How to set a specific pitch of sound to play for a specific duration

I am new to ARMv7 assembly programming (using the stm32-L476G) and I am lost on how to produce a specific-pitched sound (e.g 110 hz) to play for 15 seconds. I have done my research and reached a dead end. Can anybody help me?
method A
Configure the timer to generate 110Hz PWM 50% signal.
Configure another timer to overflow after 15 seconds.
In the second timer interrupt deactivate the PWM signal generation by the first timer
method B
1 configure the timer to overflow every 1/220 sec.
In the timer interrupt toggle the pin
count the number the interrupts when the number reaches the 220*15 disable timer
method C
1 create the sine tabue table in the memory.
confiure the timer to trigger DMA transfer to DAC every
1/(110*nsamples_per_period)
configure DMA in the circular mode
in the DMA end transfer interrupt increase the counter
when the counter is >= 110*15 disable the triggering timer

How to set frequency and duty cycle of Timer1 in 16bit P&F correct PWM

I am using a 328P (Running on the internal 8mhz) to generate a Square wave at around 111K hz or 120K hz with and adjustable duty cycle.
I'm fairly new to doing this level of hardware manipulation so please excuse my ignorance, I spent 3 days looking online and in the datasheet but I'm afraid my understanding of what the acronyms and abbreviations mean is still too limited.
So far I have come up with the following code after doing the research online and in the datasheet. But I feel like I'm missing something, What register manipulates frequency and what register manipulates duty cycle in (Datasheet 20.12.5) Phase and Frequency Correct PWM Mode?
void setup(){
DDRB |= (1 << DDB1); //Set PB1 as output
OCR1A = (Unsure of what TOP should be here);
TCCR1A = (1 << WGM10) | (1 << COM1B0) | (1 << COM1A0);
TCCR1B = (1 << CS10) | (1 << WGM13);
}
void loop(){
//manipulate duty cycle with other code here
}
What am I missing or what should I be doing differently here?
I tried to use the online AVR Timer Calc to help me get clock ticks needed for that frequency. It says a total of 72 Timer ticks with no prescaler and 16 bit timer would yield a 111Khz (approximate) Square wave. Jumping to 73 or 71 jumps the frequency too much out of the desired range. is there any way to get that closer on an AVR?
After a lot of research along side a friend of mine who is also an EE and works with embedded systems we came to find the best solution for getting what I needed out of the 328p. I will post the solution below for anyone who is interested and needs something similar.
void setup() {
// put your setup code here, to run once:
//Set Timer1 for around 109Khz signal
cli();//stop interrupts
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
//Set register bits
TCCR1A = _BV(COM1A1) | _BV(WGM11);
TCCR1B = _BV(CS10) | _BV(WGM12) | _BV(WGM13);
ICR1 = 73; // frequency = 8000000/73 = 109.589 kHz
OCR1A = 0; //0% Duty Cycle or Full Off.
sei();//allow interrupts
}
void loop() {
// put your main code here, to run repeatedly:
OCR1A = 36; //50% Duty Cycle 73/2 = 36.5 Can be changed as needed.
}
This code sets the registers for Timer 1 so it shouldn't interfere with millis or other timing functions in the Arduino libraries. I needed to manipulate a specific pin anyways and PB1 (OC1A) (or Arduino digital pin 9) is the pin that this will oscillate.
You can change ICR1 to any value you need based on some simple math,
Your clock frequency divided by the value of the counter equals the approximate frequency produced. OCR1A sets the duty cycle of the signal.
You are limited in the exact frequency but for my needs this worked out OK.
I was still able to use it to drive the transducer I was using.
This was a quick answer to the initial problem and allows me to change the duty cycle as a bonus. I don't remember the exact information on the registers we set, When I have time I will update this answer with the info from the data sheet pertaining to that.
In the title, you asked "ATMega328P How to set TIMER1 PWM Frequency". You tune the frequency by setting the TOP value to what you want it to be. A smaller TOP value means the counter reaches TOP sooner, so the frequency is higher. The prescaler and clock source you use for the timer determines how fast it counts up, so that also affects the frequency, what ranges of frequencies are possible, and the resolution you get for setting the frequency. Your TOP value also determines how much resolution you have when setting the duty cycle, since the duty cycle should be an integer less than or equal to TOP.
Near the bottom of your post, you asked "is there any way to get that closer on an AVR?" Since your AVR is running at 8 MHz, every frequency you can generate with its timers will be of the form (8 MHz)/N, where N is some integer. That's because the timers can't do anything or change anything between ticks of the clock source you are supplying to them. Timer 1 will get a clock tick 8 times per microsecond, and each time that clock tick happens it can advance its count and/or control a PWM pin and/or fire an interrupt. I think you already figured this out using the online AVR timer calculator. Here are some of the achievable PWM frequencies you can get on an AVR running at 8 MHz:
8000 kHz / 73 = 109.6 kHz
8000 kHz / 72 = 111.1 kHz
8000 kHz / 71 = 112.7 kHz
If you need more precise frequency tuning, you need to get a faster clock source in your system one way or another. You could get a faster microcontroller or maybe figure out how to supply a faster clock as an input to a timer on the microcontroller.

STM32 - How to trigger interrupt after a certain PWM ON time?

I'm new to ARM MCUs (STM32F411), and I have been trying to find my way around the peripherals using STM's HAL library and STM32Cube.
I've already configured my board in order to use some peripherals:
Timer 2 for running an interrupt with a certain frequency
Timer 3 for running PWMs on 3 channels of it.
ADC with 4 channels, into DMA mode, for reading some analog input.
Let us suppose, now, that the PWM's whole period is 100 ms and its duty cycle is 50% (50 ms PWM on and 50 ms PWM off).
I would like to trigger an interrupt after a certain time of the PWM on level, let us say 50% of it.
Hence, I would like to run an interrupt at 25 ms in order to use the ADC for sampling it's analog inputs.
Do you have any suggestion on how could I implement such a kind of interrupt?
Thank you in advance for your help!
Since the ADC of the STM32F411 is used in Regular mode (not Injected mode) and only three channels out of four are used to generate PWM on Timer 3, the fourth channel can be used to trigger the ADC.
Hence Timer 3 is configured as follows:
CH1 used for Output Compare mode 0 (TIM3->CCMR1.OC1M = 0)
CH2, CH3, CH4 used for PWM outputs
Therefore TIM3->CCR1 is loaded to a value that gives 25% of duty, then it will generate TIM3_CH1 events that can be used to trigger ADC start-of-conversion at 25% of your TIM3 timebase.

Resources