Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

SSD1306 по I2C

Сб фев 24, 2018 13:52:41

День добрый, пытаюсь завести сабж, пока безуспешно (ну точнее включается/инициализируется, но чистятся только первые 8 линий), ткните носом по возможности куда копать.

камень ATmega328p использую аппаратный TWI (подтяжка к питанию 10 КОм), внешний кварц на 16 Mhz
среда Atmel Studio 7

к методам работы с TWI вроди притензий нет (часы читаются и устанавливаются)

Код:
#define F_CPU           16000000UL            //задаем частоту МК
#define F_SCL           100000L               //задаем частоту I2C
#define LCD_module   0x78

//БИБЛИОТЕКИ
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

//===I2C====
void I2C_Init()
{
   TWSR = 0;
   TWBR = ((F_CPU/F_SCL)-16)/2;
   TWCR =(1<<TWIE)|(1<<TWEN);
}
void I2C_Start()
{
   _delay_us(5);
   TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
}
void I2C_Stop()
{
   TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
void I2C_Send_Device_Address(uint8_t dev_address, bool write)
{
   if (write == true)
   {
      TWDR = dev_address;
   }
   else
   {
      TWDR = dev_address|1;
   }
   TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
}
void I2C_Send_Register_Address(uint8_t reg_address)
{
   TWDR = reg_address;
   TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
}
void I2C_Send_Data_ACK(uint8_t data)
{
   TWDR = data;
   TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
}
void I2C_Send_Data_NACK(uint8_t data)
{
   TWDR = data;
   TWCR =(1<<TWINT)|(1<<TWEN)|(0<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
}
uint8_t I2C_Read_Data_ACK()
{
   uint8_t Result = 0;
   TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
   Result = TWDR;
   return Result;
}
uint8_t I2C_Read_Data_NACK()
{
   uint8_t Result = 0;
   TWCR =(1<<TWINT)|(1<<TWEN)|(0<<TWEA);
   while(!(TWCR &(1<<TWINT)))
   {
   }
   Result = TWDR;
   return Result;
}

//===LCD===
#define      Data_array   0b01000000      //Передача нескольких байт данных
#define      Data              0b11000000      //Передача одного байта данных
#define      Command      0b10000000      //Передача байта комманды

const uint8_t Init_Sequence[18] PROGMEM =
{
   0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,
   0x81,0x7F,0xA4,0xA6,0xD5,0x80,0x8D,0x14,0xAF
};

void LCD_Clear_Display()
{
   I2C_Start();
   I2C_Send_Device_Address(LCD_module, true);
   
   I2C_Send_Data_ACK(Command);
   I2C_Send_Data_ACK(0x20);
   I2C_Send_Data_ACK(Command);
   I2C_Send_Data_ACK(0x00);
   
   I2C_Send_Data_ACK(Data_array);
   for (uint8_t page= 0; page<8; page++)
   {
      for (uint8_t column=0; column<128; column++)
      {
         I2C_Send_Data_ACK(0x00);
      }
   }
   I2C_Stop();
}
void LCD_init()
{
   I2C_Start();
   I2C_Send_Device_Address(LCD_module, true);
   for (uint8_t i=0; i<18; i++)
   {
      uint8_t command = pgm_read_byte(&(Init_Sequence[i]));
      I2C_Send_Data_ACK(Command);
      I2C_Send_Data_ACK(command);
   }

   I2C_Stop();
}

int main()
{
   IO_Init();
   I2C_Init();
   
   sei();

   _delay_ms(500);
   LCD_init();
   _delay_ms(500);
   LCD_Clear_Display();

   while (true)
   {
      PORTC = PORTC | (1<<PORTC2);

            
      PORTC = PORTC & ~(1<<PORTC2);
   }
}

Re: SSD1306 по I2C

Сб фев 24, 2018 22:09:33

ручной выбор страниц для очистки, функция установки страницы все равно понадобится

Re: SSD1306 по I2C

Вт фев 27, 2018 20:15:48

Тоесть перед очисткой использовать страничный режим адрессации, а потом опять горизонтальный?

Re: SSD1306 по I2C

Ср фев 28, 2018 11:07:57

функции использовать согласно настройкам адресации памяти

Re: SSD1306 по I2C

Ср фев 28, 2018 17:47:42

такц стоп, я инициализирую его в горизонтальный режим адрессации, но при очистке нужно в ручную щелкать страницы или я как то не правильно понял первое сообщение? или для очистки нужен постраничный режим?
Ответить