Доброго сем времени суток!
Решил разобраться с подключением ЖК дисплея (winstar 1602) с расширителем портов PCF8574 к микроконтроллеру ATmega8.
Собрал вот такую схему в протеусе. Один диспей подключен напрямую к ножкам контроллера (я на него выводил значение регистра статуса модуля TWI). Второй дисплей подключен через PCF8574.
Спойлер

Написал вот такой код в AtmelStudio
Спойлер
Код:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#define RS_1 PORTD |= (1<<2);
#define RS_0 PORTD &= ~(1<<2);
#define E_1 PORTD |= (1<<3);
#define E_0 PORTD &= ~(1<<3);
unsigned char TWI_Status = 0;
void LCD_pin_setup(void);
void LCD_commands(unsigned char command);
void LCD_data(unsigned char data);
void LCD_settings(void);
void set_cursor(unsigned char y, unsigned char x);
void print_string(char words[]);
void TWI_Settings(void);
void TWI_Start(void);
void TWI_Stop(void);
void TWI_Write_byte(unsigned char data);
void LCD_TWI_command(unsigned char data);
void LCD_TWI_data(unsigned char data);
void LCD_TWI_settings(void);
int main(void)
{
LCD_pin_setup();
LCD_settings();
TWI_Settings();
TWI_Start();
TWI_Write_byte(0b01001110);
LCD_TWI_settings();
TWI_Stop();
TWI_Start();
TWI_Write_byte(0b01001110);
LCD_TWI_data('A');
LCD_TWI_data('B');
LCD_TWI_data('C');
TWI_Stop();
TWI_Status = TWSR;
set_cursor(1,0);
print_string("TWI status - ");
char str[16];
itoa(TWI_Status, str, 16);
print_string(str);
set_cursor(2,0);
LCD_data('A');
LCD_data('B');
LCD_data('C');
while (1)
{
}
}
void TWI_Settings(void)
{
TWBR = 2;
TWSR &= ~((1<<TWPS1) | (1<<TWPS0));
}
void TWI_Start(void)
{
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)))
;
}
void TWI_Stop(void)
{
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}
void TWI_Write_byte(unsigned char data)
{
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)))
;
}
void LCD_TWI_command(unsigned char data)
{
unsigned char val;
val = (data | (1<<3) | (1<<2)) & ~(1<<0);
TWI_Write_byte(val);
_delay_us(50);
val &= ~(1<<2);
TWI_Write_byte(val);
_delay_us(50);
val = ((data << 4) | (1<<3) | (1<<2)) & ~(1<<0);
TWI_Write_byte(val);
_delay_us(50);
val &= ~(1<<2);
TWI_Write_byte(val);
_delay_us(50);
}
void LCD_TWI_data(unsigned char data)
{
unsigned char val;
val = data | (1<<3) | (1<<2) | (1<<0);
TWI_Write_byte(val);
_delay_us(50);
val &= ~(1<<2);
TWI_Write_byte(val);
_delay_us(50);
val = (data << 4) | (1<<3) | (1<<2) | (1<<0);
TWI_Write_byte(val);
_delay_us(50);
val &= ~(1<<2);
TWI_Write_byte(val);
_delay_us(50);
}
void LCD_TWI_settings(void)
{
_delay_ms(15);
LCD_TWI_command(0b00110000);
_delay_ms(5);
LCD_TWI_command(0b00110000);
_delay_us(110);
LCD_TWI_command(0b00110000);
_delay_ms(1);
LCD_TWI_command(0b00000010);
_delay_ms(2);
LCD_TWI_command(0b00101000);
_delay_ms(1);
LCD_TWI_command(0b00001101);
_delay_ms(1);
LCD_TWI_command(0b00000001);
_delay_ms(2);
LCD_TWI_command(0b00000110);
_delay_ms(1);
}
void LCD_pin_setup(void)
{
DDRD |= (1<<7) | (1<<6) | (1<<5) | (1<<4) | (1<<3) | (1<<2);
PORTD &= ~((1<<7) | (1<<6) | (1<<5) | (1<<4) | (1<<3) | (1<<2));
}
void LCD_commands(unsigned char command)
{
PORTD = command;
RS_0;
E_1;
_delay_us(50);
E_0;
_delay_us(50);
PORTD = (command << 4);
RS_0;
E_1;
_delay_us(50);
E_0;
_delay_us(50);
}
void LCD_data(unsigned char data)
{
PORTD = data;
RS_1;
E_1;
_delay_us(50);
E_0;
_delay_us(50);
PORTD = (data << 4);
RS_1;
E_1;
_delay_us(50);
E_0;
_delay_us(50);
}
void LCD_settings(void)
{
_delay_ms(15);
LCD_commands(0b00110000);
_delay_ms(5);
LCD_commands(0b00110000);
_delay_us(110);
LCD_commands(0b00110000);
_delay_ms(1);
LCD_commands(0b00000010);
_delay_ms(2);
LCD_commands(0b00101000);
_delay_ms(1);
LCD_commands(0b00001100);
_delay_ms(1);
LCD_commands(0b00000001);
_delay_ms(2);
LCD_commands(0b00000110);
_delay_ms(1);
}
void set_cursor(unsigned char y, unsigned char x)
{
switch(y)
{
case 1: LCD_commands(x | 0b10000000);
break;
case 2: LCD_commands((x + 0x40) | 0b10000000);
break;
}
}
void print_string(char words[])
{
unsigned char z;
for (z = 0; words[z] != '\0'; z++)
{
LCD_data(words[z]);
}
}
И при запуске симуляции в протеусе получаю вот такой результат.
Спойлер

На дисплее подключенном на прямую к микроконтроллеру все отображается как надо, а на дисплее подключенном по TWI пустота и курсор смещенный на четыре символа в право. Хотя отправлялись три одиночных символа.
Если отправлять одиночный символ, то один дисплей покажет то что было отправлено, а второй совсем другой символ.
Спойлер

Уважаемые коты, помогите разобраться, что я мог сделать не так. Сильно тапками не пинайте, в программировании не очень силен.
Заранее всем спасибо за оказанную помощь!
P.S.
В железе работает так же как и в протеусе.
Прилагаю архив проекта в AtmelStudio 7 и проекта в протеусе
Вложение:
LCD display.zip [38.25 KiB]
Скачиваний: 28
Вложение:
LCD.zip [15.12 KiB]
Скачиваний: 23