Share an interesting experiment. The MCU PWM drives the full-color LED module to quickly traverse 1 million colors.
1, Using hardware
The single chip microcomputer is STM32F103C8T6, and the three color LED module is shown in the figure below (the picture comes from the network)
2, STM32CubeMx configuration
The PWM channels 1, 2 and 3 of TIM3 are configured, and the corresponding pins are PA6, PA7 and PB0 respectively. The counting cycle here is configured according to its own clock frequency. The PWM frequency I configured here is 2KHz. The calculation method is: the clock frequency is 48MHz, 48 frequency division, that is, the value of PSC in the figure is 48-1 = 47, which is 1MHz, and the counting cycle, that is, the value of Counter Period in the figure is 500-1 = 499, Then T=500/1M=500us, that is, the frequency is 2000Hz
3, PWM drive
The timer initialization code is no longer expressed. We need a function to set PWM duty cycle. In Hal library, this function is__ HAL_TIM_SetCompare, corresponding to stm32f1xx_ hal_ Macro definition in Tim. H file
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \ (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\ ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)))
Therefore, the duty cycle can be set through the following function. If the duty cycle is 100%, that is, the duty cycle is 50%, the value of register CCRx is 50499 / 100. When the duty cycle is 100%, the value of CCRx is 499, that is, the value of automatic reload register ARR. For the calculation of duty cycle, please refer to the chip manual.
/******************************************************************************* * Function name: PWM_SetDutyCycle * Function: set duty cycle * Parameter: Channel Duty Duty cycle * Return value: None * Description: None *******************************************************************************/ void PWM_SetDutyCycle(uint32_t Channel, uint16_t Duty) { uint16_t u16CCR = 0; u16CCR = Duty * 499 / 100; __HAL_TIM_SetCompare(&htim3, Channel, u16CCR); }
Call this function and set the duty cycle of the three channels to 25%, 50% and 75 respectively:
PWM_SetDutyCycle(TIM_CHANNEL_1, 25); PWM_SetDutyCycle(TIM_CHANNEL_2, 50); PWM_SetDutyCycle(TIM_CHANNEL_3, 75);
Use the logic analyzer to collect the output of the three pins, as shown in the figure below
It can be seen from the above figure that the period is 500us, that is, the frequency is 2kHz;
The figure above shows that the high-level time interval with a duty cycle of 50% is 250us. The time of the other two duty cycles will not be measured and displayed.
4, Traversal color
The three color LED module is composed of three colors of red R, green G and blue B. through the color mixing of three different proportions, the full-color display can be realized. RGB three primary colors can divide the three colors from 0 to 255 into 256 intensities, so as to mix and form a total of 16777216 colors. However, if traversing such a variety of colors is obviously too time-consuming and of little significance, we can only realize the combination of about 1.03 million colors according to the combination of duty cycle 0 to 100. If each combination is delayed by 1ms, 1.03 million colors also need about 17min, which is also time-consuming.
The code is as follows:
/******************************************************************************* * Function name: RGB_ColorTraverse * Function: color traversal * Parameter: None * Return value: None * Note: for each combination, delay 1ms *******************************************************************************/ void RGB_ColorTraverse(void) { uint8_t i, j, k; for (i =0; i < 101; i++) { PWM_SetDutyCycle(TIM_CHANNEL_1, i);//R for (j =0; j < 101; j++) { PWM_SetDutyCycle(TIM_CHANNEL_2, j);//G for (k =0; k < 101; k++) { PWM_SetDutyCycle(TIM_CHANNEL_3, k);//B HAL_Delay(1);//Delay 1ms HAL_IWDG_Refresh(&hiwdg);//Watchdog reset } } } }
Here, three-level for loop nesting is used to realize color traversal, HAL library delay function delay, because the program will always be in the for loop, so we should feed the dog.
During the experiment, it is found that the color of the innermost for cycle changes quickly and flickers too obviously. It should be because the duty cycle changes from 0 to 100, then suddenly changes to 0 and then increases to 100; Considering the improvement, after the duty cycle is changed to 100, it is gradually reduced to 0 and then increased, so as to cycle. Therefore, the flag bit is added for each layer of the for loop. At the end of each for loop, the flag bit is reversed once. The duty cycle determines whether to take the value of the loop variable or (100 loop variable) according to the value of the flag bit. The code is as follows:
void RGB_ColorTraverse(void) { uint8_t i, j, k; RGBFlag_tu uRGBFlag; uRGBFlag.byte = 0; for (i =0; i < 101; i++) { if (uRGBFlag.bt.bRedCycle) { PWM_SetDutyCycle(TIM_CHANNEL_1, 100 - i);//R }else { PWM_SetDutyCycle(TIM_CHANNEL_1, i);//R } if (i == 100) { uRGBFlag.bt.bRedCycle = ~uRGBFlag.bt.bRedCycle; } for (j =0; j < 101; j++) { if (uRGBFlag.bt.bGreenCycle) { PWM_SetDutyCycle(TIM_CHANNEL_2, 100 - j);//G }else { PWM_SetDutyCycle(TIM_CHANNEL_2, j);//G } if (j == 100) { uRGBFlag.bt.bGreenCycle = ~uRGBFlag.bt.bGreenCycle; } for (k =0; k < 101; k++) { if (uRGBFlag.bt.bBlueCycle) { PWM_SetDutyCycle(TIM_CHANNEL_3, 100 - k);//B }else { PWM_SetDutyCycle(TIM_CHANNEL_3, k);//B } if (k == 100) { uRGBFlag.bt.bBlueCycle = ~uRGBFlag.bt.bBlueCycle; } HAL_Delay(3); printf("%d,%d,%d\n",i,j,k); HAL_IWDG_Refresh(&hiwdg); } } } }
The actual effect is disappointing. It may be because of the problem of this cheap module. The distance between the three LEDs is actually far, and the three lights will not be well mixed together. It seems that there is no mixed color effect (the effect of taking photos by mobile phone is worse):
5, Summary
Don't buy this LED module.