-1
\$\begingroup\$

I don't understand on passing parameter on ATMEGA128 and AVR Studio 6, I tested this function and working find

lcd_cmd()
{
            PORTD = 0xFF;
            _delay_ms(100);
            PORTD = 0x00;
            _delay_ms(100);

            en=0;
            _delay_ms(100);
            en=1;
            _delay_ms(100);
            rs=0;
            _delay_ms(100);
            rs=1;
            _delay_ms(100);
            rw=0;
            _delay_ms(100);
            rw=1;
            _delay_ms(100);    
}
main()
{
 lcd_cmd();
}

D0-D4 are appearing ![enter image description here][1] but by the time I put parameter to be passed, it doesn't work

lcd_cmd(unsigned char data_cmd)
{
            PORTD = data_cmd;
            _delay_ms(100);
            PORTD = data_cmd;
            _delay_ms(100);

            en=0;
            _delay_ms(100);
            en=1;
            _delay_ms(100);
            rs=0;
            _delay_ms(100);
            rs=1;
            _delay_ms(100);
            rw=0;
            _delay_ms(100);
            rw=1;
            _delay_ms(100);
}

main() {
   while(1) {
     lcd_cmd(0xFF);
     _delay_ms(100);
     lcd_cmd(0x00);
   }
}

as you can see D0-D4 are missing but rw,rs,and en are working ![enter image description here][2]

What do I miss here ? It's very strange for me.... Any experiences , shares or knowledges will be very appreciated,

Here's the complete code, please let me know what I miss here ???

    #include <avr/io.h>
#include <util/delay.h>

// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0  PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
                uint8_t b1:1;
                uint8_t b2:1;
                uint8_t b3:1;
                uint8_t b4:1;
                uint8_t b5:1;
                uint8_t b6:1;
                uint8_t b7:1; } bits;

// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_A (* (volatile bits *) &PORTA)
#define PIN_A (* (volatile bits *) &PINA)
#define DDR_A (* (volatile bits *) &DDRA)

#define PORT_B (* (volatile bits *) &PORTB)
#define PIN_B (* (volatile bits *) &PINB)
#define DDR_B (* (volatile bits *) &DDRB)

//Mention Clock frequency here
#define _XTAL_FREQ 8000000 

#define lcd_data_pin PORTD

#define en PORT_A.b0
#define rs PORT_A.b1
#define rw PORT_A.b2




void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);


void lcd_init(){

    lcd_cmd(0x02);      
    lcd_cmd(0x28);      
    lcd_cmd(0x0C);
    lcd_cmd(0x06);
    lcd_cmd(0x80);

}

void lcd_data(unsigned char data1)
{

    lcd_data_pin = data1;
    lcd_control(2);


}

void lcd_cmd(unsigned char cmd){

    lcd_data_pin = cmd & 0xF0;
    lcd_control(1);

    lcd_data_pin = (cmd << 4) & 0xF0;
    lcd_control(1);


}

void lcd_control(unsigned char cmdordata){

    if(cmdordata == 1){
        en=1;
        rs=0;
        rw=0;
        _delay_ms(1);       
        en=0;
    }
    else if(cmdordata == 2){
        en=1;
        rs=1;
        rw=0;
        _delay_ms(1);
        en=0;
    }
}

void lcd_string(unsigned char *str){

    while(*str){
        lcd_data(*str++);       
    }

}




int main(){

    DDRA = 0xFF;
    DDRD = 0xFF;

    lcd_init();
    lcd_data('A');


    while(1){

        lcd_string("Working?");

    }

    return (0);
}

so the right one will be:

void lcd_data(unsigned char data1)
{

    lcd_data_pin = data1 & 0xF0;;
    lcd_control(2);

    lcd_data_pin = (data1<< 4) & 0xF0;
    lcd_control(2);


}

void lcd_cmd(unsigned char cmd){

    lcd_data_pin = cmd & 0xF0;
    lcd_control(1);

    lcd_data_pin = (cmd << 4) & 0xF0;
    lcd_control(1);

}

I tested on ATMEGA32, and it's allright, is it related with ATMEGA128 configuration ??? Latest code :

 #include <avr/io.h>
#include <util/delay.h>

// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0  PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
                uint8_t b1:1;
                uint8_t b2:1;
                uint8_t b3:1;
                uint8_t b4:1;
                uint8_t b5:1;
                uint8_t b6:1;
                uint8_t b7:1; } bits;

// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_D (* (volatile bits *) &PORTD)
#define PIN_D (* (volatile bits *) &PIND)
#define DDR_D (* (volatile bits *) &DDRD)

#define PORT_G (* (volatile bits *) &PORTG)
#define PIN_G (* (volatile bits *) &PING)
#define DDR_G (* (volatile bits *) &DDRG)

//Mention Clock frequency here
//#define _XTAL_FREQ 8000000 

#define lcd_data_pin PORTA

#define en PORT_D.b0
#define rs PORT_D.b1
#define rw PORT_D.b2


void lcd_init();
void lcd_data(unsigned char data1);
void lcd_cmd(unsigned char cmd);
void lcd_control(unsigned char cmdordata);
void lcd_string(unsigned char *str);


void lcd_init(){

    lcd_cmd(0x30);
    _delay_ms(100);      
    lcd_cmd(0x38);
    _delay_ms(100);      
    lcd_cmd(0x0F);
    _delay_ms(100);
    lcd_cmd(0x80);
    _delay_ms(100);

}

void lcd_data(unsigned char data1)
{


    lcd_data_pin = data1;// & 0x0F;
        en=1;
        rs=1;
        rw=0;
        _delay_ms(10);
        en=0;

}

void lcd_cmd(unsigned char cmd){
    lcd_data_pin = cmd ;
        en=1;
        rs=0;
        rw=0;
        _delay_ms(10);       
        en=0;

}



void lcd_string(unsigned char *str){

    while(*str){
        lcd_data(*str++);       
    }

}




int main(){

    DDR_D.b0 = 1;
    DDR_D.b1 = 1;
    DDR_D.b2 = 1;
    DDRA = 0xFF;

    lcd_init();


    while(1){
      _delay_ms (200);
        lcd_cmd(0x80);//put the cursor into the first row
        _delay_ms (300);
        lcd_cmd(0x01);//Clear display
        _delay_ms (300);
        lcd_cmd(0xC0);//goto second row
        _delay_ms (300); 
       lcd_cmd(0x01); //Clear display

       lcd_string("HELLO ATMEGA32");

    }

    return (0);
}

I used this code and can display until init but can not display character A Video : http://www.youtube.com/watch?v=BbL6GBVkWuU The code (I'm not passing parameter at all and it works ):

#include <avr/io.h>
#include <util/delay.h>

// structure to allow bit field operations, name conversions: PORTA.0 -> PORT_A.b0  PORTB.7 -> PORT_B.b7
typedef struct{ uint8_t b0:1;
                uint8_t b1:1;
                uint8_t b2:1;
                uint8_t b3:1;
                uint8_t b4:1;
                uint8_t b5:1;
                uint8_t b6:1;
                uint8_t b7:1; } bits;

// define all the ports of your microcontroller, add more ports depending on the available mcu ports
#define PORT_D (* (volatile bits *) &PORTD)
#define PIN_D (* (volatile bits *) &PIND)
#define DDR_D (* (volatile bits *) &DDRD)

#define PORT_G (* (volatile bits *) &PORTG)
#define PIN_G (* (volatile bits *) &PING)
#define DDR_G (* (volatile bits *) &DDRG)

//Mention Clock frequency here
#define _XTAL_FREQ 8000000 

#define lcd_data_pin PORTA

#define en PORT_D.b0
#define rs PORT_D.b1
#define rw PORT_D.b2





lcd_init()
{
      lcd_data_pin = 0x30;

       en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;

//next command
       _delay_ms(100);

      lcd_data_pin = 0x38;

       en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;
    _delay_ms(100);

      lcd_data_pin = 0x0F;

       en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;

//next command
       _delay_ms(100);

      lcd_data_pin = 0x80;

       en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;

      } 
  lcd_clear()
{
    lcd_data_pin = 0x80;//put the cursor into the first row
     en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;
        _delay_ms (300);

    lcd_data_pin = 0xC0;//put the cursor into the first row
     en = 1;
       rs = 0;
       rw = 0;
       _delay_ms(10);
      en = 0;
        _delay_ms (300);

}
void lcd_data()
{

       lcd_data_pin = 0x41;// & 0x0F;
        en=1;
        rs=1;
        rw=0;
        _delay_ms(10);
        en=0;

}



int main(){

    DDR_D.b0 = 1;
    DDR_D.b1 = 1;
    DDR_D.b2 = 1;
    DDRA = 0xFF;



    lcd_init();

    while(1){
        lcd_clear();
        lcd_data();
        _delay_ms(1000); 

    }

    return (0);
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Where do you set the direction of your ports? It looks to me as though there must be more code. You are not passing a port address, so the FAQ you linked to is not relevant. \$\endgroup\$
    – Tom Davies
    May 8, 2013 at 6:19
  • 3
    \$\begingroup\$ In the second variant do you really want to set PORTD to the same value twice in a row? You won't get the transitions like in the first diagram when you go from 0xFF to 0x00. \$\endgroup\$
    – PeterJ
    May 8, 2013 at 6:48
  • \$\begingroup\$ You are not passing the port as a parameter, so this isn't relevant. Passing a port as a parameter is when your function doesn't know which port to write to (PORTD, PORTB, PORTC, etc), and the port is passed as a parameter to such function. You are trying to pass the value to write to the port. Like others have said, make sure that DDRD is set correctly (for instance DDRD=0xFF;). Also, even when relevant, it doesn't help to paste entire sections of FAQs: better to just link to those. Especially when such text lacks any formatting in the answer. \$\endgroup\$ May 8, 2013 at 7:18

3 Answers 3

1
\$\begingroup\$

Here is what I need to do to make your code compile (on avr-gcc) and functional:

#include <avr/io.h>
#include <util/delay.h>

bool en;
bool rs;
bool rw;

void lcd_cmd(unsigned char data_cmd)
{
        PORTD = data_cmd;
        _delay_ms(100);
        PORTD = data_cmd;
        _delay_ms(100);

        en=0;
        _delay_ms(100);
        en=1;
        _delay_ms(100);
        rs=0;
        _delay_ms(100);
        rs=1;
        _delay_ms(100);
        rw=0;
        _delay_ms(100);
        rw=1;
        _delay_ms(100);
}

int main() {
   DDRD = 0xFF;
   while(1) {
     lcd_cmd(0xFF);
     _delay_ms(100);
     lcd_cmd(0x00);
   }
}

However, the program below does exactly the same as your code (as far as you actually shared it with us), but is a lot shorter:

#include <avr/io.h>
#include <util/delay.h>

void lcd_cmd(unsigned char data_cmd)
{
        PORTD = data_cmd;
        _delay_ms(800);
}

int main() {
   DDRD = 0xFF;
   while(1) {
     lcd_cmd(0xFF);
     _delay_ms(100);
     lcd_cmd(0x00);
   }
}
\$\endgroup\$
0
\$\begingroup\$

Your problem is in lcd_command()

lcd_data_pin = cmd & 0xF0;

Will always set d0-d3 to zero, as will

lcd_data_pin = (cmd << 4) & 0xF0;

because & 0xF0 always results in a byte with the lower four bits clear -- d0 is the least significant bit of the port, d7 the most significant.

You may have meant to write:

lcd_data_pin = cmd & 0x0f; // send the low four bits

and

lcd_data_pin = (cmd >> 4) & 0x0f; // send the high four bits in the low four bits of D (the '&' is unnecessary as cmd is unsigned)

My code above also sets d4-d7 to zero, which I don't think matters in your application.

\$\endgroup\$
7
  • \$\begingroup\$ so I'll replace : lcd_data_pin = data_cmd; with : lcd_data_pin = cmd & 0x0f; // send the low four bits then lcd_data_pin = (cmd >> 4) & 0x0f; , is that what you mean ? thanks \$\endgroup\$
    – Rick Ant
    May 11, 2013 at 3:34
  • \$\begingroup\$ so: void lcd_data(unsigned char data1) { lcd_data_pin = data1 & 0xF0;; lcd_control(2); lcd_data_pin = (data1<< 4) & 0xF0; lcd_control(2); } void lcd_cmd(unsigned char cmd){ lcd_data_pin = cmd & 0xF0; lcd_control(1); lcd_data_pin = (cmd << 4) & 0xF0; lcd_control(1); } \$\endgroup\$
    – Rick Ant
    May 11, 2013 at 3:41
  • \$\begingroup\$ Yes to your first comment -- I'm not sure what your second comment means. Feel free to accept my answer if it helps. \$\endgroup\$
    – Tom Davies
    May 11, 2013 at 8:32
  • \$\begingroup\$ So far it's not working as expected, what do I miss here ? \$\endgroup\$
    – Rick Ant
    May 13, 2013 at 22:33
  • \$\begingroup\$ What does your code look like now? \$\endgroup\$
    – Tom Davies
    May 13, 2013 at 23:06
-1
\$\begingroup\$

Set M103C fuse bit on ISP programmer to 0 and it will fix the issue,

thanks for any replies.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You should explain in more detail why this solved your problem. From what i can tell the compatibility mode does change nothing regarding PORTD. \$\endgroup\$
    – Rev
    May 21, 2013 at 14:33

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.