-1

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
SegFaulter
  • 61
  • 7

1 Answers1

1

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?

AterLux
  • 4,566
  • 2
  • 10
  • 13
  • I know those lines are not doing anything. I just noticed the behaviour where the output would change without pressing the button. So, I thought maybe it's because it's preserving the high state after one button push. – SegFaulter Jul 01 '20 at 14:37
  • Thank you for the answer. I will try to implement it and get back to you with the results. – SegFaulter Jul 01 '20 at 14:38
  • I edit the code I have to add the line `out portc, r16` to set the pull resistor. I grounded the buttons, but that doesn't seem to work. – SegFaulter Jul 01 '20 at 14:51
  • @SegFaulter you also have to invert logic. Now, when button is pressed the input has low logical level (zero), and high (one) when released. I.e. `sbic pinc, 0` change `sbic` to `sbis` – AterLux Jul 01 '20 at 14:53
  • Yeah I figured it out thanks. I'm now looking into why the bits cannot be overridden. 0 bits become 1, but not that opposite on the second press – SegFaulter Jul 01 '20 at 15:01
  • I assume the easier way to do it is to clear all bits before setting it – SegFaulter Jul 01 '20 at 15:01