Например TDA7294

Форум РадиоКот • Просмотр темы - Подключение LCD1602 + PCF8574 к ATmega8
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт июн 17, 2025 21:03:27

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 12:13:44 
Родился

Зарегистрирован: Сб сен 28, 2024 16:19:04
Сообщений: 12
Рейтинг сообщения: 0
Доброго сем времени суток!
Решил разобраться с подключением ЖК дисплея (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[]); //функция вывода строк на дисплей

//прототипы функций для ЖК дисплея с модулем TWI
void TWI_Settings(void); //функция настроек модуля TWI
void TWI_Start(void); //функция формирования условия "Старт" для модуля TWI
void TWI_Stop(void); //функция формирования условия "Стоп" для модуля TWI
void TWI_Write_byte(unsigned char data); //функция передачи байта по шине TWI
void LCD_TWI_command(unsigned char data); //функция передачи команд ЖК дисплею по интерфейсу TWI
void LCD_TWI_data(unsigned char data); //функция передачи данных ЖК дисплею по интерфейсу TWI
void LCD_TWI_settings(void); //функция настройки ЖК дисплея подключенного к микроконтроллеру по TWI (I2C) модулю

int main(void)
{
    LCD_pin_setup();
   LCD_settings();
   TWI_Settings();
   
   TWI_Start(); //отправка условия Старт
    TWI_Write_byte(0b01001110); //отправка адреса микросхемы PCF + бит записи
   LCD_TWI_settings();
   TWI_Stop();
   
   TWI_Start(); //отправка условия Старт
   TWI_Write_byte(0b01001110); //отправка адреса микросхемы PCF + бит записи
   LCD_TWI_data('A');
   LCD_TWI_data('B');
   LCD_TWI_data('C');
   TWI_Stop();
      
   TWI_Status = TWSR; //значение регистра статуса модуля TWI
   
   set_cursor(1,0); //установка курсора в позицию
   print_string("TWI status - "); //печать строки
   char str[16];
   itoa(TWI_Status, str, 16); //преобразование значения переменной статуса TWI в символьный массив
   print_string(str); //печать значения переменной статуса TWI
   
   set_cursor(2,0); //установка курсора в позицию
   LCD_data('A');
   LCD_data('B');
   LCD_data('C');
    while (1)
    {
    }
}

//============== функции для ЖК дисплея подключенного к микроконтроллеру через модуль TWI (I2C)
void TWI_Settings(void) //функция настроек модуля TWI
{
   TWBR = 2;
   TWSR &= ~((1<<TWPS1) | (1<<TWPS0));
}

void TWI_Start(void) //функция формирования условия "Старт" для модуля TWI
{
   TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
   while(!(TWCR & (1<<TWINT)))
   ;
}

void TWI_Stop(void) //функция формирования условия "Стоп" для модуля TWI
{
   TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}

void TWI_Write_byte(unsigned char data) //функция записи байта по шине TWI
{
   TWDR = data;
   TWCR = (1<<TWINT) | (1<<TWEN);
   while(!(TWCR & (1<<TWINT)))
   ;
}

void LCD_TWI_command(unsigned char data) //функция передачи команд ЖК дисплею по интерфейсу TWI
{
   unsigned char val;
   val = (data | (1<<3) | (1<<2)) & ~(1<<0); //установка 3-го бита, включение подсветки дисплея
   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); //установка 3-го бита, включение подсветки дисплея
   TWI_Write_byte(val);
   _delay_us(50);
   val &= ~(1<<2);
   TWI_Write_byte(val);
   _delay_us(50);
}

void LCD_TWI_data(unsigned char data) //функция передачи данных ЖК дисплею по интерфейсу TWI
{
   unsigned char val;
   val = data | (1<<3) | (1<<2) | (1<<0); //установка 3-го бита, включение подсветки дисплея
   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); //установка 3-го бита, включение подсветки дисплея
   TWI_Write_byte(val);
   _delay_us(50);
   val &= ~(1<<2);
   TWI_Write_byte(val);
   _delay_us(50);
}

void LCD_TWI_settings(void) //функция настройки ЖК дисплея подключенного к микроконтроллеру по TWI (I2C) модулю
{
   _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); //четырех битный интерфейс, дисплей двух строчный, размер шрифта 5*8
   _delay_ms(1);
   LCD_TWI_command(0b00001101); //включение дисплея, выключение курсора, курсор моргает (младший бит - 1 моргает, 0 не мограет)
   _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; //низкий потенциал на выводе RS
   E_1; //высокий потенциал на выводе Е
   _delay_us(50);
   E_0; //низкий потенциал на выводе Е
   _delay_us(50);
   PORTD = (command << 4);
   RS_0; //низкий потенциал на выводе RS
   E_1; //высокий потенциал на выводе Е
   _delay_us(50);
   E_0; //низкий потенциал на выводе Е
   _delay_us(50);
}

void LCD_data(unsigned char data) //функция передачи данных
{
   PORTD = data;
   RS_1; //высокий потенциал на выводе RS
   E_1; //высокий потенциал на выводе Е
   _delay_us(50);
   E_0; //низкий потенциал на выводе Е
   _delay_us(50);
   PORTD = (data << 4);
   RS_1; //высокий потенциал на выводе RS
   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); //четырех битный интерфейс, дисплей двух строчный, размер шрифта 5*8
   _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) //функция установки курсора в строке (параметр y = 1 или 2) и на заданной позиции этой строки (параметр х от 0 до 15)
{
   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]
Скачиваний: 11

Вложение:
LCD.zip [15.12 KiB]
Скачиваний: 10


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 13:20:20 
Говорящий с текстолитом

Карма: 25
Рейтинг сообщений: 450
Зарегистрирован: Сб май 05, 2012 20:24:52
Сообщений: 1612
Откуда: KN34PC, Болгария
Рейтинг сообщения: 1
строка 98:
Код:
val = (data | (1<<3) | (1<<2)) & ~(1<<0); //установка 3-го бита, включение подсветки дисплея

в
Код:
val = ((data & 0b11110000) | (1<<3) | (1<<2)) & ~(1<<0); //установка 3-го бита, включение подсветки дисплея


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 14:12:47 
Родился

Зарегистрирован: Сб сен 28, 2024 16:19:04
Сообщений: 12
Рейтинг сообщения: 0
строка 98:
Код:
val = (data | (1<<3) | (1<<2)) & ~(1<<0); //установка 3-го бита, включение подсветки дисплея

в
Код:
val = ((data & 0b11110000) | (1<<3) | (1<<2)) & ~(1<<0); //установка 3-го бита, включение подсветки дисплея


Спасибо, заработало.
На реальном железе на дисплее все отображается нормально. Различные символы, знаки, все отображается так как надо.
Протеус нормально отображает лишь "A, a, 1 и !". При отправке других символов, знаков на дисплее полная ерунда.
Главное что в железе все работает как надо.

И еще вопрос.
А можно поподробнее объяснить, зачем с байтом передаваемой команды надо делать вот это: data & 0b11110000 ?

Update
Сделал вот так: data & 0b11110000 и при передаче байта данных, и в протеусе все начало отображаться нормально.
Теперь еще болле стало интересно для чего необходимо так делать?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 15:50:37 
Говорящий с текстолитом

Карма: 25
Рейтинг сообщений: 450
Зарегистрирован: Сб май 05, 2012 20:24:52
Сообщений: 1612
Откуда: KN34PC, Болгария
Рейтинг сообщения: 0
См. "битовая маска" в булевой алгебры. Значение бит 1 произошло от значения data, а этого не должно быть.
Обычно проще сбросить все биты на ноль (которые следуют за изменением) с побитово И (&),
а затем добавить новые значения с помощью побитово ИЛИ (|).
(частично пользуюсь переводчиком)


Вернуться наверх
 
В продаже новые LED-драйверы XLC компании MEAN WELL с диммингом нового поколения

Компания MEAN WELL пополнила ассортимент своей широкой линейки светодиодных драйверов новым семейством XLC для внутреннего освещения. Главное отличие – поддержка широкого спектра проводных и беспроводных технологий диммирования. Новинки представлены в MEANWELL.market моделями с мощностями 25 Вт, 40 Вт и 60 Вт. В линейке есть модели, работающие как в режиме стабилизации тока (СС), так и в режиме стабилизации напряжения (CV) значением 12, 24 и 48 В.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 16:07:31 
Модератор
Аватар пользователя

Карма: 153
Рейтинг сообщений: 2907
Зарегистрирован: Сб авг 14, 2010 15:05:51
Сообщений: 18719
Откуда: г. Озерск, Челябинская обл.
Рейтинг сообщения: 1
Медали: 1
Лучший человек Форума 2017 (1)
Denis-1307 писал(а):
Теперь еще болле стало интересно для чего необходимо так делать?
потому что байт передается за 2 раза - по 4 старших бита.
поэтому нужно сначала сбросить 4 младших бита, а потом к байту добавить нужные биты управления.
а когда передаешь 4 младших бита, то сначала байт сдвигается влево 4 раза (чтобы младшие биты заняли позицию старших), и младшие биты после сдвигов освобождаются сами.

_________________
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Подключение LCD1602 + PCF8574 к ATmega8
СообщениеДобавлено: Пт май 30, 2025 16:10:51 
Родился

Зарегистрирован: Сб сен 28, 2024 16:19:04
Сообщений: 12
Рейтинг сообщения: 0
Спасибо, понял.


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y