72 MHz dividing by 100 code

ted
Mon Jan 01, 2018 1:59 am
STM32F103 is running at 72 MHz I believe the simple code can divide it by 100 which will give 0.72 MHz PWM output on pin, for example PA6. Maybe someone know how to write such code ?


int outputPin = PA6; //output pin

void setup() {
// put your setup code here, to run once:
pinMode(outputPin, OUTPUT);
//or ? pinMode(out1, PWM);
Serial.begin(9600);
// ???
}

void loop() {
// put your main code here, to run repeatedly:

// 72 MHz dividing by 100 code ???

// Serial.println( ???);
// Serial.print (???); // print result of dividing, PWM on pin PA6
}


dannyf
Mon Jan 01, 2018 5:15 pm
the simple code

which simple code?

Maybe someone know how to write such code ?

one typical process would be to look up the datasheet and figure out how the clock division works.

another typical process would be to beg someone else to write it for you.



Pito
Tue Jan 02, 2018 8:38 am
For example (I doubt this will work at exactly 720kHz, however), tested:
HardwareTimer pwmtimer(3);

uint16_t maxduty, duty;
uint32_t myperiod, mypulse;

void setup() {
pwmtimer.pause();
myperiod = 20; // PWM period in useconds, 20 -> freq = 50KHz
maxduty = pwmtimer.setPeriod(myperiod);
pwmtimer.refresh();
pwmtimer.resume();
pinMode(PA7, PWM);
}

void loop() {
mypulse = 5; // 0<=mypulse<=period, this is my High pulse length in useconds
duty = map((int32_t)mypulse, 0, (int32_t)myperiod, 0, (int32_t)maxduty);
pwmWrite(PA7, duty); // 0<=duty<=maxduty
while(1){};
}


ted
Tue Jan 02, 2018 4:26 pm
What I should put in brackets serial ?


#include <SPI.h>
int outputPin = PA6; //output pin

void setup() {
// put your setup code here, to run once:
pinMode(outputPin, OUTPUT);
//or ? pinMode(out1, PWM);
Serial.begin(9600);
// ???
}

void loop() {

SPI.setClockDivider(SPI_CLOCK_DIV128);
Serial.println( ???);
// Serial.print (???); // print result of dividing, PWM on pin PA6
}

/*
SPI.setClockDivider(SPI_CLOCK_DIV16); // (72 MHz / 16 = 4.5MHz)
The SPI1 works on APB2 (72 MHz). The maximum frequency that works the SPI1 is 72/2 =36 MHZ.
The SPI2 works on APB1 (36 MHz). The maximum frequency that works the SPI2 is 36/2 =18 MHZ.

The available dividers are:
CODE: SELECT ALL
SPI_CLOCK_DIV2
SPI_CLOCK_DIV4
SPI_CLOCK_DIV8
SPI_CLOCK_DIV16
SPI_CLOCK_DIV32
SPI_CLOCK_DIV64
SPI_CLOCK_DIV128
SPI_CLOCK_DIV256

*/


ted
Tue Jan 02, 2018 4:35 pm
no tested – error
div_100_a:17: error: ‘period’ was not declared in this scope

duty = map((int32_t)mypulse, 0, (int32_t)period, 0, (int32_t)maxduty);

^

exit status 1
‘period’ was not declared in this scope


ted
Tue Jan 02, 2018 4:42 pm
You may try to access the timer registers directly to achieve faster results.
output on PA7 = 550 Hz

Pito
Tue Jan 02, 2018 4:54 pm
Updated the source – see above.
Also I’ve tested the first source and it works here on BluePill.
The second source under investigation.

ted
Tue Jan 02, 2018 5:05 pm
There is no reaction when I am changing the numbers in bracket


pwmtimer.setPrescaleFactor(4); // Timer input clock Prescaler = 1 (= 36MHz input ?)
pwmtimer.setOverflow(0.5); // PWM Period width for 720kHz ?


ted
Tue Jan 02, 2018 5:11 pm
Also I’ve tested the first source and it works here on BluePill.
When I am compiling first version I have mentioned error

stevestrong
Tue Jan 02, 2018 5:18 pm
You can only set integer values for the timer registers, so floats will not work.

ted
Tue Jan 02, 2018 5:22 pm
Version #1 is working after second time – copy and paste your code.
Frequency is 50 kHz, pulse with 25%.
I will play with numbers.
Big Thanks

ted
Tue Jan 02, 2018 5:33 pm
Updated version #2 is also working, output – 1.4MHz

Pito
Tue Jan 02, 2018 5:40 pm
I’ve updated the second source above again, and double-checked with my counter.
It seems the input clock is 72MHz and I need “100-1” to get exact 720kHz (720.045kHz here).. :lol:
98 = 727.319 kHz
99 = 720.045 kHz
100 = 712.916 kHz
101 = 705.927 kHz

ted
Tue Jan 02, 2018 5:46 pm
I changed numbers in those two lines = nice squares, 720 kHz, 50% duty.


pwmtimer.setOverflow(100); // PWM Period width for 720kHz ?
pwmtimer.setCompare(TIMER_CH2, 50); // PWM High Pulse width is 50% duty (1:1)pwmtimer.setOverflow(100); // PWM Period width for 720kHz ?
pwmtimer.setCompare(TIMER_CH2, 50); // PWM High Pulse width is 50% duty (1:1)


ted
Tue Jan 02, 2018 5:51 pm
I am just curious can I divide this again by 100 and get 7.2 kHz on pin PA6 ?

Pito
Tue Jan 02, 2018 5:58 pm
get 7.2 kHz on pin PA6 ?
Here you are Sir:
HardwareTimer pwmtimer(3);

void setup() {
pinMode(PA6, PWM);
pwmtimer.pause();
pwmtimer.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer.setOverflow(10000-1); // PWM Period width for 7200 Hz ?
pwmtimer.setCompare(TIMER_CH1, 5000); // PWM High Pulse width is 50% duty (1:1)
pwmtimer.refresh();
pwmtimer.resume();
}

void loop() {
}


ted
Tue Jan 02, 2018 6:00 pm
The second updated version is perfect

ted
Tue Jan 02, 2018 6:04 pm
Thanks
Can I have both frequencies, PA7 =720 kHz and PA6 = 7.2kHz ?

Pito
Tue Jan 02, 2018 6:06 pm
Yes, but PA7 = 720kHz and PA3 = 7,2kHz – just merge the above c-sources together – also read my previous post.
HardwareTimer pwmtimer3(3);
HardwareTimer pwmtimer2(2);

void setup() {
pinMode(PA7, PWM);
pwmtimer3.pause();
pwmtimer3.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer3.setOverflow(100-1); // PWM Period width for 720kHz ?
pwmtimer3.setCompare(TIMER_CH2, 50); // PWM High Pulse width is 50% duty (1:1)
pwmtimer3.refresh();
pwmtimer3.resume();

pinMode(PA3, PWM);
pwmtimer2.pause();
pwmtimer2.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer2.setOverflow(10000-1); // PWM Period width for 7,2kHz ?
pwmtimer2.setCompare(TIMER_CH4, 5000); // PWM High Pulse width is 50% duty (1:1)
pwmtimer2.refresh();
pwmtimer2.resume();
}

void loop() {
}


ted
Tue Jan 02, 2018 6:11 pm
i will try that
You may combine both to get 720k/7k on PA7/6.

ted
Tue Jan 02, 2018 6:12 pm
Thanks again

Pito
Tue Jan 02, 2018 6:20 pm
PA7/PA6 – nope, see my previous source..
You cannot combine Timer3 with 2 different pwm periods it seems.
You need two different timers as I have done above.. it works with PA7/PA3.. :)
See the TimerX/ChannelY allocation – PWM3/2 means Timer3->Channel2:
.

STM32 BLuePill PIN diagram.JPG
STM32 BLuePill PIN diagram.JPG (209.41 KiB) Viewed 338 times

ted
Tue Jan 02, 2018 6:42 pm
just merge the above c-sources together
I will try that.
The last your code, PA7 = OK, PA6 = no signal

Pito
Tue Jan 02, 2018 6:44 pm
The Merged sources: viewtopic.php?f=19&t=3037&start=10#p39347
Also read my above posts..
HTH

ted
Tue Jan 02, 2018 6:46 pm
So I can pick up PWM2 ?

ted
Tue Jan 02, 2018 7:12 pm
The Merged sources:
Is working perfect, I have 720 kHz and 7.2 kHz.
Thanks
Now I will take a close look to understand completely how this is working.

Pito
Tue Jan 02, 2018 7:17 pm
Look at the picture with PWM pin’s allocations, and simply pick up the Timer and the Channel for the specific pin you want to use.
Some PWM TimerX/ChannelY pins are doubled – that means they can be remapped by sw.

ted
Tue Jan 02, 2018 7:23 pm
Of Course, I think I can do that.
There are nice people on the forum, just hard is to meet them.

ted
Tue Jan 02, 2018 8:38 pm
The timer has 4 PWM outputs;
1. For square wave we can use HIGH/LOW on pin instead PWM ?
2. One of PWM can generate sine wave on additional pin?

ted
Wed Jan 03, 2018 5:17 am
I have disabled two lines and program is running ok, will this cause the problems ?

// Use timer 2
HardwareTimer pwmtimer2(2);

void setup() {
pinMode(PA3, PWM);
// pwmtimer2.pause();
pwmtimer2.setPrescaleFactor(100); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer2.setOverflow(100-1); // PWM Period width for 7,2kHz ?
pwmtimer2.setCompare(TIMER_CH4, 50); // PWM High Pulse width is 50% duty (1:1)
// pwmtimer2.refresh();
pwmtimer2.resume();

}

void loop() {

}


stevestrong
Wed Jan 03, 2018 9:40 am
Why have you disabled those lines? Do you have problems if you do so?
If not, I would recommend to leave those lines enabled, in case you wish to use the same sequence in other context they may be important.

ted
Wed Jan 03, 2018 1:03 pm
No reason for disabling, I was learning what each line is doing. I very happy with this program and thank you for helping me. Now I am understanding PWM 95%
Will disabling those lines make microcontroller less busy ?
I guess not much.

stevestrong
Wed Jan 03, 2018 3:23 pm
Those lines will be called once in the setup phase, so they will not reserve any further MCU resources.

ted
Wed Jan 03, 2018 5:35 pm
After pointing, I looked at the program and I see that it is obvious.

Pito
Wed Jan 03, 2018 5:46 pm
Unless you start to modulate the PWM with your data.. :)

ted
Wed Jan 03, 2018 7:41 pm
i didn’t think about it, again thanks for mentioning that.
what is your image – aged sculpture ?

ted
Wed Jan 03, 2018 8:10 pm
So I can modulate PWM by sine wave, but how ?

ted
Wed Jan 03, 2018 9:08 pm
Which one I should choose ?

#1
function y = sin3(x)
n = 1 : 1000;
for i = 1 : length(x)
y(i) = x(i).*prod(1 - x(i)^2 ./ (n*pi).^2);
end


mrburnette
Thu Jan 04, 2018 3:58 pm
[ted – Wed Jan 03, 2018 1:03 pm] –
<…>
Will disabling those lines make microcontroller less busy ?
I guess not much.

There is a danger to my not responding to this statement as it may be read and interpreted by a non-hardware user as meaning that within the uC, disabling peripheral interfaces will/would make the uC run faster. This is not the case.

If one studies the STM32 architecture document, one will note that the microcontroller has internal buses that connect various subsystems. Disabling a subsystem “may” reduce the chip power usage, but generally subsystems that are not utilized are not initialized and configured, so power dissipation of non-used peripherals should be minimal.

What does make a microcontroller “busy” is the start-up/initialization code and then user code that exercises the various peripheral activities. Some peripheral devices such as PWM consume bandwidth when they are configured but afterward do not consume any user execution time unless something is changed by user code. Of course, when PWM is active, electrical power is consumed because that device is active and clocking to an output pin.

Image


ted
Thu Jan 04, 2018 5:29 pm
Thank You Very much for explanation, it is very helpful.

ted
Wed Feb 28, 2018 8:02 am
Why I can’t get signal on PB4 but only on PA6, both of them are PWM 3/1 ? The same with another pins , PA7, PA5 and so on no signal except PA6.

/*
HardwareTimer pwmtimer(3);

void setup() {
pinMode(PA6, PWM);
pwmtimer.pause();
pwmtimer.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer.setOverflow(10000-1); // PWM Period width for 7200 Hz ?
pwmtimer.setCompare(TIMER_CH1, 5000); // PWM High Pulse width is 50% duty (1:1)
pwmtimer.refresh();
pwmtimer.resume();
}

void loop() {
}
*/
HardwareTimer pwmtimer(3);

void setup() {
pinMode(PB4, PWM);
pwmtimer.pause();
pwmtimer.setPrescaleFactor(1); // Timer input clock Prescaler = 1 (= 72MHz input ?)
pwmtimer.setOverflow(10000-1); // PWM Period width for 7200 Hz ?
pwmtimer.setCompare(TIMER_CH1, 5000); // PWM High Pulse width is 50% duty (1:1)
pwmtimer.refresh();
pwmtimer.resume();
}

void loop() {
}


fpiSTM
Wed Feb 28, 2018 10:49 am
PA5 has no timer.
PA7 uses the Timer 3 with Channel 2
PB4 uses the Timer 3 with channel 1 but it’s an alternate function (AFIO_TIM3_PARTIAL). you have to ensure the AF is set properly.

Probably you could try adding:
afio_remap(AFIO_REMAP_TIM3_PARTIAL);


mrburnette
Wed Feb 28, 2018 1:25 pm
Opinion:

Anyone hoping to be successful working with timers need to be familiar with the specific STM32 Reference Manual. Yes, it is a big PDF but it is also the bible for any aspiring engineer. Beyond the PDF, there are many smaller dissertations which will help provide some glue knowledge to help in understanding the details around timers. All commonly available references can be found with only a single Google query.

To everyone posting in the forum… THINK BEFORE YOU POST
In reviewing this thread, the Op has done what many of us do from time-to-time; that is, posted and then gone back and deleted a post.
In this case, several posts were deleted in sequence. A thread should be continuous in thought and response and deletes, especially multiple deletes, leaves the thread discontinuous and hard to follow. DO NOT DO THIS… If you must edit a prior post, then at least strike-through like this the old or add some key to let the reader know that the text was time-shifted, edited, amended, etc. Everyone is responsible for being a good citizen in the forum, so think before you post.

Image

Ray
(Global Moderator)


ted
Wed Feb 28, 2018 7:52 pm
Here is the drawing clarifying my question – why A is not equal B .
fpiSTM – thanks for your suggestions, it not working yet, but is it some point to start.

RogerClark
Thu Mar 01, 2018 7:13 am
Note.

Posts cant actually be deleted, the system just hides them.

Ray. does moderator privileges allow you to show them again, if not I’ll see if I can change the settings


fpiSTM
Thu Mar 01, 2018 8:14 am
It probably could be a new subject.
As Ray mentioned, I think you should read the data sheet and do some search about Alternate function.
http://www.st.com/content/ccc/resource/ … 171190.pdf

See §9 General-purpose and alternate-function I/Os (GPIOs and AFIOs)

A GPIO pin can have several functions but not at the same time. Up to you to configure it depending of your need.

Software remapping of I/O alternate functions
To optimize the number of peripheral I/O functions for different device packages, it is possible to remap some alternate functions to some other pins. This is achieved by software, by programming the corresponding registers (refer to AFIO registers. In that case, the alternate functions are no longer
mapped to their original assignations


ted
Thu Mar 01, 2018 10:45 am
I committed a crime deleting my own post.

ted
Tue Mar 27, 2018 3:31 pm
Pito
Can you help me to add a sine wave output to your code, maybe by combining A and B codes ?
Code A

HardwareTimer pwmtimer2(2);
void setup() {
pinMode(PA3, PWM);
pwmtimer2.pause();
pwmtimer2.setPrescaleFactor(10);
pwmtimer2.setOverflow(1000-1);
pwmtimer2.setCompare(TIMER_CH4, 500);
pwmtimer2.refresh();
pwmtimer2.resume();
}

victor_pv
Tue Mar 27, 2018 5:42 pm
[ted – Wed Feb 28, 2018 7:52 pm] –
Here is the drawing clarifying my question – why A is not equal B .
fpiSTM – thanks for your suggestions, it not working yet, but is it some point to start.

Those are alternate pins. The MCU allows you so select if a peripheral uses one pin OR another pin, but you can’t use 2 pins at the same time for the same function. It’s alternate, one or the other.
all that is in the reference manual, it’s long, but you should read thru it to understand the peripherals. No amount of QA in the forum will cover what the reference manual can teach you.
Furthermore, you can’t do a sine wave with PWM. The times can output 0 or 1, low or high, but not an analogous signal. You need a DAC for that, and the bluepill MCU doesn’t have a DAC, so no sine wave.


ted
Tue Mar 27, 2018 11:19 pm
I don’t need DAC, PWM and filter it is enough, all sine waves microcontrollers are using this method

Leave a Reply

Your email address will not be published. Required fields are marked *