Со скоростями все нормально - проект модифицировался из рабочего. MK = Attiny2313, 8MHz, скорость 19200 Зачем нужен байт окончания сообщения? Идет сообщение с N байт, выполняется N прерываний с записью во флеш в итоге имеем записанными N байт. Далее анализируем сообщение по символам... В текущей версии: .., выполняется N прерываний с записью только символов, приходящих после символа ','. Ввел защиту от переполнения, при которой после принятых/записанных 15 символов я перевожу адрес на начало секции data. На стороне принимающего МК после начала работы постоянно сыпятся ошибки "PC=0x0000. RETI address = 0x0000". Куда копать?
; ====== Начало программного кода ==================== .cseg ; Выбор сегмента программного кода .org 0 ; Установка текущего адреса на ноль
; ***** INTERRUPT VECTORS ************************************************ rjmp reset reti ;INT_0 ;INT0addr = 0x0001 ; External Interrupt Request 0 rjmp INT_1 ;INT1addr = 0x0002 ; External Interrupt Request 1 reti ;ICP1addr = 0x0003 ; Timer/Counter1 Capture Event reti ;OC1Aaddr = 0x0004 ; Timer/Counter1 Compare Match A reti ;OVF1addr = 0x0005 ; Timer/Counter1 Overflow reti ;OVF_0 ;OVF0addr = 0x0006 ; Timer/Counter0 Overflow rjmp RX_OK ;URXCaddr = 0x0007 ; USART, Rx Complete reti ;UDREaddr = 0x0008 ; USART Data Register Empty reti ;UTXCaddr = 0x0009 ; USART, Tx Complete reti ;ACIaddr = 0x000a ; Analog Comparator reti ;PCIaddr = 0x000b ; Pin Change Interrupt Request 0 reti ;OC1Baddr = 0x000c ; Timer/Counter1 Compare Match B reti ;OC0Aaddr = 0x000d ; Timer/Counter0 Compare Match A reti ;OC0Baddr = 0x000e ; Timer/Counter0 Compare Match B reti ;USI_STARTaddr = 0x000f ; USI Start Condition reti ;USI_OVFaddr = 0x0010 ; USI Overflow reti ;ERDYaddr = 0x0011 ; EEPROM Ready reti ;WDTaddr = 0x0012 ; Watchdog Timer Overflow reti ;PCINT1addr = 0x0013 ; Pin Change Interrupt Request 1 reti ;PCINT2addr = 0x0014 ; Pin Change Interrupt Request 2
;.org INT_VECTORS_SIZE ; Конец таблицы прерываний. Активизируется при урезанной таблице векторов, ; для резервирования памяти под будущее расширение ; ***** END INTERRUPT VECTORS ************************************************
ldi temp,0b11111111 ;Все выводы порта B - на выход out DDRB,temp ldi temp,0b11110010 ;Все выводы порта D - на выход, out DDRD,temp ldi temp,0b00001101 ;Вкл подтяжку на входных выводах out portD,temp
ldi temp,(1<<CS02)+(0<<CS01)+(1<<CS00) out TCCR0B,temp ;Set clock to count on CK/1024 ;8000000/1024=7812,5 (делим тактовую частоту МК на выбранный предделитель). 8 разрядов таймера означает, что в нем 2 в 8 степени позиций = 256. ;7812,5/256=30,52 (считаем число переполнений). Значит потребуется примерно 30 переполнений всего таймера(с 0) для достижения 1 секунды.
ldi temp,(0<<TOIE0) out TIMSK,temp ;Disable timer 0 overflow interrupt
ldi temp,(0<<U2X) ;Disable Double the USART Transmission Speed out UCSRA,temp
ldi temp,(0<<UMSEL)+(0<<USBS)+(0<<UPM0)+(0<<UPM1)+(1<<UCSZ1)+(1<<UCSZ0) ;UMSEL:USART Mode Select=async, USBS:Stop Bit Select=1, UCSZ0/1:Character Size=8 bits out UCSRC,temp
ldi temp,(0<<UCSZ2)+(1<<TXEN)+(1<<RXEN)|(1<<RXCIE);|(1<<TXCIE)|(0<<UDRIE) ;UCSZ2:Character Size=8bits + Enable UART Tx and Rx. ; Прерывания разрешены out UCSRB,temp ;Используем все три прерывания. По приему, по опустошению буфера и по окончании передачи. ;Но пока разрешаем только два — по приему и по передаче. Иначе при старте мы сразу же ускачем на обработчик UDRIE — буфер то пуст!
ldi temp,BAUD out UBRRL,temp ;Set baud rate generator=UBRR
ldi temp,(0<<ISC00)+(1<<ISC01)+(0<<ISC10)+(0<<ISC11) ;Set INT0 on the falling edge and INT1 on the rising edge out MCUCR,temp
ldi temp,(1<<INT0)+(1<<INT1) ;Set INT0 and INT1 interrupt enable out GIMSK,temp
ldi temp,(1<<INTF0)+(1<<INTF1) ;Clear external interrup flags out EIFR,temp
; <<<<<<<<<<<<<<<<<<< End Internal Hardware Init >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Main =====================
Main:
sei NOP ; Любой произвольный код главной программы NOP NOP
;======== ; Подпрограмма проверки сохранения смс ;======== INT_1: ;INT0 interrupt ;??????? Проверка факта записи ???????????????????????????????? ldi temp,4 ;Read 4 bytes of RAM ldi YL,RamStart+1 ;It is the first byte of RAM clr YH
Read_more: ld txbyte,Y+ ;3225 from +CMTI: "MT",3225 rcall b_transmit dec temp brne Read_more
reti
;======== ; Подпрограмма прерываний по приему байта в usart ;======== RX_OK: cli
clr XH ldi XL,RamStart+1 ;Адрес RAM куда складываем строку
ret ;======================= ; Transmiting routine ;=======================
b_transmit: sbis UCSRA,UDRE ;Is UART transmitter ready? rjmp b_transmit out UDR,txbyte ;Sent out char
ret
send_command: cli lpm tst r0 ;Check if its the last character (the zero) breq return ;If yes, return. mov txbyte,r0 rcall b_transmit adiw zl,1 ;Increase zl rjmp send_command ;Read next character from flash memory
Фактом приема байта по флагу RxC с одновременным сбросом оного является чтение UDR. Вы в обработчике зацикливаетесь, потому что флаг не сброшен чтением.
Код:
;======== ; Подпрограмма прерываний по приему байта в usart ;======== RX_OK: in rxbyte,UDR
;======== ; Подпрограмма прерываний по приему байта в usart ;======== RX_OK: again: rcall receive cpi rxbyte,',' ;0x2C Ignore all till comma brne again
clr XH ldi XL,RamStart+1 ;Адрес RAM куда складываем строку
ret ;======================= ; Transmiting routine
Есть ещё несколько предложений по более строгой инициализации Спойлер
Код:
ldi temp,(1<<CS02)+(0<<CS01)+(1<<CS00) out TCCR0B,temp ;Set clock to count on CK/1024 ;8000000/1024=7812,5 (делим тактовую частоту МК на выбранный предделитель). 8 разрядов таймера означает, что в нем 2 в 8 степени позиций = 256. ;7812,5/256=30,52 (считаем число переполнений). Значит потребуется примерно 30 переполнений всего таймера(с 0) для достижения 1 секунды.
ldi temp,(0<<UCSZ2)+(1<<TXEN)+(1<<RXEN)|(1<<RXCIE);|(1<<TXCIE)|(0<<UDRIE) ;UCSZ2:Character Size=8bits + Enable UART Tx and Rx. ; Прерывания разрешены out UCSRB,temp
NOP IN R0,UDR ; псевдочтение для сброса флага приёма SBI UCSRB,TxC ; сброс флага передатчика
;Используем все три прерывания. По приему, по опустошению буфера и по окончании передачи. ;Но пока разрешаем только два — по приему и по передаче. ; Иначе при старте мы сразу же ускачем на обработчик UDRIE — буфер то пуст! ldi temp,(0<<ISC00)+(1<<ISC01)+(0<<ISC10)+(0<<ISC11) ;Set INT0 on the falling edge and INT1 on the rising edge out MCUCR,temp
akl, спасибо тебе огромное!!!!!! Работает (пока проверял первый вариант), но как-то не так как хотелось. Для формулирования надо набрать статистику... Но результату отпишу. Хороших выходных!!!
Добавлено after 55 minutes 1 second: Первый вариант в протеус работает след.образом: Независимо от количества ПЕРЕДАЧ сообщений из U3-GENERATOR (по прерыванию по кнопке 1), на U1-RECEIVER могу проверить запись ЧТЕНИЕМ символов отправкой сообщения по усарт (по прерыванию по кнопке 2) только в таком порядке: Нажатие кнопок Кн1->Кн2->Кн1. Причем триггером является переход Кн2 -> Кн1 и тогда передается от U1-RECIVER четыре символа. Т.е. не зависимо от количества нажатий первый раз кнопки Кн1 и кнопки Кн2. NxКн1->MxКн2->Кн1.
Обоги... эту программу уже НИЧТО не спасёт. В прерывании кто будет сохранять регистры и регистр статуса? ВАМ ТОЧНО нужно разрешать прерывания в прерывании? У вас сами обработчики не реентерабельные, поэтому вообще плохая идея в прерывании разрешать другие прерывания. Это не для начинающих магия. А уж темболее чего-то ждать в прерывании. Классическое "RETI address = 0x0000" означает с 99% вероятностью разрушение/переполнение стека, и что-то мне подсказывает что это из-за разрешения прерываний в прерывании. На живом контроллере это будет равносильно его сбросу. Советую пересмотреть подход к программе и переписать её, иначе удивительные открытия у вас ещё в переди. Изменение регистров, а темболее регистра статуса в прерывании это очен коварная штука. Поскольку прерывание может возникнуть в любой момент у вас программа бует странным образом глючить то там то там, выполняться "невозможные" ветки кода и т.п. Главное что это будет носить довольно таки случайный характер и выловить истинную проблему будет очень сложно.
попытался завести на аттини 2313 два таймера, и не могу понять что у меня получилось. Один работает нормально: Т0 в норм режиме и прерывание по переполнению (канал А), а второй должен тикать 2 раза в сек а осцилограф выдает какую то фигню (канал Б)
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Вс янв 28, 2018 17:58:17
Это не хвост, это антенна
Карма: 20
Рейтинг сообщений: 188
Зарегистрирован: Вс мар 28, 2010 12:52:22 Сообщений: 1368 Откуда: Беларусь
Рейтинг сообщения:0
Канал Б измеряет переменную составляющую. Именно так и должен выглядеть НЧ прямоугольный сигнал. Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).
_________________ «Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).
Уважаемый akl, проверено в протеусе с отсылкой команды через терминал. Первый вариант работоспособен. При работе двух МК в протеус глюки, наверное, объясняются проблемой в протеус. Второй пока не проверял. Спасибо прЕОгромное!!!!
это только у меня gavrasm (свежий, v.37) не видит XH,XL,YH,YL,ZH,ZL ? странно, что более ранние версии нормально понимали, например v.25 а в добавок - свистопляска прописи ворда - и R25:R24, и R25:24, и даже тупо R24
З.Ы.ну когда уже весна нафик
_________________ ..всего две 6Ф1П, включенные последовательно, высушат обое ваших сапог даже в автомобиле..
Ассемблер видит то, что прописано в *.inc файлах. Возможно в новой версии где-то "очепятались". Или используется файл от старых версий (проблемы совместимости).
Компилятор поддерживает базовую систему команд ядра. Дополнительные особенности обеспечивают файлы с указанием/объявлением расширенного функционала. Тот же результат можно получить написав собственный файлик с такими определениями. Другое дело симулятор или программатор (софт-оболочка). В основном проблемы применения МК в них и упираются - программатор хош и можно самому сочинить, но ради единичного случая такое сооружать долго и накладно. Переписывать/дополнять компилятор как-то... Лучше для начала досконально его изучить в том виде, который имеется, а уж потом чего мудрить (это относительно "открытых исходников"). Лучше хорошо построенное описание правил работы/синтаксиса компилятора... и предпочтительно владение несколькими "дружественно-подобными" для различных семейств... Дык вроде как микрочип/атмел постарался немного над юзерс гвиде avrasm2 для народопользователя: download/file.php?id=303044
Продолжаю писать программу для бегущей строки. И столкнулся с каким-то непонятным глюком. Есть вот такой простой кусок кода (это конец обработчика прерываний по таймеру)
Exit: sts ArrCtrOffset,R21 sts ReadOffset,R25 pop XH pop XL pop R19 pop R18 pop R17 pop R16 out SREG,R16 pop R16
Первая часть кода, которая увеличивает значение ArrCtrOffset, заработала сразу. Читаем из ОЗУ значение ArrCtrOffset в регистр R21, инкрементируем, сохраняем обратно в ОЗУ. Но как выяснилось позже, заработала только потому, что R21 больше нигде не используется. Если взять другой регистр (R16, R17, R18), то начинается какая-то хрень. Сначала взял R16 - значение ReadOffset вообще не инкрементируется (или не сохраняется в ОЗУ?), с R18 то же самое, с R17 вообще знакогенератор стал выдавать крякозябры вместо букв. Вторая половина этого кода, которая изменяет значение ReadOffset, сначала никак не хотела работать, поскольку я пробовал регистры R16, R17, R18. И только когда взял нигде больше не используемый R25, всё заработало (хотя и не совсем как надо).
На первый взгляд кажется, что проблема очевидна - я изменяю содержимое указанных регистров, а они ведь где-то используются. Да, используются, но в начале подпрограммы (обработчик прерываний по таймеру) идёт загрузка в эти регистры из ОЗУ
Переменные Read, ReadOffset, ArrCtrOffset объявлены в самом начале (до таблицы векторов прерываний) по 1 байту на каждую. BuffSize - константа, равная 32, тоже объявлена в начале. Далее идёт работа с этими регистрами, но никакой записи обратно в ОЗУ! И только в самом конце подпрограммы надо инкрементировать их значения и сохранить в ОЗУ. Да и в любом случае, в начале обработчика прерываний R16, R17, R18 сохраняются в стек, а в конце извлекаются, т.е. это локальные переменные.
Такое ощущение, что запись регистров в ОЗУ и извлечение оттуда вообще не работает, а работа идёт только напрямую с регистрами. Не могу понять, почему так
Добавлено after 7 minutes 15 seconds: При этом когда я изменял значения ReadOffset, ArrCtrOffset в обработчике другого прерывания - INT0 (при вращении энкодера), всё работало. Т.е. тогда прокрутка текста была вручную.
_________________ Фак, кот грызёт провод! Сейчас его ударит либо током, либо тапком! ))
Если хрень по вине куска кода в прерывании, то причины: Не сохраняется SREG. Не сохраняются регистры, используемые в прерывании. В обработчике прерывания ошибка. Основной код и обработчик не корректно работают по временным параметрам.
Пользуйтесь симулятором в студии для отладки программ.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 362
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения