26 Сен., 2020, 04:12

Признание проблемы - половина успеха в ее разрешении.

Зигмунд Фрейд


Последние сообщения

Страницы1 2 3 4 ... 10
1
Цифровая техника / Re: Как засветить светодиоды о...
Последний ответ от Shaman - Вчера в 16:01
Благодарю за столь подробный ответ!  :o  :)

С вашей помощью немного оптимизировал код.
Сейчас он выглядит так:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#define _data_1 PORTC |= (1<<3)      // Выбираем пин для вывода данных в сдвиговые регистры и устанавливаем на нём 1 путём установки порта и назначения разряда соответствующего пину
#define _data_0 PORTC &= ~(1<<3)     // -.- устанавливаем на нём 0 -.-
#define _clock_high PORTC |= (1<<4)  // Выбираем пин clock и устанавливаем на нём высокий уровень
#define _clock_low PORTC &= ~(1<<4)  // Выбираем пин clock и устанавливаем на нём низкий уровень
#define _latch_up PORTC |= (1<<5)    // Выбираем пин защёлки и поднимаем её
#define _latch_down PORTC &= ~(1<<5) // Выбираем пин защёлки и опускаем её
#define SIZE_SCREEN 4                //размер буфера экрана
unsigned char buffer [SIZE_SCREEN];  //создаем буфер буфер экрана


int record (); //прототип функции для записи в сдвиговые регистры

int main (void)
{

    DDRC = 0b00111000; //устанавливаем необходимые пины на вывод
    _clock_high;       // для предотвращения ложного срабатывания
    _latch_up;         // поднимаем защелку   
    while (1)
    {
        buffer[0] = 0b01010101;
        buffer[1] = 0b01010101;
        buffer[2] = 0b01010101;
        buffer[3] = 0b01010101;
         record ();
        _delay_ms(50);
        buffer[0] = 0b10101010;
        buffer[1] = 0b10101010;
        buffer[2] = 0b10101010;
        buffer[3] = 0b10101010;
        record ();
        _delay_ms(50);               
    }
   
   
}
int record ()
{
    _latch_down;                           // опускаем защелку
   
  for (int x = 0; x<SIZE_SCREEN; x++)      //цикл для переборки байтов в массиве (уточнить как храниться число)
  {
       for (int y = 7; y>=0; y--)          // цикл для перебора битов в байте и подачи их на выход
        {   
            _clock_low;                    // переводим регистры в режим ожидания данных   
           
            if ((buffer[x] & (1<<y)) == 0) // накладываем побитовую маску для считывания нужного бита
            {
                _data_0;                   // если ответ 0, выставляем на входе регистра 0
            }
            else
            {
                _data_1;                   //иначе, выставляем на входе регистра 1
            }
           
            _clock_high;                   // записываем данные в регистр
           
        }
  }
    _latch_up;                            // поднимаем защелку, включаем светодиоды
}
[свернуть]
И работает
[свернуть]

Команды дерганья пинов решил полностью вывести в дефайны и сделать их 2-х видов выставление 1 и 0.
В противном случае, даже при использовании ваших примеров, при использовании других выводов и портов либо я не смогу назначить им уникальные имена поскольку все эти варианты
#define _data 8  // назначаем разряд 3 порта как сигнал Data
#define _data 1<<3  // назначаем разряд 3 порта как сигнал Data
#define _clock 1<<4 // назначаем разряд порта для сигнала clock
PORTC |= _clock; // устанавливаем clock в "1"
PORTC &= ~_clock; // устанавливаем clock в "0"
[/quote]
означают что я всего лишь заменяю операцию сдвига бита или вообще номер бита уникальным именем, а эта операция используется по отношению ко всем портам.
А вот мой вариант
#define _data_1 PORTC |= (1<<3)      // Выбираем пин для вывода данных в сдвиговые регистры и устанавливаем на нём 1 путём установки порта и назначения разряда соответствующего пину
#define _data_0 PORTC &= ~(1<<3)     // -.- устанавливаем на нём 0 -.-
#define _clock_high PORTC |= (1<<4)  // Выбираем пин clock и устанавливаем на нём высокий уровень
#define _clock_low PORTC &= ~(1<<4)  // Выбираем пин clock и устанавливаем на нём низкий уровень
#define _latch_up PORTC |= (1<<5)    // Выбираем пин защёлки и поднимаем её
#define _latch_down PORTC &= ~(1<<5) // Выбираем пин защёлки и опускаем её
это уже использование конкретного бита на конкретном порту и буде возникнет необходимость поменять порт и бит нужно всего лишь исправить несколько строчек кода, а не шарахаться по всему листингу.

И да простят меня прожженные AVR-щики  :), но я буду комментировать что выбираю я именно пины просто так привык со среды Arduino. Там оперирование идет именно пинами, а не абстрактными регистрами и битами. Просто подкорректирую формулировку дабы было понятно, что оперирование идет именно через регистры памяти привязанные к пинам и биты в них.

Сейчас буду думать в каком виде хранить данные выводимые на экран и как их передавать в буфер. Если подскажут идею не обижусь.  ;)   ;D
2
Фото, видео, аудио / Re: Эта музыка будет вечной...
Последний ответ от Slabovik - Вчера в 11:26
Эх, нравится мне, как эти мужички лабают :)

3
Atmel Studio - это среда для разработки программ на языках 'Си' и 'ассемблер' для микроконтроллеров AVR. На сегодняшний день уже довольно старая, однако в любительском применении микроконтроллеры этой серии заслуженно популярны. Жаль, но несколько лет назад фирма Atmel с потрохами продалась конкурирующей фирме Microchip и, как следствие, нереализованные идеи Atmel теперь в составе новой продукции этой уважаемой фирмы (честно говоря, микроконтроллеры PIC тоже неплохи, но любители склонялись к несколько более дружелюбным и понятным AVR).

Сегодня Atmel Studio всё ещё можно скачать на сайте Microchip'а. Новых версий ожидать не стоит т.к. на старом форуме разработчиков Atmel были разговоры, что практически вся команда программистов, работавших в Atmel, в Microchip не работает. Да и Microchip предлагает свою среду разработки программ (правда, не совсем понятно, как там насчёт поддержки AVR - предлагаю с этим разобраться в другой теме).

Ладно. Рассмотрим один неприятный момент. Вот скачали вы Atmel Studio, начинаете ставить, и вдруг обнаруживаете, что... не ставится, зараза, требует чего-то

Atmel Studio Installation Error.png

Увы, это как раз следствие того, что программа заброшена. Вот что говорят об этом специалисты
Цитата: undefinedЧасто не ставится с предупреждением, что какое-то из обновлений Windows отсутствует.
Это присходит из-за того, что Atmel не всегда может предугадать изменения в составе обновлений Windows, а проверяет только наличие обновлений, что не совсем корректно.
В моём случае был отказ установки из-за отсутствия обновления KB2999226, которое на самом деле присутствовало в системе, но установщик этого почему-то не видел.
Решение вопроса нашлось здесь https://www.avrfreaks.net/comment/2002911#comment-2002911
скрытый текст
Причина:
1. ваша система основана на Microsoft Windows 7, обновлена до SP1 и полностью обновлена до последнего обновления Windows Update.
2. при попытке установить выпуск 7.0.1188 Atmel Studio 7.0 запрашивает обновление Windows KB3033929.
3. Вы загружаете KB3033929 и устанавливаете его, а Microsoft Windows 7 отвечает «уже установлено»
4. если вы ищете KB3033929 в списке установленных обновлений Windows, вы не найдете.
5. если из командной строки Windows вы введете цифру, wmic qfe | найти "KB3033929", KB3033929 не найден. Это связано с тем, что KB3033929 включен в накопительное обновление для Windows 7 (KB3172605).
Таким образом, Atmel Studio ищет KB3033929, он существует, но под большим контейнером KB3172605, из-за чего Atmel Studio отказывается продолжать установку.

Решение:
если вы выполнили 3. сказанное ранее, то KB3033929 установлен, даже если он находится в скрытом положении, вы можете принудительно установить Atmel Studio и Windows 7:
1. Откройте командную строку Windows 7. Обычно это находится в C:\Windows\System32\cmd.exe
2. Перейдите в каталог, в который было загружено приложение Atmel Studio 7.0. В моем случае cd c:\users\Mario\Downloads\Atmel
3. введите dir и убедитесь, что приложение as-installer-7.0.1188-full.exe указано в списке.
4. введите as-installer-7.0.1188-full.exe /SystemValidationErrorAsWarning
В этом случае, когда Atmel Studio 7.0 проверяет наличие KB3033929, отображается предупреждение, а не ошибка. На этот раз выбрал следующий и продолжаю.
Надеюсь, это наконец поможет.
[свернуть]
Таким образом, запуск инсталляции с ключом

/SystemValidationErrorAsWarning

решает проблему.

Также есть сведения, что если убрать галочку напротив '32bit MCU', то ошибка вовсе не возникает
4
Программы и сети / Ссылки: интересные места
Последний ответ от Slabovik - 24 Сен., 2020, 18:45
Иногда находишь в сети что-нибудь интересное, а потом забываешь. Я вот думаю, что можно и сюда записать.

Студия Ghibli опубликовала арты из своих мультфильмов. http://www.ghibli.jp/info/013344/
5
Цифровая техника / Re: Как засветить светодиоды о...
Последний ответ от Slabovik - 23 Сен., 2020, 23:00
Насколько я понимаю, схема подключения регистров выглядит примерно так
Схема-регистров-595.png

Для начала надо точно понимать, что собой представляет 74HC595 (она же ИР52 в отечественной системе обозначений). Думаю, с этим проблем нет, но я всё-таки нарисую, чтобы было куда пальцем тыкать (это важно т.к. устраняет неопределённости, когда один думает об одном, а другой о другом и в итоге друг друга не понимают).

ИР52 по внутреннему строению состоит как бы из двух микросхем. Вот как-то так
Схема-регистров-595-внутри.png
Т.е. внутри у неё фактически два регистра, первый регистр сдвига, куда данные можно задвигать при помощи сигналов D (Data) и C (Clock). При этом процесс записи и сдвига (вообще, сдвиг - это тоже запись) происходит строго по фронту (переходу из 0 в 1) сигнала Clock. Чисто логически это можно изобразить так
Схема-регистров-595-сдвиг.png

Такая связка двух микросхем в одном корпусе весьма удобна - поскольку выходной регистр "непрозрачный", то на его выходах всегда хранится информация, которая там запомнилась при переходе сигнала OC (по схеме Ready) из 0 в 1. Получается, что пока мы "двигаем" Data в регистре сдвига, на выходах Q0~Q7 информация "стоит как вкопанная" с прошлого раза. И только когда мы "дёрнем" OC, на выходах появится то, что мы только что записывали в регистр сдвига. Очень, очень удобно  :)

Диаграмма записи всех 8 бит в регистр типа 595 рекомендую делать такого вида

Схема-регистров-595-процедура.png

Что тут получается. Самое главное: опускаем сигнал Clock -> выставляем сигнал Data (очередной бит, который мы ходим задвинуть) -> поднимаем сигнал Clock. Делаем так столько раз, сколько бит нам нужно записать в регистр. В случае 4-х последовательно включенных регистров 595, сделать так надо 32 раза (есть исключения, но они связаны уже со схемотехникой. Вдруг, например, выводы Q4~Q7 самого правого (по схеме выше) регистра никуда не подключены - тогда их и заполнять не надо, а значит, сдвигов можно делать меньше).

Сигнал Ready рекомендую (именно рекомендую, т.к. фактически, опустить, т.е. сделать 0, его можно в любой момент) опускать ровно перед тем, как соберётесь записывать Data в регистр сдвига. А как всё запишете - поднимайте. Дело в том, что такое поведение сигнала Ready даёт возможность контролировать физически (осциллографом), когда у вас началась процедура записи, а когда закончилась, что облегчает ловлю багов (не хвалитесь - баги всегда есть, даже если вы их не видите).

Посмотрим код. Вот честно... каждый раз говорю, что Си, а тем более ++ я знаю весьма фигово. То ли дело - ассемблер :)
Цитата: undefined#define _data 3  // устанавливаем пин
Наверное, не устанавливаем пин, а назначаем разряд порта.
Да, тут надо аккуратно, потому что здесь есть одно место, порождающее глобальную путаницу при малейшей неосторожности (я тоже постоянно путаюсь).
Биты порта нумеруются с 1 по 8. А вот разряды с 0 по 7. При этом 1-й бит порта - это 0-й разряд, второй бит - первый разряд и т.д. Я тоже буду путать(ся) в показаниях - имейте это в виду и следите за руками  :)

про дефайны
При таком способе назначений (define) для работы с портами используется записи типа
Цитата: undefinedPORTC |= (1<<_clock)
Честно говоря, мне совсем не нравятся эти записи "1<<Clock". Считаю, что в этом месте надо чётко писать "Clock" без всяких 1<<

Для этого надо... всего лишь привести в порядок дефайн. Например, для Data это должно выглядеть так
#define _data 8  // назначаем разряд 3 порта как сигнал DataЭто потому что на порт посмотреть как на биты, слева старший, справа младший, то он выглядит как бинарное число '00001000', т.е. '8' в нашем обиходе.

Да, '8' надо записать просто потому, что говорят, в Си, нет возможности записывать бинарные числа. Или врут? Я в коде вижу бинарную запись. Удивительно...
Впрочем, можно (и может даже нагляднее) использовать такое определение
#define _data 1<<3  // назначаем разряд 3 порта как сигнал DataЗдесь записано, что 1 сдвинута логически влево три раза, т.е. на три разряда. Бинарно это выглядит так
00000001(bin) << 3 получаем 00001000(bin)Точно также определим "_clock"
#define _clock 1<<4 // назначаем разряд порта для сигнала clockЕсли сделать так, то процедура изменения значения порта станет выглядеть так
PORTC |= _clock; // устанавливаем clock в "1"
PORTC &= ~_clock; // устанавливаем clock в "0"
[свернуть]
Алгоримт вроде верен, но на 100% ручаться не могу. Единственное, проход битов производится от 0 до 7, что означает, что первым будет задвигаться в регистр младший бит, затем старший, а на микросхемах выходы маркированы наоборот. Это совершенно ничего не значит, просто надо иметь ввиду, что Q7 микросхемы в этом случае соответствует младшему биту буфера (в проектах даже можно переименовывать имена выводов микросхем, чтобы они соответствовали их реальной логической роли).
Да, разве что установку _clock в 0 я бы я бы делал не после установки _data, а перед. Но можно и так оставить, если между установкой _clock в "0" и установкой в "1" вставить какой-нибудь nop.

Для проверки работоспособности можно в CharBuffer записать какие-нибудь значения и поморгать (в цикле, естественно, не быстром)

зы: долго вспоминал, как выглядят логические опреаторы. В итоге Вики сдала все  :)

зы:зы: Просвещаюсь дальше: оказывается, в Си нет типа "byte". Похоже, что тип "char" - вполне нормально для данного места. Хотя если определить его как "unsigned char", то он видимо и будет полностью равноценен типу "byte", который я точно где-то использовал...

зы:зы:зы: С вашего позволения продолжу.
Могу показать свой ассемблерный код, которым я делаю то же самое на этом же (точнее, на 168, но это те же штаны) процессоре.
AsmCode.png
Это один файл, просто я показал нужные места. Если чуть помедитировать, то станет видна та же картина: имеется буфер под выводимые на индикатор символы и процедура вывода этих символов, чуть украшенная ещё парой входов на "гасим всё" и "зажигаем всё".

И не стесняйтесь на комментарии того, что вы делаете в своём коде. Обильное комментирование - залог понимания кода, когда к нему вдруг придётся вернуться.

И вот как чисто физически, на осциллографе (весьма хреновеньком, надо сказать) выглядит бурст обновления "экрана".
AsmCode_Burst_8_bytes.png AsmCode_Burst.png
Синий луч - сигнал "Clock", жёлтый - сигнал "Rdy" (Ready, Latch, OC...). Data не показана - там не так явно.
Частота процессора здесь 14,3 МГц, в пределах одного байта частота следования битов 1 МГц, а между байтами видна небольшая задержка в передаче - всё согласно программы: между байтами ведь выполняется несколько больше действий, нежели между битами.
6
Цифровая техника / Как засветить светодиоды от AV...
Последний ответ от Shaman - 23 Сен., 2020, 19:16
Захотелось мне сделать свой космический модуль... Задний фонарь для велосипеда с указанием поворотов и стоп-сигналом. Поскольку лепить такое на ардуино будет слишком громоздким и есть потребность поглубже разобраться в написании программ на Си решено было использовать голый микроконтроллер. Потому как отдельных светодиодов зажечь нужно много (27) решено было использовать сдвиговые регистры 74HC595 (4шт.). Микроконтроллер был взят Atmega328P как самый доступный.
Поскольку в AVR я новичок то решил разбить задачу на этапы и первый из них это написать процедуру, которая будет из некоего буфера экрана брать данные и вносить их последовательно в регистры.
Немного побившись головой об стол получил вот такой код:
Немного побившись головой об стол получил вот такой код:
#define F_CPU 8000000UL
#include <avr/io.h>
#define _data 3  // устанавливаем пин вывода данных в сдвиговые регистры
#define _clock 4 // устанавливаем пин clock
#define _latch 5 // устанавливаем пин защёлки
#define SIZE_SCREEN 4
unsigned char buffer [SIZE_SCREEN]; //создаем буфер буфер экрана (выяснить какой тип данных применить)


int record (); //прототип функции для записи в сдвиговые регистры

int main (void)
{

    DDRC = 0b00111000;
    PORTC |= (1<<_clock); // устанавливаем clock в 1 для предотвращения ложного срабатывания
    PORTC |= (1<<_latch); // поднимаем защелку
    PORTC |= (1<<_data); // устанавливаем на выходе дата 1       
   
}
int record ()
{
    PORTC &= ~(1<<_latch); // опускаем защелку
  for (int x = 0; x<SIZE_SCREEN; x++) //цикл для переборки байтов в массиве (уточнить как храниться число)
  {
       for (int y = 0; y<8; y++) // цикл для перебора битов в байте и подачи их на выход
        {
            if ((buffer[x] & (1<<y)) == 0) // накладываем побитовую маску для считывания нужного бита
            {
                PORTC &= ~(1<<_data); // если ответ 0, выставляем на входе регистра 0
            }
            else
            {
                PORTC |= (1<<_data); //иначе, выставляем на входе регистра 1
            }
            PORTC &= ~(1<<_clock); // устанавливаем clock в 0, переводим регистр в режим ожидания данных
            PORTC |= (1<<_clock);  // устанавливаем clock в 1, записываем данные в регистр
        }
  }
    PORTC |= (1<<_latch); // поднимаем защелку включаем светодиоды
}
[свернуть]
Он даже скомпилировался значит явных ошибок нет. Осталось выяснить как его можно проверить на железе или в эмуляторе.
А пока уважаемые гуру не могли бы вы проверить меня на ошибки?
7
Раздел создан.
8
Фото, видео, аудио / Re: Эта музыка будет вечной...
Последний ответ от Slabovik - 22 Сен., 2020, 13:10
Та самая Take Five (немного истории)

Dave Brubeck Quartet - Take Five (live 1964)
[свернуть]
которая быстро стала джазовым стандартом и ей даже придумали слова
Al Jarreau - Take Five
[свернуть]
Abi Flynn - Take Five
[свернуть]

И даже так
Sachal Studios Orchestra - Take Five
[свернуть]
9
Фото, видео, аудио / Re: Коротко о погоде
Последний ответ от Slabovik - 21 Сен., 2020, 23:37
Вчера было хорошо, тепло, несмотря на внезапные дождички и сильный южный ветер. Ну, ещё хотя бы потому, что вчера было воскресенье :)
А сегодня вот, опять: ветер западный, на небе ни просвета, то и дело заряжает мелкий дождик, и... холодрыга...

TJM-21SEP2020.jpg
10
Путешествия / Re: Отчёты о велопрогулках
Последний ответ от Slabovik - 21 Сен., 2020, 23:17
Увы, пока никуда не выбирался - варил свои железяки. Тоже интереснейшее занятие, но, скажем так... для избранных. В каждом деле есть свой дзен :)

Между делом приобрёл новый вынос руля. Поставлю с его помощью руль на 3 сантиметра выше, чем он стоит сейчас, надеюсь, руки мять будет поменьше...

Новый-вынос.jpg
Страницы1 2 3 4 ... 10