# Microcontrol port for lcd

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 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);
PORT&=~(1<<E_PIN); // E=0
_lcd_delay_us_small(2);
PORT|=1<<E_PIN; // E=1
_lcd_delay_us_small(1);
PORT&=~(1<<E_PIN); // E=0
return command;
}

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) {
}

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) {
}

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();
}

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;
lcd_putc(c);
}

• What microcontroller are you using? Maybe PORTC has less than 7 pins (From the code you linked, I can see that the LCD needs at least 7 pins to function correctly). – m.Alin Jul 11 '12 at 13:35
• ATMEGA16, portc has also 8 pins. i have also wiring the pins correct to databus lines – Power-Mosfet Jul 11 '12 at 13:40
• Can you try it on port B or D, or is this on a PCB (not breadboard)? – stevenvh Jul 11 '12 at 15:04
• just a chip on breadboard. I Have also tried port B and D, nothing on display it only works on port A. – Power-Mosfet Jul 11 '12 at 15:12
• Just to throw this out there, have you looked for / tried a different library? – vicatcu Jul 11 '12 at 16:59

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....

• I had already disabled the jtag fuse. I use the SPI to program the chip – Power-Mosfet Jul 11 '12 at 14:52
• I just don't get, it only works on port A? – Power-Mosfet Jul 11 '12 at 14:54
• OP says it doesn't work on Port B or D either, so I don't think you'll find it in alternative functions. – stevenvh Jul 11 '12 at 15:15
• @Power-Mosfet thanks for the accept, but what did it turn out to be? – vicatcu Jul 12 '12 at 13:36

I had a look at the library file and it appears that it has PORTA hard-coded in it; I thought it used the first list of defines. So it's PORTA all over, also in the functions you didn't edit.

edit
You updated your code, and it looks like all PORTAs have been replaced. The best way to make sure is to #undefine PORTA, PINA and DDRA. The compiler will complain if there's any trace of either of them left.

• I have added those to make it dynamic. with or without those defines same result – Power-Mosfet Jul 11 '12 at 15:24
• But did you change the other functions too? lcd_init, for instance, doesn't appear in your code, and also refers to PortA – stevenvh Jul 11 '12 at 15:26
• I Have modify all functions to use the defines. thought it will be too much to post the throughout the library. – Power-Mosfet Jul 11 '12 at 15:30
• But they're not all in the code you posted. I checked that for any overlooked PortA, and there isn't any, but there could be one in the rest of the code, which you didn't post. Have you checked that? Twice? – stevenvh Jul 11 '12 at 15:32
• Did you try #undefine PORTA? I keep believing there must be still one left somewhere. If it's undefined you should get errors if there is still one in the code. – stevenvh Jul 11 '12 at 15:46