Тахометр на OLED (часть 2)

Обсуждаем электронику на колесах. Нужен увлажнитель воздуха для Камаза? Вам сюда.
Ответить
Аватара пользователя
Champ
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср апр 10, 2013 23:26:08

Тахометр на OLED (часть 2)

Сообщение Champ »

Всем доброго времени суток! Есть схема цифрового тахометра на ОЛЕД дисплее,
который здесь http://radiokot.ru/forum/viewtopic.php? ... 8#p1854078 уже обсуждался. Прошло не мало времени, была проблема с дисплеем, первый раз выслали не тот (на 15 пин). Но теперь он собран, его
нужно запрограммировать. Я начал с дисплея — UG-2832HSWEG02.
Контроллер дисплея — SSD1306. Проблема в том, что я не знаю
точный адресс ведомого (управляется по I2C), в даташите на
дисплей он не указан. В даташите на контроллер дисплея сказано,
что адресс ведомого: 011110xRW, где x - 0, если на ножке SA0 (D/C#)
низкий уровень и 1, если высокий. Но у этого дисплея нет ножки D/C#.
Соответственно может быть 2 адреса: 01111010b (0x7A) или 01111000b (0x78).
Был написан код инициализации и частичного заполнения дисплея пикселями.
Было проверено оба адреса. В итоге – ничего не работает)
Дисплей либо ничего не выводит, либо иногда рандомно загораются пиксели
(мусор в памяти дислея). По началу ножка RES# дисплея висела в воздухе,
но потом её подключил к свободной ноге контроллера, думал из за этого
может не работать, в итоге опять ничего. Прошу вашей помощи, где я допустил ошибку?)
Прилагаю исходник и схему всего этого чуда. Скачать исходник http://yadi.sk/d/pwbeA84HLGrXZ
Схема
СпойлерИзображение
Изображение
Исходник
Спойлер.include "m8Adef.inc"

.macro outi
ldi r16, @1
out @0, r16
.endm

.dseg
.eseg
.cseg
.org 0x00
rjmp Reset
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
.org 0x13
Reset:
; initialization of RAM
outi SPL, Low(RAMEND)
outi SPH, High(RAMEND)
; ===

; flushing of RAM
ldi ZL, Low(SRAM_START)
ldi ZH, High(SRAM_START)
clr r16
Flush:
st Z+, r16
cpi ZH, High(RAMEND)
brne Flush
cpi ZL, Low(RAMEND)
brne Flush
; ===============

; ports configuration
outi DDRB, 0
outi PORTB, 0xFF

outi DDRC, 0
outi PORTC, 0xFF

outi DDRD, 0
outi PORTD, 0xFF
; ===================

rcall OLED_Init

;========= test =========
rcall IIC_Start ; send start condition

ldi r16, 0x78 ; set slave address
rcall IIC_SendByte

ldi r16, 0x40 ; control byte for send data
rcall IIC_SendByte

; partial filling of the display
ldi r16, 0xFF
ldi r17, 0xFF
NextByte:
rcall IIC_SendByte
dec r17
brne NextByte

rcall IIC_Stop ; send stop condition
;========= test =========

MainLoop:
rjmp MainLoop

Delay:
ldi r18, 0xFF
D2:
ldi r19, 0xFF
D1:
dec r19
brne D1
dec r18
brne D2

ret

OLED_Init:
; reset of display
outi DDRC, 0x4 ; set PC2 to out
rcall Delay
rcall Delay
outi PORTC, 0 ; set 0 to PC2
rcall Delay
rcall Delay
outi PORTC, 0x4 ; set 1 to PC2
rcall Delay
rcall Delay
; ================

rcall IIC_Init ; initialize of TWI

rcall IIC_Start ; send start condition

ldi r16, 0x78 ; set slave address
rcall IIC_SendByte

ldi r16, 0x00 ; control byte for send command
rcall IIC_SendByte

ldi r16, 0xAE ; turning off display
rcall IIC_SendByte

ldi r16, 0xD5 ; set clock divide ratio/oscillator frequency
rcall IIC_SendByte
ldi r16, 0x80
rcall IIC_SendByte

ldi r16, 0xA8 ; set multiplex ratio
rcall IIC_SendByte
ldi r16, 0x3F
rcall IIC_SendByte

ldi r16, 0xD3 ; set display offset
rcall IIC_SendByte
ldi r16, 0x00
rcall IIC_SendByte

ldi r16, 0x40 ; set display start line
rcall IIC_SendByte

ldi r16, 0x8D ; set charge pump
rcall IIC_SendByte
ldi r16, 0x14 ; turn on internal DC/DC converter
rcall IIC_SendByte

rcall Delay
rcall Delay
rcall Delay
rcall Delay

ldi r16, 0xA1 ; set segment re-map
rcall IIC_SendByte

ldi r16, 0xC8 ; set COM output scan direction
rcall IIC_SendByte

ldi r16, 0xDA ; set COM pins hardware configuration
rcall IIC_SendByte
ldi r16, 0x02
rcall IIC_SendByte

ldi r16, 0x81 ; set contrast control
rcall IIC_SendByte
ldi r16, 0x8F
rcall IIC_SendByte

ldi r16, 0xD9 ; set pre-charge period
rcall IIC_SendByte
ldi r16, 0xF1 ; internal DC/DC converter
rcall IIC_SendByte

ldi r16, 0xDB ; set VCOMH deselect level
rcall IIC_SendByte
ldi r16, 0x40
rcall IIC_SendByte

ldi r16, 0xA4 ; set entire display on/off
rcall IIC_SendByte

ldi r16, 0xA6 ; set normal/inverse display
rcall IIC_SendByte

ldi r16, 0x20 ; set addressing mode
rcall IIC_SendByte
ldi r16, 0x0
rcall IIC_SendByte

ldi r16, 0xAF ; turn on display
rcall IIC_SendByte

rcall IIC_Stop ; send stop condition

ret

IIC_Init:
outi TWBR, 12 ; set bitrate of TWI
outi TWSR, 0 ; for 4MHz chip freq
ret

IIC_Start:
outi TWCR, 1 << TWINT | 1 << TWSTA | 1 << TWEN | 0 << TWIE
IIC_S:
in r16, TWCR
andi r16, 1 << TWINT
breq IIC_S
ret

IIC_SendByte:
out TWDR, r16
outi TWCR, 1 << TWINT | 1 << TWEN | 0 << TWIE
IIC_B:
in r16, TWCR
andi r16, 1 << TWINT
breq IIC_B
ret

IIC_RecvByte:
outi TWCR, 1 << TWINT | 1 << TWEN | 1 << TWEA | 0 << TWIE
IIC_R:
in r16, TWCR
andi r16, 1 << TWINT
breq IIC_R
ret

IIC_RecvLastByte:
outi TWCR, 1 << TWINT | 1 << TWEN | 0 << TWEA | 0 << TWIE
IIC_RL:
in r16, TWCR
andi r16, 1 << TWINT
breq IIC_RL
ret

IIC_Stop:
outi TWCR, 1 << TWINT | 1 << TWSTO | 1 << TWEN | 0 << TWIE
IIC_ST:
in r16, TWCR
andi r16, 1 << TWSTO
breq IIC_ST
ret
Реклама
Аватара пользователя
Champ
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср апр 10, 2013 23:26:08

Re: Тахометр на OLED (часть 2)

Сообщение Champ »

Неужели никто не может помочь?
Реклама
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Re: Тахометр на OLED (часть 2)

Сообщение mr_smit »

Champ писал(а):Дисплей либо ничего не выводит, либо иногда рандомно загораются пиксели
Значит инициализация проходит.

Я на STM32 Discovery его запустил. Адрес дисплея 0x78. Взял у китайцев из исходников. Там есть одна фишка. Этот дисплей бывает 2-х типов: 128х64 и 128х32. Размер страницы 128х8 пикс. Т.е. для 128х64 это 8 строк высотой 8 пикс, для 128х32 это 4 строки высотой 8 пикс. Так вот, для дисплея 128х32 самая верхняя страница это 4!!!! Т.е. весь дисплей занимает с 4-ой по 7-ю страницу. Получается что это обрезанная сверху версия 128х64 у которого как и положено с 0 по 7 страницу. Об этом почему то нигде не сказано. Я долго тупил почему не работает. Потом уже методом тыка разобрался. Т.е. начинайте вывод данных не в 0 страницу, а в 4-ю.

В АСМе не силен, но вот код инициализации под Си:
Спойлерvoid SSD1306_Init()
{
writec(0xAE); //display OFF

writec(0xA8); //set multiplex ratio
writec(0x3F); //

writec(0xD3); //set display offset
writec(0x00); //

writec(0x40); //set display start line

writec(0xA1); //set segment re-map

writec(0xC8); //set com output scan direction

writec(0xDA); //set COM pins
writec(0x02); //

writec(0x81); //set contract control
writec(0xFF); //255

writec(0xA4); //disable entire display on

writec(0xA6); //set normal display

writec(0xD5); //set osc frequency
writec(0x80); //

writec(0x8D); //enable charge pump regulator
writec(0x14);

writec(0xD9); //set pre-charge period
writec(0xF1); // Под вопросом. Можно не включать в инициализацию.

writec(0xDB); //set VcomH
writec(0x30); // Под вопросом. Можно не включать в инициализацию.

writec(0xAF); //display ON
}
Вывод картинки:
Спойлерvoid showpic()
{
uint32_t x;

writec(0x20); // горизонтальная адрессация
writec(0x00); //

writec(0x21); // по оси X от 0 до 127
writec(0x00); //
writec(0x7F); //

writec(0x22); // по оси Y от 4-ой страницы до 7-ой
writec(0x04); // (для дисплея 128х32)
writec(0x07); //

for(x=0;x<512;x++)
{
writed(picture[x]);
}
}
Нельзя всё знать, достаточно понимать.
Аватара пользователя
Champ
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср апр 10, 2013 23:26:08

Re: Тахометр на OLED (часть 2)

Сообщение Champ »

Да, адрес подходит, пиксели загораются рандомно, но не могу изменить контрастность или вывести что-либо на него. Если есть возможность, буду благодарен за тестовую прошивку, хочу понять дело в моей прошивке или в железе.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Re: Тахометр на OLED (часть 2)

Сообщение mr_smit »

Так вместо writed(picture[x]); напишите 0xFF. Просто белым зальется экран.
Нельзя всё знать, достаточно понимать.
Реклама
Аватара пользователя
Champ
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср апр 10, 2013 23:26:08

Re: Тахометр на OLED (часть 2)

Сообщение Champ »

Уже пробовал так делать, пиксели все равно горят рандомно...
Реклама
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Re: Тахометр на OLED (часть 2)

Сообщение mr_smit »

Такого не может быть. Значит не правильно что то делаете. Получается у вас посыл команды проходит, а посыл данных нет. Смотрите свою функцию отправки данных (не команды). Судя по англоязычным комментариям в asm коде - вы не сами писали это. Возможно поэтому у вас и не работает... Разбирайтесь.
Нельзя всё знать, достаточно понимать.
Аватара пользователя
Champ
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср апр 10, 2013 23:26:08

Re: Тахометр на OLED (часть 2)

Сообщение Champ »

код написан мной с нуля. англоязычные коментарии мои. функции для работы с и2с дернуты у ди хальта изиэлектроникс, просто я их рерайтил, обозвал по своему. Фунуция отправки данных отличается лишь контрольным байом, который и говорит дисплею что мы в него отправляем. Старт->контрольный байт->байт днных->еще байт данных->стоп. Вечером перепишу в си
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Re: Тахометр на OLED (часть 2)

Сообщение mr_smit »

Champ писал(а):Старт->контрольный байт->байт днных->еще байт данных->стоп
Вроде как надо:

Старт -> адрес устройства -> адрес регистра -> данные -> стоп

И команда/данные отличаются адресом регистра (0x00 или 0x40), а не как вы говорите контрольным байтом.

Может поможет. Для STM32:
Спойлерvoid writec(unsigned char COM)
{
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter); // адрес устройства
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

I2C_SendData(I2C1, 0x00); // адрес регистра
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_SendData(I2C1, COM); // данные
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_GenerateSTOP(I2C1, ENABLE);
}


//===================
void writed(unsigned char DATA)
{
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter); // адрес устройства
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

I2C_SendData(I2C1, 0x40); // адрес регистра
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_SendData(I2C1, DATA); // данные
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

I2C_GenerateSTOP(I2C1, ENABLE);
}
Нельзя всё знать, достаточно понимать.
Ответить

Вернуться в «АвтоМотоВело»