Electronic – Microcontrol port for lcd

avrcmicrocontroller

Ihave modify an existing lcd library, it only works on DDRA for exmple if i change:

Update error Fixed:

I have found the error in the code assembly delay was too short for port B, C and D. by changing delay time i was able to use all ports.

Im using a AVR ATMEGA16. i have also wiring the pins correct to databus lines.

#define DDR       DDRA
#define PORT      PORTA  
#define PIN       PINA
#define RS_PIN    0
#define RW_PIN    1
#define E_PIN     2

to this nothing happens

#define DDR       DDRC
#define PORT      PORTC  
#define PIN       PINC
#define RS_PIN    0
#define RW_PIN    1
#define E_PIN     2

here is the link to library

and this is what i have changed. p.s it doesn't give any warnings or error

#include "lbl_lcd.h"
#include <avr/io.h>

/* One byte delay loop, one loop costs 3 cycles. */
void _lcd_delay_8(uint8_t t) {
    asm volatile (  "\n"
                    "L_dl0%=:   subi %0,1"      "\n\t"
                    "           brcc L_dl0%="   "\n\t"
                    :: "r" (t));
}

/* Two byte delay loop, one loop costs 4 cycles. */
void _lcd_delay_16(uint16_t t) {
    asm volatile (  "\n"
                    "L_dl1%=:   subi %A0,1"         "\n\t"
                    "           sbci %B0,0"         "\n\t"
                    "           brcc L_dl1%="   "\n\t"
                    :: "r" (t));
}




#define DDR       DDRD
#define PORT      PORTD  
#define PIN       PIND
#define RS_PIN    0
#define RW_PIN    1
#define E_PIN     2



uint8_t lcd_read_command(void) {
    uint8_t command;
    DDR|=1<<E_PIN|1<<RW_PIN|1<<RS_PIN; // control bus output
    DDR&=~0xF0; // databus input
    PORT|=1<<RW_PIN|0xF0; // R/!W= 1 (Read) and Pullup inputs 
    PORT&=~(1<<RS_PIN); // RS=0
    _lcd_delay_us_small(2);
    PORT|=1<<E_PIN; // E=1
    _lcd_delay_us_small(1);
    command=PIN&0xF0; // read high nibble
    PORT&=~(1<<E_PIN); // E=0
    _lcd_delay_us_small(2);
    PORT|=1<<E_PIN; // E=1
    _lcd_delay_us_small(1);
    command|=PIN>>4; // read low nibble
    PORT&=~(1<<E_PIN); // E=0
    return command;
}

uint8_t lcd_read_data(void) {
    uint8_t data;
    DDR|=1<<E_PIN|1<<RW_PIN|1<<RS_PIN;
    DDR&=~0xF0;
    PORT|=1<<RW_PIN|1<<RS_PIN|0xF0; // R/!W= 1 (Read) RS=1 and Pullup inputs 
    _lcd_delay_us_small(2);
    PORT|=1<<E_PIN;
    _lcd_delay_us_small(1);
    data=PIN&0xF0;
    PORT&=~(1<<E_PIN);
    _lcd_delay_us_small(2);
    PORT|=1<<E_PIN;
    _lcd_delay_us_small(1);
    data|=PIN>>4;
    PORT&=~(1<<E_PIN);
    return data;
}

static void wait(void) {
    while (lcd_read_command()&0x80);
}

static void pos_pulse_E(void) {
    _lcd_delay_us_small(2);
    PORT|=1<<E_PIN; // E=1
    _lcd_delay_us_small(1);
    PORT&=~(1<<E_PIN); // E=0
}

void lcd_write_command(uint8_t command) {
    wait();
    DDR|=1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0; // controlbus and databus output
    PORT&=~(1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0);
    PORT|=command&0xF0; // all control signals low RS=0 R/!W=0
    pos_pulse_E();// write high nibble
    PORT&=~(1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0);
    PORT|=command<<4; // all control signals low RS=0 R/!W=0
    pos_pulse_E();// write low nibble
}

void lcd_write_data(uint8_t data) {
    wait();
    DDR|=1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0;
    PORT&=~(1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0);
    PORT|=(data&0xF0)|1<<RS_PIN; // RS=1 other control signals 0 R/!W=0
    pos_pulse_E();
    PORT&=~(1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0);
    PORT|=(data<<4)|1<<RS_PIN;
    pos_pulse_E();
}

void lcd_init(void) {
    DDR|=1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0;
    _lcd_delay_us(15000);
    PORT&=~(1<<E_PIN|1<<RW_PIN|1<<RS_PIN|0xF0); 
    PORT|=0x30; // all control signals low RS=0 R/!W=0
    pos_pulse_E(); 
    _lcd_delay_us(4100);
    pos_pulse_E(); 
    _lcd_delay_us(100);
    pos_pulse_E(); 
    _lcd_delay_us(100);
    PORT&=~0x10; 
    pos_pulse_E(); 
    _lcd_delay_us(100);
    lcd_write_command(0x28);
    lcd_write_command(0x06);
    lcd_cls();
    lcd_cursor(true, true);
}

void lcd_cls(void) {
    lcd_write_command(0x01);
}

void lcd_home(void) {
    lcd_write_command(0x02);
}

void lcd_cursor(bool cursorOn, bool cursorBlinks) { 
    lcd_write_command(0x0C+(cursorOn?0x02:0)+(cursorBlinks?0x01:0));
}

void lcd_goto(uint8_t row, uint8_t column) {
    if (row<2 && column<16) {
        lcd_write_command(0x80+row*0x40+column);
    }
}

uint8_t lcd_get_row(void) {
    wait();
    return lcd_read_command()&1<<6 ? 1 : 0;

}

uint8_t lcd_get_column(void) {
    wait();
    return lcd_read_command()&0x3f;
}

void lcd_putc(char data) { 
    lcd_write_data(data);
}

void lcd_puts(char *s) {
    while(*s) {
        lcd_putc(*s++);
    }
}

void lcd_puts_P(const char* PROGMEM s) {
    char c; 
    while ((c = pgm_read_byte(s++))) 
        lcd_putc(c);
}

Best Answer

The "obvious" possibility is that something other aspect of your software is trampling on PORTC and/or DDRC. However, I think your problem is a tiny bit more subtle. Did you notice that PORTC has JTAG pins in it? You had better be disabling that interface somehow or not much about that port is going to be "General Purpose." The easiest way to do this is to disable the JTAGEN fuse.

C.0 and C.1 are the TWI pins as well. Make sure you haven't got the TWI interface enabled or again this won't work. That is to say - make sure that TWCR bit 2 is cleared (reads 0). That is the default state, so unless you are doing something with I2C in your system this seems like an unlikely possibility.

The code is also using soft delays, maybe you have more capacitance on your PORTC pins or something. You could try making the delays longer....