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