Jump to content

123654789

Members
  • Content Count

    10
  • Joined

  • Last visited

Community Reputation

0 Обычный

About 123654789

  • Rank
    Новенький

Электроника

  • Стаж в электронике
    Не связан с электроникой
  1. Советы применил, спасибо. Обнаружил еще одну неточность: выше я пишу Это неверно. int в AVR занимает 2 байта, не 4. Источник: https://gcc.gnu.org/wiki/avr-gcc Для четырехбайтового целого следовало использовать long. Не понимаю вопроса, аппаратные модули это что в данном контексте? Конструкторы a-la Arduino? Я же так в контроллеры не научусь никогда.
  2. Да, всё именно так: проблемы вызывает поднятый флаг прерывания. Решить можно двумя способами: убрать из кода запрещение/разрешение прерываний (в данном случае запрещать ничего не требуется, поэтому я выбрал этот путь) или вручную сбрасывать флаг прерывания через регистр GIFR. Исправленный код прилагаю. #define F_CPU 4800000L // 4.8 Мгц #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define INVERT_PIN(x) PORTB ^= x /* PB2 (7) - реле (ВЫХОД). PB1 (PCINT1) (6) - ИК-приёмник (ВХОД). PB0 (PCINT0) (5) - сенсорная панель (ВХОД). PB3 (2) - светодиод (ВЫХОД). PB4 (PCINT4) (3) - кнопка (ВХОД). */ volatile char is_sensor_active = 0; volatile unsigned int rc_code = 0; volatile unsigned int etalon_rc_code = 0; // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__delay_1gad22e7a36b80e2f917324dc43a425e9d3.html // 262.14 / 4.8 = 54.61 мс - это максимальная задержка для данной частоты, до которой можно использовать _delay_ms. void delay_ms(unsigned int period) { while(--period) { _delay_ms(1); } } ISR(PCINT0_vect) { is_sensor_active = 1; } int main() { DDRB = 0b00001100; // Срабатывание прерывания при смене логического уровня на ножках. MCUCR = 0b00000001; // Прерывание генерятся при изменении уровня на ножках. GIMSK = 0b00100000; // Выбор генерящих прерывание пинов. PCMSK = 0b00000010; sei(); while(1) { if( is_sensor_active ) { rc_code = 0; for( int i = 0; i < sizeof(rc_code) * 8; ++i) { rc_code = (rc_code << 1) + ((PINB & 0b00000010) >> 1); _delay_ms(16); } if( etalon_rc_code == 0) etalon_rc_code = rc_code; if( etalon_rc_code == rc_code) { INVERT_PIN(0b00000100); } else { for( int i = 0; i < 10; ++i) { INVERT_PIN(0b00001000); _delay_ms(30); } } is_sensor_active = 0; delay_ms(240); } } return 0; }
  3. Проблема в другом: блок for( int i = 0; i < 10; ++i) { INVERT_PIN(0b00001000); _delay_ms(30); } вызывается всякий раз, вне зависимости от принятого кода. Притом блок с условием etalon_rc_code == rc_code работает как ожидалось: срабатывает, когда пришел запомненный код и не срабатывает, когда пришел незапомненный (сужу, жамкая разные кнопки на пульте). Согласно коду, проблемная ситуация может возникнуть только если в блок считывания и проверки выполняется более одного раза. Тем временем, в паспорте читаю (выделение моё): Таким образом, моим следующим шагом будет попробовать очищать флаг PCIF в регистре GIFR перед включением прерывания (после распознавания команды и прочей логики) и посмотреть, что из этого выйдет.
  4. Пишу прошивку для управления всяким с пульта от телека, столкнулся с непонятным мне поведением программы (об этом ниже). Прошивка: #define F_CPU 4800000L // 4.8 Мгц #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define INVERT_PIN(x) PORTB ^= x /* PB2 (7) - реле (ВЫХОД). PB1 (PCINT1) (6) - ИК-приёмник (ВХОД). PB0 (PCINT0) (5) - сенсорная панель (ВХОД). PB3 (2) - светодиод (ВЫХОД). PB4 (PCINT4) (3) - кнопка (ВХОД). */ volatile char is_sensor_active = 0; volatile unsigned int rc_code = 0; volatile unsigned int etalon_rc_code = 0; // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__delay_1gad22e7a36b80e2f917324dc43a425e9d3.html // 262.14 / 4.8 = 54.61 мс - это максимальная задержка для данной частоты, до которой можно использовать _delay_ms. void delay_ms(unsigned int period) { while(--period) { _delay_ms(1); } } ISR(PCINT0_vect) { is_sensor_active = 1; } int main() { DDRB = 0b00001100; // Срабатывание прерывания при смене логического уровня на ножках. MCUCR = 0b00000001; // Прерывание генерятся при изменении уровня на ножках. GIMSK = 0b00100000; // Выбор генерящих прерывание пинов. PCMSK = 0b00000010; sei(); while(1) { if( is_sensor_active ) { cli(); rc_code = 0; for( int i = 0; i < sizeof(rc_code) * 8; ++i) { rc_code = (rc_code << 1) + ((PINB & 0b00000010) >> 1); _delay_ms(16); } if( etalon_rc_code == 0) etalon_rc_code = rc_code; if( etalon_rc_code == rc_code) { INVERT_PIN(0b00000100); } else { for( int i = 0; i < 10; ++i) { INVERT_PIN(0b00001000); _delay_ms(30); } } is_sensor_active = 0; delay_ms(240); sei(); } } return 0; } Как я ожидаю она должна работать: как только на ножке 6 сменится логический уровень, с ножки же 6 будет считано четырехбайтовое беззнаковое целое, принято за эталон команды и на ножке 7 установится лог. 1. При повторном зажигании прерывания снова будет считана команда, сравнена с эталонной и, если совпадает, инвертируется ножка 7. В противном случае помигать ножкой 2. Как оно на самом деле работает: вне зависимости от была ли команда верной или нет, контроллер дергает ножкой 2. Отсюда я делаю вывод, прерывание почему-то зажигается дважды. Но ведь не должно же! Вопрос: что же я упустил, приводящее к такому поведению? При обработке команды я прерывания запрещаю же, потом обратно включаю.
  5. Интернеты говорят, это касается только Arduino Uno https://www.arduino.cc/en/Tutorial/ArduinoISP
  6. Разобрался. Как это обычно бывает, дело было в кривых руках и недостаточном понимании своих действий. Что сделал для решения проблемы: 1. Использовал панельку с жестко припаянными проводками, а не макетную плату, обеспечил надежное соединение ардуины с контроллером. 2. В качестве дополнительной защиты от дурака добавлил в SCK, MISO, MOSI резисторы 1 КОм, в RESET контроллера резистор 330 Ом, соеденил RST и VCC ардуины сопротивлением 10 КОм. 3. Убрал опцию -e (erase chip) при программировании. Думаю, это было одно из двух главных причин невозможности повторной прошивки. 4. Убрал программирование фьюза SUT1 (просто по недосмотру, а не какой-либо причине). Результат: раз за разом контроллер программируется успешно, разными прошивками.
  7. Не прошивается, не обманываю, прошивка-то старая в контроллере остается. Пока за рабочую версию решил взять нарушенный контакт при программировании, хоть это и недостаточно удовлетворительно поясняет, что пошло не так. По причине опции -F при программировании, вестимо.
  8. Написано. Не может. Вопрос в почему не может, если перед этим успешно программировался несколько раз. Фьюзы трогал, конечно же. -U lfuse:w:0x71:m -U hfuse:w:0xff:m Согласно http://www.engbedded.com/fusecalc/ это соответствует следующим установкам:
  9. По каким-то причинам перестал прошиваться контроллер Attiny13A при помощи avrdude. В качестве программатора использую Arduino Pro Micro с скетчем ArduinoISP, модифицированным для этой версии адруины (RESET перекинут на пин 10). Шью Attiny13a, прошивка - мигалка светодиодом. В качестве программатора - avrdude. Команды: avrdude -p t13 -c avrisp -e -U flash:w:blink.hex -U lfuse:w:0x71:m -U hfuse:w:0xff:m -P /dev/ttyACM0 -v -b 9600 Соединяю дуину с контроллером следующим образом: ___дуина_|_контроллер ___VCC__|_8 (VCC) ___GND__|_4(GND) ___10____|_1(RESET) 15 (SCK)__|_7 (SCK) 14 (MISO)_|_6 (MISO) 16 (MOSI)_|_5 (MOSI) Результат: несколько раз контроллер прошился успешно, светодиодом мигает. В третий раз при прошивке получаю: avrdude: Device signature = 0xffffff avrdude: Yikes! Invalid device signature. Double check connections and try again, or use -F to override this check. Притом при повторении попыток прошить вместо 0xFFFFFF может появиться также 0x000000 или 0xFF0000, 0x00FFFF. Попытка прошить принудительно, используя опцию -F, тоже завершается неудачно, вдобавок рапортуя: avrdude: verifying ... avrdude: verification error, first mismatch at byte 0x0000 0xff != 0x09 avrdude: verification error; content mismatch Однако, когда всё же прошивается (принудительно), обнаруживаю, что в контроллере всё еще действует старая прошивка, но не новая. Попытался считать фузы, получил l:FF, h:FF. Паспорт на микросхему имеет сказать, что l:FF недопустимо для данного контроллера. Что же пошло не так? Прошивка успешно заливалась несколько раз подряд и тут вдруг всё испортилось. Притом эта ситуация наблюдается с обоими двумя контроллерами, имеющимися в моём распоряжении. Также, если судить по считанным фьюзам, означает ли это, что контроллер брикнулся и вернуть фьюзам оригинальное состояние удастся только при помощи высоковольтного программатора?
×
×
  • Create New...