NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » Could someone explain this please

May 06, 2010
by Ralphxyz
Ralphxyz's Avatar

Imagine I am confused again.

I am "trying" to show the value of the PORTB register bits. PB0, PB1, PB2, PB3, PB4, and PB5on the LCD.

This is just a extension of the NerdKit led_blink project combined with some samples I have found on the web.

This works fine:

// led6.c
// for NerdKits with ATmega328p
// rhulslander at gmail.com

#define F_CPU 14745600

#include <stdlib.h>
#include <inttypes.h>

#include <avr/io.h>
#include <avr/pgmspace.h>

#include "../libnerdkits/io_328p.h"
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

int main (void)
{
// start up the LCD
lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_home();

/* set PORTB for output*/   
//DDRx is DataDirection Register. Sets PB0, PB1, PB2, PB3, PB4 and PB5 high  11111111
// DDRB means Data Direction for PORTB
DDRB = 0xFF;

while (1) 
{

PORTB |= (1<<PB5);  // ON   turns on the internal pull-up resistor which pulls the pin (PB5) high
lcd_line_one;
fprintf_P(&lcd_stream, PSTR("PB5 0x%x= 00010101"), PORTB);  // 21
   delay_ms(500);
PORTB &= ~(1<<PB5); // OFF
}
return 0;
}

This loops continuously and always has the correct (I think) value for PB5.

Substitute the following while loop for the prior one and I get a strange error. All if the values are correct for the first iteration but subsequent ones have all subtracted 1.

PB5 is 21 for the first loop but for subsequent loops it is 20, it is the same for all of the bits.

All of the LEDs light correctly but the bit value is reported wrong. while (1) {

PORTB |= (1<<PB5);  // Led ON   turns on the internal pull-up resistor which pulls the pin (PB5) high
lcd_line_one;
fprintf_P(&lcd_stream, PSTR("PB5 0x%x= 00010101"), PORTB);  // 21
    delay_ms(500);
PORTB &= ~(1<<PB5); // Led OFF

PORTB |= (1<<PB4);  // Led ON
lcd_line_two();
fprintf_P(&lcd_stream, PSTR("PB4 0x%x= 00001011"), PORTB);  // 11
delay_ms(500);
PORTB &= ~(1<<PB4); // Led OFF

PORTB |= (1<<PB3);  // Led ON   
lcd_line_three();
fprintf_P(&lcd_stream, PSTR("PB3 0x%x= 00001001"), PORTB);  // 9
    delay_ms(500);
PORTB &= ~(1<<PB3); // Led OFF

PORTB |= (1<<PB2);  // Led ON
lcd_line_four();
fprintf_P(&lcd_stream, PSTR("PB2 0x%x= 00000101"), PORTB);  // 5
delay_ms(1500);
PORTB &= ~(1<<PB2); // Led OFF
lcd_init();

PORTB |= (1<<PB1);  // Led ON
lcd_line_one();
fprintf_P(&lcd_stream, PSTR("PB1 0x%x= 00000013"), PORTB);  // 3
delay_ms(500);
PORTB &= ~(1<<PB1); // Led OFF

PORTB |= (1<<PB0);  // Led ON
lcd_line_two();
fprintf_P(&lcd_stream, PSTR("PB0 0x%x= 00000001"), PORTB);  // 1
delay_ms(500);
PORTB &= ~(1<<PB0); // Led OFF

lcd_line_four();
fprintf_P(&lcd_stream, PSTR("PORTB 0x%x= 00000000"), PORTB);   // all off 00000000
delay_ms(1500); 
lcd_init();  
}

Thanks for the help,

Ralph

May 06, 2010
by Ralphxyz
Ralphxyz's Avatar

Darn I tried to clean up the code to keep it simple an dmessed it up.

Try this:

// led6.c
// for NerdKits with ATmega328p
// rhulslander at gmail.com

#define F_CPU 14745600

#include <stdlib.h>
#include <inttypes.h>

#include <avr/io.h>
#include <avr/pgmspace.h>

#include "../libnerdkits/io_328p.h"
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

int main (void)
{
// start up the LCD
lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_home();

/* set PORTB for output*/   
//DDRx is DataDirection Register. Sets PB0, PB1, PB2, PB3, PB4 and PB5 high  11111111
// DDRB means Data Direction for PORTB
DDRB = 0xFF;

while (1) 
{

PORTB |= (1<<PB5);  // ON   turns on the internal pull-up resistor which pulls the pin (PB5) high
lcd_line_one;
fprintf_P(&lcd_stream, PSTR("PB5 0x%x= 00010101  "), PORTB);    // 21
    delay_ms(1500);
PORTB &= ~(1<<PB5); // OFF
lcd_init();
}
return 0;
}

It has the #include for the ATmega328p so remove that to run on the 168

Ralph

May 10, 2010
by Ralphxyz
Ralphxyz's Avatar

This is great, in order to illustrate my "perceived" problem I have spent the last couple of days learning how to edit movies.

Another thing I have always been curious about but had never taken the time to learn, so once again thank you NerdKits for expanding my understanding of how things work and not just MCUs.

The problem as I saw it, was when lighting leds on PORTB using a loop the returned value of the PORTB bits were decremented after the first iteration.

The first time through I would get:

PB5 = 0x21
PB4 = 0x11
PB3 = 0x09
PB2 = 0x05
PB1 = 0x03
PB0 = 0x01

The next time through I would get:

PB5 = 0x20
PB4 = 0x10
PB3 = 0x08 
PB2 = 0x04
PB1 = 0x02
PB0 = 0x01

All of the values were minus one except for PB0. Watch the movie.

If the code invoking PBO is removed it works as expected. Watch the movie.

Sorry about the delay in downloading.

The Solution!!

Do not touch or try to use PB0.

Now after days of trying to understand what was happening I realize that if I just do not use PB0 I can do everything I was trying to do, so I can move on. I suppose there is something about PB0 being used by the bootloader as the programming pin that is causing this.

ta dah!!

Ralph

Post a Reply

Please log in to post a reply.

Did you know that NerdKits believes in the importance of a mixture of meaningful topics, clear instruction, and engaging projects? Learn more...