1
\$\begingroup\$

I'm currently working on a small queuing system where whenever someone presses a button (which I have linked to INT0), my 8051 would increase the register and would display a higher number on the dual digit 7-segment.

As an example. If the 7-segment is currently displaying 76, if I press the INT0 button, the number on the 7-segment would increase to become 77.

I have already finished the above mentioned parts when it comes to coding and hardware, and I believe that they work bug free. I would now like to add a buzzer, so that whenever the INT0 button is pressed, the number on the 7-segment would increase and the buzzer would play a sound.

From what I've studied so far, I've written the following code to play a sound with the buzzer:

PLAY_SOUND:         
    MOV R1, #50
MI_L1:  MOV R0, #21
MI_L2:  MOV TH0, #HIGH(-379)
    MOV TL0, #LOW(-379)
    SETB TR0
    JNB TF0, $
    CLR TR0
    CLR TF0
    CPL P0.0
    DJNZ R0, MI_L2
    DJNZ R1, MI_L1
    CLR P0.0
    RET

The following is a partial code of how the system should interact together

.
.
.
;---------------------------------INT0 ISR-----------------------------------
ORG 0003H               ;Starting address for the ISR (INT0)
LCALL PLAY_SOUND  
LCALL INC_7_SEG         ;Increase the 7-segment count
RETI
.
.
.
;-------------------------------SOUND SUBRO---------------------------------
PLAY_SOUND:         
    MOV R1, #50
MI_L1:  MOV R0, #21
MI_L2:  MOV TH0, #HIGH(-379)
    MOV TL0, #LOW(-379)
    SETB TR0
    JNB TF0, $
    CLR TR0
    CLR TF0
    CPL P3.7
    DJNZ R0, MI_L2
    DJNZ R1, MI_L1
    CLR P3.7
    RET

The above code works somewhat fine, as in, whenever the button in INT0 is pressed, the buzzer would play a sound, BUT, while the buzzer is playing a sound, the 7-segment turns off. And then the after the buzzer is done, the 7-segment increases it's number.

If it is of any help, here is the schematic of the circuit I've made so far:

Circuit Schematic

How can I make the buzzer play a sound, without the 7-segment turning off (momentarily) using my current setup?

I can provide the full code if I need to, but its about 350 lines long.

\$\endgroup\$
  • \$\begingroup\$ Why don't you start a timer when the buzzer is turned on? When the timer fires an interrupt later, just turn the buzzer off. In the meantime, your display and key monitoring code keeps doing what it always does. If you already have an active timer running for other reasons, just add a variable that you count down until it reaches zero and clear the buzzer in the timer code when it is zero (and don't count down further, obviously.) \$\endgroup\$ – jonk Aug 25 '19 at 6:26
  • 1
    \$\begingroup\$ @James: I think you need to comment your code more thoroughly. \$\endgroup\$ – Transistor Aug 25 '19 at 8:03
1
\$\begingroup\$

I suggest using a timer interrupt, say every 250 microseconds, to time both the beeper and the display makes multiplexing.

If you toggle the buzzer output every 250us you’ll get a 2kHz beep. If you display a new digit every one or two interrupts the whole display gets scanned at 500 or 250Hz, either of which are adequate.

Adjust the numbers to fit your situation.

I would not use an interrupt input for the button. You can also use the aforementioned timer interrupt to de bounce the button if you want, and even use it to generate flags for button press, button release, button prolonged hold, button double tap etc.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ It's fairly obvious that the beeper is self-oscillating. It just needs to be turned on and then turned off 1 second later. Also, a timer interrupt every 250 us is a lot on an 8051. I think 1 ms would be plenty often, and still gives you a 250 Hz refresh on a 4-digit display. \$\endgroup\$ – Dave Tweed Aug 25 '19 at 12:32
1
\$\begingroup\$

In order to keep the display driver all the time, you have to ensure that the MCU won't be disturbed by other tasks for significant duration (preset case). For now, the buzzer function is taking complete attention for the whole duration of sound event.

Please utilise a hardware timer built in which can run independent of what MCU core is executing. When the hardware timer expires, it will interrupt the MCU.

As @Jonk suggested, you can set the GPIO to drive the buzzer, fire the hardware timer and go back to LCD driving function. This can be done with just a few couple of instructions and should not create a visible pause of the display. When the hardware timer expires, it will create an interrupt. This time, you can turn off the buzzer and return to the display function again.

  1. update the LCD display to show new number
  2. Set the buzzer GPIO and fire the hardware timer with appropriate delay
  3. Once hardware timer interrupts, RESET buzzer GPIO

Only in case of urgent hardware solution: For now, I would also put a 555 timer for the buzzer control in case th function is needed urgently

Also read,
https://stackoverflow.com/questions/24128864/how-to-achieve-multitasking-in-a-microcontroller

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You'd spend money putting in a 555 in for a buzzer in case a microcontroller can't do it? \$\endgroup\$ – TonyM Aug 25 '19 at 10:00
  • \$\begingroup\$ @TonyM if sequential programming isn't allowing it for now, i would put one. It costs me about 10-20 cents. Only for interim solution. Do you have other suggestions ? \$\endgroup\$ – User323693 Aug 25 '19 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.