0
\$\begingroup\$

This simple program for ATmega32A is expected to work in this way:

  1. Set PORTC 0,1,2,3 as Output pins
  2. Set PORTC 4, 5, 6, 7 as Input pins with pull ups
  3. Turn on/off output pins 0, 1, 3: 3a. If input pin PORTC6 is HIGH turn 0, 1, 3 HIGH (5V) 3b. If input pin PORTC6 is LOW turn 0, 1, 3 LOW (0V)

    #define __DELAY_BACKWARD_COMPATIBLE__
    
    #ifndef F_CPU
    #define F_CPU 1000000UL    /* 1 MHz clock speed */
    #endif
    
    #include <avr/io.h>
    #include <util/delay.h>
    
    int
    main(void) {
        DDRC = 0x0F;    /* 00001111, set lower nibble of PORTC to OUTPUT, upper nibble to INPUT */
        PORTC = 0xFC;   /* set HIGH PORTC.3 and PORTC.2 00001100, Low PORTC.1 PORTC.0 and set pull-ups on all INPUT pins */
    
        while(1) {
            if (PINC & (1 << PC6)) { /* lets assume a 4V supply comes to PORTC.6 and Vcc = 5V */
                PORTC |= (1 << PC3);       /* 00001011 but don't touch PORT PC2 - it stays HIGH */
                PORTC |= (1 << PC1);       /* 00001011 but don't touch PORT PC2 - it stays HIGH */
                PORTC |= (1 << PC0);       /* 00001011 but don't touch PORT PC2 - it stays HIGH */
                _delay_ms(1000);    /* delay 1s */
            } else {
                PORTC &= ~(1 << PC3);       /* turn off all output pins */
                PORTC &= ~(1 << PC1);       /* turn off all output pins */
                PORTC &= ~(1 << PC0);       /* turn off all output pins */
                _delay_ms(1000);    /* delay 1s */
           }
        }
    }
    

I have built flash image and loaded this into MCU using avr-dude executing below commands:

avr-gcc -g -DF_CPU=1000000  -Wall -Os -Werror -Wextra -mmcu=atmega32a -Wa,-ahlmns=main.lst -c -o main.o main.c
avr-gcc -g -DF_CPU=1000000  -Wall -Os -Werror -Wextra -mmcu=atmega32a -o main.elf main.o
chmod a-x main.elf 2>&1
avr-objcopy -j .text -j .data -O ihex main.elf main.flash.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex main.elf main.eeprom.hex
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
avrdude -p m32 -cusbasp -B 5 -e -u -U flash:w:main.flash.hex

avrdude: set SCK frequency to 187500 Hz
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9502
avrdude: erasing chip
avrdude: set SCK frequency to 187500 Hz
avrdude: reading input file "main.flash.hex"
avrdude: input file main.flash.hex auto detected as Intel Hex
avrdude: writing flash (176 bytes):

Writing | ################################################## | 100% 0.19s

avrdude: 176 bytes of flash written
avrdude: verifying flash memory against main.flash.hex:
avrdude: load data flash data from input file main.flash.hex:
avrdude: input file main.flash.hex auto detected as Intel Hex
avrdude: input file main.flash.hex contains 176 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.10s

avrdude: verifying ...
avrdude: 176 bytes of flash verified

avrdude done.  Thank you.

PORTC0 and PORTC1 work as expected and described above, when PORTC6 is LOW multimeter indicates voltage close to 0V, when PORTC6 goes HIGH the voltage is 4.92 - 4.98 V. The problem is PORTC3 doesn't work as expected. When it should be LOW multimeter shows 4.77 V

enter image description here

and when it should be HIGH it is 4.21 V (!):

enter image description here

Why it is so? Am I doing something wrong?


[UPDATE]

Just as suggested disabling JTAG by programming fuses to hfuse:w:0xD9:m did the thing. Much better now:

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ Check for shorts in the breadboard. \$\endgroup\$ Commented Jul 3, 2016 at 20:40
  • \$\begingroup\$ This is not the cause of any issue (your code is fine), but its handy to know: you can reduce the three writes to PORT C in a row to be a single one of: PORTC &= ~((1 << PC3) | (1 << PC1) | (1 << PC0)); for all to be 0 and PORTC |= ((1 << PC3) | (1 << PC1) | (1 << PC0)); for all to be 1. \$\endgroup\$ Commented Jul 3, 2016 at 20:43
  • \$\begingroup\$ @Tom Carpenter But I got 4.77V as LOW voltage on PORTC3 and 4.21V as HIGH? These values are simply wrong. \$\endgroup\$
    – 4pie0
    Commented Jul 3, 2016 at 20:55

1 Answer 1

3
\$\begingroup\$

Look at the "Alternate Functions of Port C" section of the datasheet. C3's alternate function is part of the JTAG port. (C0 and C1 are not associated with the JTAG port.) "When the JTAG interface is enabled, this pin can not be used as an I/O pin." Try disabling the JTAG port and then see if your code works as you expect.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you. That was this. Disabling JTAG by programming fuses to hfuse:w:0xD9:m did the thing. \$\endgroup\$
    – 4pie0
    Commented Jul 3, 2016 at 22:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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