Заголовок сообщения: Re: CodeVision AVR в вопросах и ответах
Добавлено: Вс дек 01, 2019 19:40:22
Открыл глаза
Зарегистрирован: Вт сен 10, 2019 16:18:33 Сообщений: 64
Рейтинг сообщения:0
всем привет,я нубас,скажите внешние прерывания INT0 и INT1 не могут одновременно работать?только поочереди по приоритету?у меня две мигалки от двух кнопок подключенных к инту0 и инту1,при нажатий первой все норм,когда вторую наживаю то не запускает вторую мигалку пока первая не закончит свой цикл или просто рандомно на второй мигалке загорятся пару светодиодов и все [
Последний раз редактировалось shrus43 Вс дек 01, 2019 22:16:13, всего редактировалось 1 раз.
Пока одно прерывание на закончит, второе не начнётся.
Убирайте задержки в прерываниях. Их суть - что-то очень быстро сделать и выйти в основную программу. Все задержки должны быть в ней.
Напишите отдельные функции мигания для обоих светодиодов. Причём так, чтобы они завершались (return), если прерывание взводит флаг. Тогда задержка будет минимальна.
А вообще лучше по таймеру мигать, тогда вообще мгновенный будет переход от одного мигания ко второму.
Если обработчик прерывания будет всего несколько тактов процессора (взвести флаг много не стоит), то по сути будет без разницы, одновременно или последовательно.
А вот если пихать 50мс задержку в прерывание (а это десятки тысяч тактов) - тут можно и прозевать очередное прерывание, пока старое ещё выполняется.
В любом случае, после окончания прерывания основная программа продолжает выполняться с того же места, в котором была прервана. И пока не закончит со своими задержками и не дойдёт до какой-то проверки того, что поменялось в прерывании, никакой видимой реакции на прерывание до тех пор не будет.
Разрешите еще вопрос по SPI. Предположим МК работает на частоте 8 МГц от встроенного генератора. SPI2X, SPR1, SPR0 стоят как 0 0 0, следовательно 8 МГц делим на 4, получается частота SPI 2 МГц или 2 000 000 (два миллиона) Герц. Все верно пока что?
Бит данных передается, как я понял, с каждым тактом шины SPI либо по фронту, либо по спаду. Пусть я настроил передачу по фронту, значит за 8 тиков шины байт будет передан. Верно? Поправьте пожалуйста, если где не так.
Немного рассчитав, получим, что бит передается за 0,5 микросекунды. Значит передача байта, допустим 00000111 выдаст на линию MOSI сначала повышенное напряжение на 1,5 мкс, затем пониженное на 2,5 мкс. Я прав или снова ничего не понял? )
Наоборот. Сначала пониженное на 1.5мкс, потом повышенное на 2.5мкс + дополнительное время, затрачиваемое на подготовку нового байта данных. А оно может быть и сравнимо, и даже намного больше этих цифр
Разбираюсь в управлении ws2812 через SPI, вроде понятно все, кроме разрушения таймингов как раз при подготовке очередного пакета данных, чтения этих данных из массива
Разбираюсь в управлении ws2812 через SPI, вроде понятно все, кроме разрушения таймингов как раз при подготовке очередного пакета данных, чтения этих данных из массива
Все примеры, ваш в том числе, они на 16 МГц ) Интересно, справится ли, например, attiny85 на встроенной частоте 8 МГц с шестью диодами. Буду пробовать ) в принципе супер эффектов особо не надо, только радугу хотел и плавную смену. Ну да ладно, на неделе займусь реализацией в железе, посмотрим ) На крайний на tiny85 можно и кварц поставить, хотя и не хочется конечно. --------
Я правильно понял код?
Код:
__inline // Функция будет подставлена в код как есть static void send_byte(uint8_t byte){ for(uint8_t mask=0x80; mask; mask >>=1){ // Единичка бежит по байту 10000000 -- 01000000 и так далее while(bit_is_clear(SPSR, SPIF)); // ждем конца передачи SPDR = byte & mask ? WS2812_BIT_1 : WS2812_BIT_0; // Если бит 0 или 1, то отправляем на линию нужный байт, где рассчитана соответствующая задержка } }
Код:
// Тут последовательно отправляем байты цвета на диоды начиная с последнего и заканчивая первым на линии static void ws2812_show(void){ uint16_t b; leave_sd_mode(); // Тут что то с карточкой, не вникал, мне на данный момент не нужно
/*ATOMIC_RESTORESTATE. Это другой из возможных параметров для макроса ATOMIC_BLOCK(). Когда ATOMIC_BLOCK() создан с параметром ATOMIC_RESTORESTATE, то это приведет к восстановлению предыдущего состояния регистра SREG, которое было сохранено перед тем, как флаг глобального разрешения прерываний будет запрещен. Результирующий эффект от такого использования макроса ATOMIC_BLOCK гарантирует атомарное выполнение блока кода, причем предыдущее состояние прерываний не будет нарушено на выходе из блока. */ ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ // честно пытался разобраться и гуглить что это, но не понял ( Если совсем по простому, что это? Можно ли без этого обойтись? for(uint8_t i=0; i < cfg.tp; i++){ // Бежим по элементам массива структуры grb b = pixels[i].bright+1; // Не понял этот момент, зачем? Могу я просто отправлять компоненты цвета типа 255, 0, 0 (зеленый) или что нибудь типа 0, 128, 128? // send_byte (128, 0, 128) // для чипа WS2812 порядок цветовых составляющих должен быть таким: send_byte((pixels[i].g * b)>>8); // сначала ЗЕЛЕНЫЙ send_byte((pixels[i].r * b)>>8); // затем КРАСНЫЙ send_byte((pixels[i].b * b)>>8); // в конце - СИНИЙ // Ну а на не большой частоте контроллера и SPI (8 мгц, 4 МГц например) возможно и будет разваливаться при обращении к элементам массива как у меня сейчас с NOP происходит ( } } while(bit_is_clear(SPSR, SPIF)); // ждем завершения передачи последнего бита enter_sd_mode(); }
Правильно ли до меня дошел смысл работы? ------
Еще немного почитал, подумал, Атомик Блок это кусок кода где нельзя вызывать прерывания, место критичное к времени выполнения, чтобы процессор ни на что не отвлекался? Можно заменить на #asm("cli"), а в конце сделать sei?
в attiny85 вместо нормального SPI реализован дебильный USI - выигрыш очень небольшой по сравнению с тупым дрыгоногом. если уж вы собрались делать на ней, вам придется процедуру вывода цвета сделать очень оптимальной "ручками", и, разумеется, запрещать прерывания на время её работы.
мой код для вормирования одного бита цвета передает один байт, состоящий из такого количества единиц и нулей, что формируется импульс по диаграмме WS2812. если вы будете "вручную" обеспечивать вывод битов через идиотский USI, вам проще будет чисто ассемблерной вставкой делать задержку без геморроя с USI... имхо
атомик_блок отличается от простого запрета-разрешения прерываний тем, что есл он выполняется, когда прерывания ЗАПРЕЩЕНЫ, то и после этого блока они останутся ЗАПРЕЩЕНЫ, т.е. атомик_блок НЕ ПОРТИТ состояние флага разрешения прерываний после себя. кроме того, эта конструкция работает только в AVR-GCC, в вашем codevision не будет работать.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Тини85 и без кварца работает на 16 мгц, так что справится.
Каким образом, если внутренний генератор максимум 8 МГц?
_________________ "Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
да многие AVR могут работать практически на удвоенной частоте встроенного RC-генератора. в моих экспериментах мега8 работала примерно на 14,5 МГц при тактировании от встронного 8МГц.
а у attinyX5 внутри PLL есть ...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Всех приветствую! Вывожу изображение на дисплей, для чего накидал функцию:
Код:
void small_image(unsigned char x,unsigned char y, flash unsigned char image []){ //произвольный размер в пикселах unsigned int i, num_bytes; num_bytes = sizeof(image); LCD_Goto(x, y); for (i=0; i < num_bytes; i++){ SSD_data(image[i]); if (i == (num_bytes/4 - 1) || i == (num_bytes/4 + num_bytes/2 - 1) || i == (num_bytes/2 - 1) || i == num_bytes-1){y++; LCD_Goto(x,y);} } }
Компилятор ругается на num_bytes = sizeof(image); Вроде да, типы переменных разные, но я же не пытаюсь переписать флеш переменную, а лишь считаю ее количество байт. Подскажите, как обойти этот момент? мега 644, потому картинки хочется хранить во флеше. Благодарю!
WiseLord, в том то и дело, что я не знаю размер массива и хочу узнать его при помощи sizeof, если я сделаю все тоже самое, но для определенного безразмерного массива - все считается как надо.
не может быть! все, что находится во FLASH благодаря усилиям программиста, доступно ему!
когда вы передаете в функцию указатель (т.е. адрес массива), вы прекрасно можете использовать sizeof для этого конкретного массива. а вот внутри функции по значению указателя это сделать уже невозможно (если, конечно, нет какого-либо соглашения о формате данных, на которые указатель указует - как, например, ноля в конце строк).
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения