Search code examples
avratmegamicroprocessorsatmega32

Reading state of push button to turn on LED in AVR using Atmega32


I have a program that's supposed to read input values from a dip switch connected to PORTA and when button on PC0 is pressed, then it outputs the bits to the LEDs on PORTB, or if PC7 is pressed, then it shows up in PORTD. When PC3 is pressed, it's supposed to multiply both bytes for a 16-bit value stored as a high and low bytes.

The issue is that once I press the button once, the result does show up in the LEDs. However, after the first button press, the logic stops working. For example, when switching input on PORTA, it still shows up in the LEDs regardless of whether the button is pushed or not.

I cannot pinpoint where the issue is exactly and I really need help debugging this.

I'm using an atmega32, programming in Atmel studio, and simulating in Proteus.

I appreciate any help.

enter image description here

.cseg
.org 0x0000

; set stack pointer
ldi r29, low(ramend)
out spl, r29
ldi r29, high(ramend)
out sph, r29

start:
    ser r16
    out ddrb, r16   ; portb output  
    out ddrd, r16   ; portd output
    clr r16
    out ddra, r16   ;porta input
    out ddrc, r16   ;portc input
    ser r16
    out portc, r16  ;pull-up resistor on PORTC
    rjmp main

main:
    sbic pinc, 0    ;skip if button is not pressed on PC0
    call Load_Low   ;call subroutine function to load the lower bit
    sbic pinc, 7
    call Load_High  ;call subroutine function to load the higher bit
    sbic pinc, 3
    call Multiply   ;call subroutine function to multiply both stored values
    rjmp main

Load_High:
    in r20, pina    ;read bits in PINA to R20
    mov r30, r20    ;store copy
    out portb, r30  ;output to LEDs on PORTB
    cbi portc, 0    ;clear bit
    ret

Load_High:
    in r20, pina
    mov r31, r20
    out portd, r31
    cbi portc, 7
        ret

Multiply:   
    mul r31, r30
    out portd, r0
    out portb, r1
    cbi portc, 3
        ret

Solution

  • In the schematics there is no pull-down resistor which could make a low logical level when the button is released. Therefore voltage is undefined, in real life voltage will be floating causing unexpected logical level change on the inputs.

    Instead of adding external pull-down resistors you can connect buttons to the "GND" and engage internal pull-up resistors (setting corresponding bits of PORTC to 1 while in DDRC those bits are 0)

    Also in all your routines there are strange lines without explanation:

    cbi portc, 0    ;clear bit
    cbi portc, 7
    cbi portc, 3
    

    those are the button inputs, why you're clearing PORTC bits each time?