The schematic diagram for the project is as follows:
If the output performance of the I/O cannot be guaranteed, pull-up or pull-down resistors can be added as needed.
Getting to the point: In the program, the buzzer is driven by a high-low level. A high level turns the transistor on, and the buzzer sounds; a low level turns the transistor off, and the buzzer doesn't sound. It's indeed very simple. Initially, I wrote the program like this:
Of course, if the microcontroller does not have a good I/O transition function, it can be modified like this:
Here is a brief explanation:
1)
Function: Buzzer sound generation driver
Input parameter: Number of times the buzzer sounds
2)
The number of beeps, cnt, needs to be doubled within the function. This is because the input parameter is intended to make the buzzer sound continuously, cnt. However, a buzzer can also be silent at times. In other words, the buzzer needs to be turned off after each beep. Without this off-hook operation, it wouldn't sound several times but rather a single, continuous beep. This is easily deduced.
3)
After the while loop completes, a buzzer should be added to turn it off.
If the parameter passed in here is 2, the goal is to make the buzzer sound twice. According to the program's execution steps:
cnt2 becomes 4.
The buzzer is turned on for the first time in while(4), and cnt decrements to 3.
The buzzer is turned off for the second time in while(3), and cnt decrements to 2.
The buzzer is turned on for the third time in while(2), and cnt decrements to 1.
The buzzer is turned off for the 4th time while(1), and cnt decrements to 0.
The while(0) loop exits for the 5th time.
It can be seen that the buzzer is actually off after the while loop, but to be on the safe side, it's important to ensure that the buzzer is off after the function call is complete. This is especially important for the first function's I/O transition, because the code only shows the transition, not the state after it.
That concludes our review of a simple buzzer circuit and driver program. Now, let's get to the practical stuff:
When writing programs, efficiency is often a key consideration. For example, in driving a buzzer, efficiency is reduced during the process, and a skilled programmer can quickly identify this as a delay issue. However, as mentioned above, eliminating the delay is also not feasible. Therefore, prioritizing efficiency, I tried a different method to drive the buzzer.
The code is as follows:
It's also very simple to implement; let me briefly explain the principle:
1) The first step is to provide the I/O configuration for the buzzer driver.
2) Next is the configuration of the timer.
3) Finally, the timer interrupt function is implemented.
The timer I chose is the simplest one in the microcontroller for the project, configured with a 1ms interrupt to provide an overflow interrupt. I usually use this timer to keep track of system runtime (Systick_ms). However, this project doesn't use this system time, so I'll use this timer for this purpose.
Implementation method:
1. The same function has the same interface when calling the buzzer driver, and the parameter passed in is still the number of times the buzzer sounds.
2. The function body has changed. Here, it involves assigning values to two variables. The first, BELL_CNT, is the same as cnt2 in a normal method, so I won't go into detail here. The second, FLAG_BELL, is a state variable used to store whether the buzzer needs to be driven. Therefore, since it's a call to the driver function, this variable must be true.
3. A static variable `NOW` was added to the timer interrupt function. Its purpose is to generate a 50ms time slice with `Systic_ms`. What's it used for ? It's definitely for the delay between the buzzer on/off state, simulating software delay. Now let's analyze this code:
1) First, NOW and Systic_ms must be unconditionally assigned values to guarantee a 50ms time slice. The corresponding code is NOW = Systic_ms + 50;
2) Determine if the buzzer driver state variable is true. If it is not true, turn off the buzzer. This is also unconditional.
3) If the state variable is true: The buzzer first switches to Bell_Tog(); of course, if this switching function is not available, the method of judging cnt mentioned above can also be used, so I won't elaborate further, as they are the same. At the same time, the count is decremented by BELL_CNT--; it is also checked whether it has decremented to 0. If it has decremented to 0, it means the buzzer has finished ringing, so the state variable is set to false. Upon re-entry, regardless of whether the buzzer is on or off, the shut-off operation will be performed, which is the same as the safety mechanism mentioned above.
4) Finally, these two variables are global variables, presented here as a structure, because in many cases these two functions are not in the same C code. If you insist on writing them in the same C code, you can ignore this point.
Disclaimer: This article is a reprint. If it involves copyright issues, please contact us promptly for deletion (QQ: 2737591964). We apologize for any inconvenience.