Pulse width modulation (PWM) is an analog modulation technique in which the duration or width of a pulse varies over time. It is a commonly used technique for generating a continuous pulse signal with a defined frequency and duty cycle. Simply put, PWM changes the width of the pulse while keeping the frequency constant.
Using PWM signals, you can easily control the speed of a servo motor or the brightness of an LED. Since general purpose microcontrollers can only provide logic 1 (high) or logic 0 (low) on their output pins, they cannot provide varying analog voltages unless it has a built-in digital-to-analog converter (DAC) or an external connection . In this case, the microcontroller can be programmed to output pulse width modulation (PWM) with different duty cycles, which can then be converted to different analog voltages.
So, in this tutorial, we will interface the LED with a universal STM8S microcontroller which is controlled using PWM signals generated by the microcontroller, we will program the microcontroller using STVD and Cosmic C compiler. Before that, let's understand some basics of PWM signals.
Understand the basics of PWM signals
As you may have heard, PWM stands for Pulse Width Modulation. It is an analog modulation technique used in a large number of different applications and projects. An image of the PWM signal is shown below.
The image you see above is a generic square wave with the same ON time and OFF time. Now, assume that the total period of the square wave is 1 second, which means that the square wave's on time and the square wave's off time are also 500 milliseconds. So if we connect an LED and power it with this square wave, the LED will be on for half a cycle and off for half a cycle. It looks like the LED is glowing at half brightness.
In the picture above, you can see that we have reduced the duty cycle, if we consider the same 1S period, our On-TIme is 250ms and our OFF time is 750ms. Now, if we connect the same LED, we will observe that the LED becomes dimmer as the duty cycle decreases.
STM8S PWM generator circuit: hardware setup and requirements
Since we use PWM to control the LED, we need an LED connected to the STM8S board. Since the STM8S development board has LEDs, I will use it for demonstration. We also need the STM8S development board and ST-LINK programmer. In addition to this we will need a 5V power supply to power the board as the board has an onboard micro USB cable which we will use to power the board.
LED dimmer circuit diagram based on STM8S microcontroller
To program the circuit, we connected the ST-Link V2 programmer to the 3.3V, SWIM and GROUND pins of the STM8S development board. The most interesting thing about the STM8 microcontroller is that it only requires one SWIM pin to program the microcontroller.
As you can see in the schematic above, the test LED is connected to the development board and is connected to port 1.4 on the far left side of the board
PWM pins on ST Micro STM8S microcontroller
STM8S has 20 pins, 8 of which can be configured as PWM. The image below shows the PWM pins marked in red boxes. These pins are also GPIO pins that can be used for other functions.
As we can see in the above image, the labeled pins can generate PWM signals. So we will use one of the ones on the board to generate the PWM signal. However, enabling PWM disables other features, so we need to be careful about which pin we configure as PWM. Since we are building this circuit for online demonstration, we will use PIN D4 to generate the PWM signal.
Programming an STM8s microcontroller to generate PWM signals
Create a workspace and new project as we discussed in our Getting Started with STM8S Microcontrollers tutorial. You can add all header and source files, or just the gpio, TImer2, config and stm8s files. Open the main.c file and start writing the program.
Make sure you have included the header file as shown above. Open the main.c file and start the code. The complete main.c code can be found at the bottom of this page, where you can also download the project file. The code is explained below, if you are confused about the coding part you can also refer to the SPL User Manual or the video linked at the bottom of this page.
Before we start the coding process, you need to include stm8s_gpio.c, stm8s_TIm2.c and in the source and header folders you need to include stm8s_gpio.h, stm8s_TIm2. H. You can get these header files from the STM8S103F3P6 SPL GitHub Repository. Once completed, we start our code by including all required libraries and defining all necessary variables. For this lab code, we just need to save the PWM value in a variable, which is why we include a variable called pwm_duty.
#Include "STM8S.h" signed int pwm_duty = 0;
Once we have declared all libraries and variables, we need to build our defer function as cosmic c compiler does not provide any predefined defer function. We will use the assembly instruction NOP which takes only one clock cycle. And since the core of the microcontroller runs at 2MHz, we can easily speculate on the latency. For this reason, we combine the delay with two for loops. This is the simplest and most accurate way to defer the cosmic C compiler.
void delay_ms (int ms) //Function definition { for (int i=0; i<=ms; i++) for (int j=0; j<120; j++) // Nop = Dark/4 _asm("nop"); //Perform no operation //Assembly code }
Next, we'll look at our main loop. For this section we need to look at the SPL user manual. We start the main function by deinitializing the GPIO pins and Timer2. If the GPIO or Timer has been used previously by other applications, they should be initialized before using them. This is not mandatory, but it is a good practice.
GPIO_DeInit(GPIOD); TIM2_DeInit();
Next, we have to declare the pin as output, set up Timer2 with the help of TIM2_OC1Init() function and use a prescaler in the timer to achieve a PWM frequency of 4KHz. We do this with the help of the TIM2_TimeBaseInit() function. Once completed, we enable the timer with the help of TIM2_Cmd(ENABLE) function. For this project we decided to use PIN D4 on the board, which is a PWM capable PIN.
GPIO_DeInit(GPIOD); TIM2_DeInit(); GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST); TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000, TIM2_OCPOLARITY_HIGH); TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500); TIM2_Cmd(enable);
Next, we have our infinite loop. In the infinite loop, we set up the for loop and enabled capture and compare statements, which will allow us to set up the PWM channel.
while(true){ 对于(pwm_duty = 0;pwm_duty < 1000;pwm_duty += 2){ TIM2_SetCompare1(pwm_duty); delaymilliseconds(10); } 对于(pwm_duty = 1000;pwm_duty > 0;pwm_duty -= 2){ TIM2_SetCompare1(pwm_duty); delaymilliseconds(10); } }
The above code is responsible for generating the PWM signal, because in the first for loop the PWM signal will change from high level to low level, and because of the next for loop, the PWM signal will change from low level to high level and continue cycle.
Use STM8S to generate PWM signals
Compile the code and upload it to your STM8S development board. If you encounter any compilation errors, make sure you have added all header and source files as mentioned before. After uploading the code, you should see the brightness of the LED connected on pin D4 change.
#Includes "STM8S.h"
signed int pwm_duty = 0;
void delay_ms (int ms) //Function definition
{
for (int i=0; i<=ms; i++)
for (int j=0; j<120 ; j++) // Nop = Fosc/4
_asm("nop"); // Perform no operation // Assembly code
}
void main (void)
{
GPIO_DeInit(GPIOD);
TIM2_DeInit();
GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST) ;
TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000,
TIM2_OCPOLARITY_HIGH);
TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500);
TIM2_Cmd(enabled);
while(true) {
for(pwm_duty = 0; pwm_duty < 1000 ; pwm_duty += 2){ // Loop
TIM2_SetCompare1( pwm_duty); //Set Timer2's capture comparison
delay milliseconds (10); //Delay 10ms
}
For (pwm_duty = 1000; pwm_duty > 0; pwm_duty -= 2) {
TIM2_SetCompare1(pwm_duty);
Delay milliseconds (10);
}
}
}
Previous article:Directly debug and run the program without resetting the MCU, making bugs fearful
Next article:[Ultra-low power consumption series three] Selection of BAM mode and Stop mode
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Compile BLE_Chat under BLE_Examples with software, and fail to search for Bluetooth signal after running
- [RT-Thread reading notes] Solved the confusion of interruption
- How does LoRa achieve positioning?
- MPLAB cannot complete compilation
- ISE Tutorial
- Common Misunderstandings in PCB Differential Signal Design
- 【XMC4800 Relax EtherCAT Kit Review】+LWIP Application
- [NXP Rapid IoT Review] + Mobile Synchronizer 3
- Design of USB interface based on DSP
- How to test the third-order intermodulation intercept point (OPI3) of RF signal source and arbitrary waveform generator?