Здравствуйте!
Подскажите плз куда подсунуть тему Отправка, прием по прерыванию и анализ принятого по USART? На ASM.
C одного МК отправляю сообщение по кнопке, а на другом дрыгаюсь по прерыванию и вывожу принятые символы по нажатию кнопки. Есть наброски и проект протеус.
Нуждаюсь в помощи.
Сразу подскажу, что при использовании UART лучше сразу прикрутить кварц на МК… заметил тенденцию у некоторых МК – не в какую не желают попадать в заявленные частоты при передаче… когда тактируются от внутреннего генератора.
Хочу отработать алгоритм прерывания по получению сообщения и сохранению сообщения во flash с последующим его анализом и реакцией в главной программе.
Прерывание отрабатывает, сохраняет сообщение без проблем, если сообщение кидаю через HyperTerminal. Создал в протеус второй МК, который по кнопке отправляет сообщение, первый по прерыванию должен это сообщение принять и сохранить, а по нажатию на кнопку - выдать сохраненные символы обратно в усарт.
чОт фигня получается. Кварцы использовал.
[uquote="siimao",url="/forum/viewtopic.php?p=3293062#p3293062"]...алгоритм прерывания по получению сообщения...[/uquote]
Прерывание срабатывает при получении одного байта. При окончании получения сообщения должен приняться байт, сигнализирующий об окончании пакета. Вот после приёма такого байта и нужно уже всё обрабатывать.
[uquote="siimao",url="/forum/viewtopic.php?p=3293062#p3293062"]чОт фигня получается. Кварцы использовал.[/uquote]
Я про кварц в железе, а не в каком-то симуляторе. Какой МК используешь?
Со скоростями все нормально - проект модифицировался из рабочего.
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. Вы в обработчике зацикливаетесь, потому что флаг не сброшен чтением.
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 R16,0
STS RX_Count,R16
OUT UBRRH,R16
ldi temp,BAUD
out UBRRL,temp ;Set baud rate generator=UBRR
;ldi temp,(1<<TOIE0)
;out TIMSK,temp ;Enable 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
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 раза в сек а осцилограф выдает какую то фигню (канал Б)
Канал Б измеряет переменную составляющую. Именно так и должен выглядеть НЧ прямоугольный сигнал.
Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Jetetex Выберите входы A и B DC. 2 раза в секунду прерывания OC1A будут при частоте тактирования 500кГц.
[uquote="dr.doc",url="/forum/viewtopic.php?p=3295150#p3295150"]Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).[/uquote]Уточню. При выходе по RETI да.
[uquote="akl",url="/forum/viewtopic.php?p=3293298#p3293298"]Как то так вижу прием.[/uquote]
Уважаемый akl, проверено в протеусе с отсылкой команды через терминал. Первый вариант работоспособен. При работе двух МК в протеус глюки, наверное, объясняются проблемой в протеус.
Второй пока не проверял.
Спасибо прЕОгромное!!!!