ATmega8 + OLED SSD1306

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Just_Fluffy писал(а):Если заранее известна частота тактирования SPI - вместо цикла опроса флага готовности просто ставятся NOPы в нужном количестве. Можно даже не высчитывать, а заведомо поставив больше нопов, чем надо, смотреть логическим анализатором и посчитать, сколько нопов надо выбросить.
Да. действительно. Позже попробую. При перерисовке полей выгода не существенна, а вот при заливке всего дисплея думаю актуально..

НОП-ы скорее всего без анализатора определятся, там при убавлении НОП-ов цвета пикселей измениться должны.
Just_Fluffy писал(а):LGT - предпочитаю не пользоваться странными китайскими поделиями-однодневками.
Ну мы с вами в разных условиях :dont_know: , я же радиолюбитель, у меня и знаний фундаментальных не столько, да и развиваться уже особо некуда :dont_know:
Потребляю то, что менее затратно в плане перехода ))
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 553
Зарегистрирован: Ср июн 29, 2022 16:25:45

Сообщение Just_Fluffy »

shonty, ну у меня основная работа тоже не связана с радиолюбительством. Немного связана с программированием на PLSQL. Так что условия одинаковые.
А радиолюбительство тоже хобби. И иногда сторонний заработок.
Но я предпочитаю все же "проверенные временем" камни брать. К коим LGT и клоны СТМок не относятся.
Хотя я не знаю, насколько честными являются СТМки с али по 80 центов. Но студия их видит как стм, используемая мною периферия работает как у стм...
Adrift писал(а):2 такта сохранение PС, 2 или 3 такта RJMP/JMP,
по сравнению с мнимальным кодом отправки массива в SPI из прерываниия (когда массив в ОЗУ, указатель на массив - в ОЗУ) - 9/10 тактов против 41.... Вот и считать - единственный плюс SPI на прерываниях - конвеерная обработка без участия основной программы. Т.е. массив подготовить - отправку пнуть - и забыть.
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Реклама
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

Adrift, ты не прав. обычно это составляет 7/8 циклов (а не тактов).
Just_Fluffy, если это делать на Си, то компилятор там может нагородить и более 41 цикла.
а если делать на ассме, то "кучу" перечисленных тобой операций делать вообще не нужно.
вот кусочек моего текста (приемную часть я убрал, оставил передающую.

Код: Выделить всё

SPI_Complete:
in save_SREG, SREG	; 1 цикл
push ZL			; 2
ldi ZL, low(SPI_out)	; 1
add ZL, count_SPI	; 1
ld data_SPI, Z		; 2
out SPDR, data_SPI	; 1
pop ZL			; 2
out SREG, save_SREG; 1
reti				; 4
итого 15 циклов, плюс вход в прерывание 7/8 циклов = 22/23.
да, тоже не мало.
конечно, "караулить" флаг должно получиться быстрее.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Вт окт 01, 2024 15:22:33

Сообщение Adrift »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4669352#p4669352"]ты не прав. обычно это составляет 7/8 циклов (а не тактов).[/uquote]
Да, спутал с новыми AVR, там PUSH однотактовый и PC сохраняется за 2, а не за 4 такта, но так еще больше получается )
И какая разница такты или циклы применительно к AVR?
Реклама
Эиком - электронные компоненты и радиодетали
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

большая разница.
цикл состоит из нескольких тактов.
но в AVR ты эти такты просто не видишь.
а чтобы получилось несколько тактов в цикле, в AVR стоит умножитель частоты.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 553
Зарегистрирован: Ср июн 29, 2022 16:25:45

Сообщение Just_Fluffy »

Starichok51, я не описывала Си.
Я описала предположение, когда массив для отправки в ОЗУ, указатель на текущий байт массива (2 байта) тоже в ОЗУ. И расписала, как бы я в общем случае писала это на асме.
Сначала загрузить указатель, потом загрузить данные по указателю, отправить данные, сделать инкремент указателю и сохранить его назад в ОЗУ.
Судя по всему, у вас count_SPI сидит на регистрах. Кроме того, или у вас ОЗУ менее 256 байт, или непонятно, как у вас задается ZH. Плюс я не вижу инкремента/декремента count_SPI - т.е. будет отправляться один и тот же байт. Но даже и в этом случае 22+ цикла. Т.е. непосредственная отправка будет быстрее.
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Вот кстати без стёков и ОЗУ обхожусь. Вообще они тут не к чему :dont_know:
Из программной памяти через lpm загружаю байт, передаю, потом adiw ZL,1 ну и в цикле всё это.
Вымогатель припоя
Аватара пользователя
Сообщения: 553
Зарегистрирован: Ср июн 29, 2022 16:25:45

Сообщение Just_Fluffy »

shonty, А если график надо нарисовать?
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Вт окт 01, 2024 15:22:33

Сообщение Adrift »

Starichok51, нет в AVR никакого умножителя частоты, там простейший конвеер.

Изображение

Пока одна инструкция исполняется, для следующей выполняется Fetch, т.е. просто инструкция из флеша читается. Затем эта уже прочитанная инструкция может выполниться за 1 такт, хотя без конвеера потребовалось бы 2. Естественно это не касается инструкций переходов для которых конвеер сбрасывается. На самом деле когда CPU встречает инструкцию типа RJMP, то прыгает на новый адрес за 1 такт, в этом нет ничего сложного, но предвыборка была сделана за инструкцией следующей за RJMP и это не то, что нам нужно, потому при переходах конвеер сбрасывается и если мы прыгнули на простейший INC, то он выполнится за 2 такта(Fetch + Execute). В документации пошли на упрощение, они лишний такт который потратится на Fetch новой инструкции добавили инструкциям перехода...
В любом случае конвеер у нас не отключаемый и если вы насчитали 22 цикла, то они всегда равны 22 тактам, без разницы знаем мы как там все устроено или нет ) Вот для PIC разница есть, там в машинном цикле 4 такта.
Вложения
fetch.png
(28.69 КБ) 487 скачиваний
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

[uquote="Just_Fluffy",url="/forum/viewtopic.php?p=4669432#p4669432"]shonty, А если график надо нарисовать?[/uquote]
График да. С озу или еепром-а.
На BME280 график давления с еепром-а рисовал, там проверка заз в 15 минут + возможно отключение станции. поэтому еепром.

Но графики всего 2 раза и делал.

Добавлено after 26 minutes 40 seconds:
Сейчас глянул, в еепром только данные на график, сам вывод без стёков и прочих пересохранений.
Ещё сетка поверх.

Добавлено after 52 seconds:
У меня алергия на озу. Крайне редко использую :dont_know:
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

Just_Fluffy, "inc count_SPI" у меня в приемной части прерывания, которую я удалил, а в скопированный кусок кода не вставил.
это код для АТмега8, и там у меня ZH всегда равен 1, для обращения в блок памяти 0x100-0x1FF. то есть все данные хранятся в этом блоке и изменять ZH мне никогда не нужно.
Adrift писал(а):нет в AVR никакого умножителя частоты, там простейший конвеер.
тогда каким образом за 1 цикл Т2 выполняется первая инструкция (команда)?
ведь нужно выполнить несколько действий:
1. декодировать команду.
2. выполнить команду.
может, я что-то еще упустил, но минимум указанных 2 такта уже набралось.
так что, твоя картинка не доказывает, что внутри цикла нет тактов.
вон старые МК 51-го семейства вообще имели 12 тактов в одном цикле, а позже появились 51-ые с 6 тактами.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Вт окт 01, 2024 15:22:33

Сообщение Adrift »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4669469#p4669469"]тогда каким образом за 1 цикл Т2 выполняется первая инструкция (команда)?
ведь нужно выполнить несколько действий:
1. декодировать команду.
2. выполнить команду.[/uquote]
У AVR простое ядро, инструкции за такт читаются из флеша(T1), затем за такт(или несколько) декодируются и выполняются(T2), одновременно считывается следующая инструкция выполняемая за T3. Стандартная схема, можно взять более сложный Cortex-M0+ у которого тоже двухступенчатый конвеер, но он часть декодирования выполняет в обоих фазах:

Изображение

Может и AVR так делает, а про PLL нигде ни слова...
Вложения
m0.png
(33.63 КБ) 434 скачивания
Вымогатель припоя
Аватара пользователя
Сообщения: 553
Зарегистрирован: Ср июн 29, 2022 16:25:45

Сообщение Just_Fluffy »

Starichok51 писал(а):"inc count_SPI" у меня в приемной части прерывания, которую я удалил, а в скопированный кусок кода не вставил.
это код для АТмега8, и там у меня ZH всегда равен 1, для обращения в блок памяти 0x100-0x1FF. то есть все данные хранятся в этом блоке и изменять ZH мне никогда не нужно.
Ага, т.е. это не весь код прерывания. Соответственно, не 15 тактов, а больше. Я после того, как "потрогала" DMA и вывод в SPI без участия основной программы, задумалась, а можно ли такое сделать на АВРках... И анализ показал, что можно. Но это не будет независимым от ядра параллельным процессом, как DMA, это будет отправка данных с долгими прерываниями и маленькими перерывами на основную программу. И годится такое только для какого то медленного SPI, когда сидеть и ждать окончания отправки слишком расточительно. Но как правило SPI - это либо внешняя память, либо дисплей, либо другая достаточно скоростная периферия, для которой частоты AVR - вполне себе средненькие, если не медленные. И гонять этот SPI приходится на 1/4..1/2 от тактовой. Для дисплеев рабочая частота SPI запросто может быть 50-100 МГц и выше... И вот тогда тормознутость прерывания и покажет себя во всей красе.
Но я не отговариваю, ваш подход имеет право на жизнь. У меня в каком то проекте именно так опрашивается тачскрин дисплея. Но там реально SPI на 500 кГц крутится. И опрос запускается сколько то там раз в секунду от системного таймера, далее работает автономно и машина состояний при нажатии на тач генерирует событие. Т.е. все в фоне, там опрос тача - десяток байт.
shonty писал(а):У меня алергия на озу. Крайне редко использую
Ну да... один тут доказывал, что прерывания - зло, они вызывают глюки... Теперь вы утверждаете, что использовать ОЗУ - плохо для вас )))))

Давайте вернемся в русло темы OLED1306. Дисплей имеет 1 бит на пиксель, организация - горизонтальными блоками высотой 8 пикселей (1 байт).
Любой вывод, который не идет сразу в 8 пикселей одного блока - сразу становится интересным - задача комбинирования уже отрисованного изображения и выводимого без доступа к данным отрисованного - становится нетривиальной.
Обычно для таких дисплеев выделяется буфер в ОЗУ. В нашем случае 64*128 = 8192 бита или 1 килобайт.
И все рисование производится в этом буфере, который потом можно выплюнуть в дисплей.
Можно уменьшить размер буфера, например, до 8 пикселей по вертикали, но это менее удобно.

Хотя, если писать на асме и стараться использовать только регистры, то, наверное, можно минимизировать использование ОЗУ. Но... зачем?
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Just_Fluffy писал(а):Ну да... один тут доказывал, что прерывания - зло, они вызывают глюки... Теперь вы утверждаете, что использовать ОЗУ - плохо для вас )))))
Ну ОЗУ это лишние такты или циклы же)) Да и вообще (чисто субъективное мнение) суть асма - это тотальный контроль за ресурсами и любыми действиями)) Поэтому почти всегда можно раскидать задачу по регистрам. Мне например на умножения с 80-тью битным результатом свободно хватает регистров. ОЗУ - ну это когда данных действительно много и нужно сохранять, то тогда использую. Раньше ещё озу на флаги использовал, но теперь и от них избавился, сменив организацию программы..
Just_Fluffy писал(а):Давайте вернемся в русло темы OLED1306.
Давайте)) Дисплеи мелкие, применяю только вместо светодиода, как тестовый))
Just_Fluffy писал(а):Дисплей имеет 1 бит на пиксель, организация - горизонтальными блоками высотой 8 пикселей (1 байт).
Немного не понял. Дисплей мелкий же. Я чтобы не вглядываться в однострочный шрифт, настраиваю его на многострочный вывод. Команда 0х20, параметр 0х01. Ну да, запись всё равно идёт блоками по 8 бит, но при выводе не нужно переключаться между PAGE (страницами). Он как графический начинает работать.
Вот его использование с двухстрочным шрифтом:
Изображение
Just_Fluffy писал(а):Любой вывод, который не идет сразу в 8 пикселей одного блока - сразу становится интересным - задача комбинирования уже отрисованного изображения и выводимого без доступа к данным отрисованного - становится нетривиальной.
Согласен, задача не простая. Но немного не ясна цель)) Попробуйте конкретизировать))
Just_Fluffy писал(а):Любой вывод, который не идет сразу в 8 пикселей одного блока - сразу становится интересным
Кстати, хотел бы тут рассказать про шрифты для графических дисплеев, типа TFT))
Весь вывод ведь также идёт высотой кратной 8-ми битам. Например шрифт 12px высотой, всё равно в "библиотеках" он высотой 16px.
Я набросал для себя программку для 12 пиксельных по высоте символов. Вывод "чистый": байт+полубайт по вертикали)) Если длинна массива не кратна 8, то в конце массив просто добивается 12-тью битами нулей))
Изображение

А про вывод на SSD1306 конкретизируйте задачу :)
Последний раз редактировалось shonty Чт янв 09, 2025 07:30:08, всего редактировалось 2 раза.
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

Adrift, до меня дошло, если использовать не только фронт, но и спад тактового импульса, то получается, как раз, те два такта для декодирования и исполнения команды.
но в любом случае цикл и такт - разные вещи.
Just_Fluffy, я обрезал код прерывания, чтобы посчитать чисто для передачи. а в программаторе нужно не только передавать в пациента, но и читать из него.
более того, в программаторе (посмотрим usbasp) есть выбор частоты SPI, чтобы подстроиться под тактовую пациента.
shonty писал(а):Поэтому почти всегда можно раскидать задачу по регистрам.
видимо, у тебя всегда очень примитивные задачи, если тебе хватает регистров.
а мне почти никогда не хватает регистров. есть большая куча параметров и данных, которые ни в какие регистры не влезут, и еще буфер приемопередатчика для связи с компом.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Starichok51 писал(а):видимо, у тебя всегда очень примитивные задачи, если тебе хватает регистров.
Скорее всего у меня задачи попроще.. Да и связью с компом не пользуюсь. Но я имел ввиду постоянное пересохранение промежуточных результатов в контексте выполнения одной процедуры.
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

я знаю, что такое "сохранение", а что такое "пересохранение" я не знаю. и мне это напоминает "недоперепил".
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Starichok51 писал(а):а что такое "пересохранение" я не знаю.
Не в тему:
Спойлерэто когда сохранению предшествует эксгумация :)))
Вымогатель припоя
Аватара пользователя
Сообщения: 553
Зарегистрирован: Ср июн 29, 2022 16:25:45

Сообщение Just_Fluffy »

shonty, Асм - это тотальный контроль, да.
Простые задачи можно держать в регистрах. Задачи посложнее в регистры не помещаются. Совсем сложные задачи на асме уже будет тяжело... Вон посмотрите в статьях - 2 часов на меге 128 с ТФТ дисплеями... я б повесилась такое на асме писать.
про вывод на SSD1306 конкретизируйте задачу
У вас есть включенный пиксель с координатами (1,1).
Вам нужно зажечь соседний под ним пиксель с координатами (1,2).
Но вы можете загрузить за 1 раз только столбец с координатами от (1,0) до (1,7).
Как вы будете зажигать второй пиксель, не выключая первый? Вам где то нужно тогда хранить информацию о первом пикселе.

Весь вывод ведь также идёт высотой кратной 8-ми битам. Например шрифт 12px высотой, всё равно в "библиотеках" он высотой 16px.
Если нужно отрисовать текст, начиная со строки, не кратной 8? Или подчеркнуть этот текст?

Касательно хранения шрифтов - отводить на хранение 12 бит целых 2 байта - расточительство. Правильней хранить упакованную битовую последовательность - это может дать достаточно большую экономию в размере шрифта. В вашем случае - до 33%. И как по мне, для TFT-дисплеев правильней хранить биты построчно, последовательно слева направо. Большинство "взрослых" дисплеев поддерживают оконный вывод именно построчно. А для ОЛЕДов придется делать конверсию шрифта в памяти. Либо иметь 2 версии одного шрифта - с построчной и постолбцовой организацией.
Белая и Пушистая
Я не ИИ, поэтому могу ошибаться.
Мучитель микросхем
Аватара пользователя
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

Сообщение shonty »

Just_Fluffy писал(а):отводить на хранение 12 бит целых 2 байта -
у меня 1,5 байта теперь.
Just_Fluffy писал(а):2 часов на меге 128 с ТФТ дисплеями... я б повесилась такое на асме писать.
а что там писать? вот только сейчас подключил дисплей и заранее написаный драйвер. Поправил один вывод. Минут 5..10 заняло программное подключение..
На асм-е писать нужно 1 раз, ну потом только улучшать и оптимизировать..

С НОП-ами проэксперементировал..
Вобщем вот окончательный код заливки TFT 240*320:
SPI WAIT в трёх разных ипостасях:

Код: Выделить всё

	.def color_back_L	=	R11	
	.def color_back_H	=	R12	
	.def color_front_L	=	R13	
	.def color_front_H	=	R14	

DSPL_FULL_TONE:
	ldi	R17, 2
DFT_1:	
	ldi R18, 160
DFT_2:	
	ldi R19, 240
DFT_3:	
	out SPDR,color_back_H
		ldi R24, 5				; spi wait
		dec R24
		brne PC-1
		rjmp PC+1
	out SPDR,color_back_L
		jmp PC+1				; spi wait
		jmp PC+1
		jmp PC+1
	dec	R19
	brne DFT_3
	dec	R18
	brne DFT_2
	dec	R17
	brne DFT_1
		in R24,SPSR			; spi wait
		sbrs R24,SPIF
		rjmp PC-2
	ret
Добавлено after 57 minutes 57 seconds:
Just_Fluffy писал(а): И как по мне, для TFT-дисплеев правильней хранить биты построчно, последовательно слева направо. Большинство "взрослых" дисплеев поддерживают оконный вывод именно построчно.
Можно и построчно, но я предпочитаю выводить символ столбцами слева направо. То тогда строка выводится последовательно столбцами. Если построчно, то вы как представляете? Вам нужно вывести строку символов, вы на каждый символ будете поле вывода переопределять?
Ответить

Вернуться в «AVR»