Форум РадиоКот https://radiokot.ru/forum/ |
|
atmega 128 прерывание по таймеру https://radiokot.ru/forum/viewtopic.php?f=57&t=72364 |
Страница 1 из 2 |
Автор: | astrgan [ Вс май 20, 2012 15:31:11 ] |
Заголовок сообщения: | atmega 128 прерывание по таймеру |
Здравствуйте. Подскажите пожалуйста как сделать программу где срабатывает прерывание при TCNT0=OCR0. Как я понимаю нужно создать вектор прерывания типа .ORG $XXX ? |
Автор: | Mytilus G. [ Пн май 21, 2012 00:07:35 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
.org $1E |
Автор: | astrgan [ Вт май 22, 2012 02:38:40 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
А может есть пример, а то все равно не получается. |
Автор: | BOB51 [ Вт май 22, 2012 05:50:44 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
вектора прерываний уже обозначены в файле m128def.inc (m128adef.inc *.inc) не выдумывайте ничего лишнего дабы не плодить ошибок при компиляции! ![]() |
Автор: | Alkul [ Вт май 22, 2012 07:08:12 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
astrgan писал(а): А может есть пример, а то все равно не получается. Я рекомендую писать вот так (адреса взяты из файла-описания на ATmega128): Код: .org 0x00 jmp RESET jmp INT0addr ; External Interrupt0 Vector Address jmp INT1addr ; External Interrupt1 Vector Address jmp INT2addr ; External Interrupt2 Vector Address jmp INT3addr ; External Interrupt3 Vector Address jmp INT4addr ; External Interrupt4 Vector Address jmp INT5addr ; External Interrupt5 Vector Address jmp INT6addr ; External Interrupt6 Vector Address jmp INT7addr ; External Interrupt7 Vector Address jmp OC2addr ; Output Compare2 Interrupt Vector Address jmp OVF2addr ; Overflow2 Interrupt Vector Address jmp ICP1addr ; Input Capture1 Interrupt Vector Address jmp OC1Aaddr ; Output Compare1A Interrupt Vector Address jmp OC1Baddr ; Output Compare1B Interrupt Vector Address jmp OVF1addr ; Overflow1 Interrupt Vector Address jmp OC0addr ; Output Compare0 Interrupt Vector Address jmp OVF0addr ; Overflow0 Interrupt Vector Address jmp SPIaddr ; SPI Interrupt Vector Address jmp URXC0addr ; USART0 Receive Complete Interrupt Vector Address jmp UDRE0addr ; USART0 Data Register Empty Interrupt Vector Address jmp UTXC0addr ; USART0 Transmit Complete Interrupt Vector Address jmp ADCCaddr ; ADC Conversion Complete Handle jmp ERDYaddr ; EEPROM Write Complete Handle jmp ACIaddr ; Analog Comparator Interrupt Vector Address jmp OC1Caddr ; Output Compare1C Interrupt Vector Address jmp ICP3addr ; Input Capture3 Interrupt Vector Address jmp OC3Aaddr ; Output Compare3A Interrupt Vector Address jmp OC3Baddr ; Output Compare3B Interrupt Vector Address jmp OC3Caddr ; Output Compare3C Interrupt Vector Address jmp OVF3addr ; Overflow3 Interrupt Vector Address jmp URXC1addr ; USART1 Receive Complete Interrupt Vector Address jmp UDRE1addr ; USART1 Data Register Empty Interrupt Vector Address jmp UTXC1addr ; USART1 Transmit Complete Interrupt Vector Address jmp TWIaddr ; TWI Interrupt Vector Address jmp SPMRaddr ; Store Program Memory Ready Interrupt Vector Address ;Заглушки неиспользуемых обработчиков прерываний INT0addr: ; External Interrupt0 Vector Address INT1addr: ; External Interrupt1 Vector Address INT2addr: ; External Interrupt2 Vector Address INT3addr: ; External Interrupt3 Vector Address INT4addr: ; External Interrupt4 Vector Address INT5addr: ; External Interrupt5 Vector Address INT6addr: ; External Interrupt6 Vector Address INT7addr: ; External Interrupt7 Vector Address OC2addr: ; Output Compare2 Interrupt Vector Address OVF2addr: ; Overflow2 Interrupt Vector Address ICP1addr: ; Input Capture1 Interrupt Vector Address OC1Aaddr: ; Output Compare1A Interrupt Vector Address OC1Baddr: ; Output Compare1B Interrupt Vector Address OVF1addr: ; Overflow1 Interrupt Vector Address ;OC0addr: ; Output Compare0 Interrupt Vector Address OVF0addr: ; Overflow0 Interrupt Vector Address SPIaddr: ; SPI Interrupt Vector Address URXC0addr: ; USART0 Receive Complete Interrupt Vector Address UDRE0addr: ; USART0 Data Register Empty Interrupt Vector Address UTXC0addr: ; USART0 Transmit Complete Interrupt Vector Address ADCCaddr: ; ADC Conversion Complete Handle ERDYaddr: ; EEPROM Write Complete Handle ACIaddr: ; Analog Comparator Interrupt Vector Address OC1Caddr: ; Output Compare1C Interrupt Vector Address ICP3addr: ; Input Capture3 Interrupt Vector Address OC3Aaddr: ; Output Compare3A Interrupt Vector Address OC3Baddr: ; Output Compare3B Interrupt Vector Address OC3Caddr: ; Output Compare3C Interrupt Vector Address OVF3addr: ; Overflow3 Interrupt Vector Address URXC1addr: ; USART1 Receive Complete Interrupt Vector Address UDRE1addr: ; USART1 Data Register Empty Interrupt Vector Address UTXC1addr: ; USART1 Transmit Complete Interrupt Vector Address TWIaddr: ; TWI Interrupt Vector Address SPMRaddr: ; Store Program Memory Ready Interrupt Vector Address reti OC0addr: ; Output Compare0 Interrupt Vector Address ;Ваш код обработчика прерывания по совпадению reti RESET: ;Основная программа Те обработчики прерываний, которые Вам понадобятся, Вы "вытаскиваете из "заглушек", создаете свою подпрограмму-обработчик. А в блоке "заглушек" перед этим адресом ставите точку с запятой. Так Вы никогда не "потеряетесь" в обработчиках и не перепутаете адреса векторов. |
Автор: | BOB51 [ Вт май 22, 2012 14:24:23 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Alkul, вот это как раз и есть классическая ошибка... ![]() в стандартном заголовочном файле avr studio обычно всегда подключается шаблон (в данном случае m128def.inc) - а там уже заявлены адреса векторов под собственными именами, которые повторно использовать не рекомендуется! А вот пользоваться этими именами весьма полезно: "шапка" проекта (avrasm2) Код: ;----------
;_____ ; .nolist .include "m128def.inc" .list :---------- ; .cseg .org 0x0000 ;_____ ; здесь размещаются вектора прерываний ; или короткие подпрограммы их обслуживания ; irq_res: rjmp init ; вектор RESET, если небыло переконфигурации таблицы векторов и самого Вектора сброса (см. config fuse) .org (irq_res+OC0addr) rjmp ISR_OC0 ; или как я его хочу обозвать ;_____ ; .org (irq_res+INT_VECTORS_SIZE) ; обход блока векторов прерываний ; блок начальной инициализации кристалла init: ; точка входа в модуль начальной инициализации ;---------- ISR_OC0: ; а здесь уже сам обработчик данного прерывания |
Автор: | Alkul [ Вт май 22, 2012 15:00:09 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
BOB51 писал(а): Alkul, вот это как раз и есть классическая ошибка... ![]() в стандартном заголовочном файле avr studio обычно всегда подключается шаблон (в данном случае m128def.inc) - а там уже заявлены адреса векторов под собственными именами, которые повторно использовать не рекомендуется! Во-первых, я показал лишь подход. Имена можно написать свои, убрав окончания "addr", это неважно. А в файле-описателе микросхемы прописаны соответствия имен обработчиков прерываний с адресами их расположения в памяти, но это не освобождает от необходимости расписывать всю таблицу векторов с командами jmp или rjmp (в зависимости от модели памяти контроллера) на адрес конкретного обработчика. Написание блока "заглушек" неиспользуемых прерываний очень важно, так как по невнимательности программист может разрешить то или иное прерывание случайно. И если не будет "заглушки", то программа при вызове "незапланированного" обработчика перейдет Бог знает куда. То, что предлагаете Вы, как раз и является ошибкой. Вы предлагаете размещать в таблице векторов только те, которые реально используются, высчитывая их адреса, правильно я Вас понял? И размещать в памяти программ только те обработчики, которые реально существуют? А на месте неиспользуемых векторов будет "мусор"? Ошибки в программах бывают такими изощренными, что разрешение неиспользуемого прерывания - это "семечки". И куда будет сделан переход в этом случае? Если Вы не инициализируете ВСЮ область векторов прерываний, то в свободных участках, скорее всего, будут либо нули, либо единицы. Я не нашел в командах AVRовского ассемблера команды 0xFFFF, её нет либо она недокументирована. Как поведет себя контроллер в этом случае, я не знаю. А вот если там будут 0x0000, то это банальная команда NOP. Контроллер "пробежится" по Вашим NOPам, пока не дойдет до команды перехода на реально существующий обработчик, на который с удовольствием и перейдет. Либо выполнение NOPов дойдет до первой подпрограммы, расположенной за таблицей векторов, и контроллер радостно начнет выполнять эту подпрограмму. И Вы будете долго отлавливать причину этих странных "глюков". Во-вторых, с чего Вы взяли, что не рекомендуется повторно использовать адреса векторов? Если при ассемблировании не выдается ошибок, то это вполне допустимо. Иногда (редко) при использовании чужих подпрограмм пользуешься теми именами регистров, которые использовал автор. В этом случае, естественно, вместе с подпрограммой прилагаются описания типа .def - ничего криминального в этом нет. Компилятор, естественно, выдаст предупреждения о дублировании имен, но это просто предупреждения разработчику о самом факте - а вдруг он сделал это по ошибке? На генерации же выходного кода это не сказывается совершенно никак. |
Автор: | BOB51 [ Вт май 22, 2012 16:12:02 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
а с чего Вы взяли, что будут произвольно выполняться какие-либо из запрещенных прерываний? ![]() ведь для того, чтобы прерывание было активировано, его предварительно еще разрешить надобно! причем многоступенчато - сначала условия, затем маску и в конце - общее разрешение... естественно при работе с ассемблером (особенно на "нафаршированных" ИС) задача начальной конфигурации весьма тяжелая, однако управление прерываниями строго регламентировано и случайностей там не бывает - если чего "не разрешено" - то того и не будет, даже при сбое (тут уж смотри схемотехнику внешней обвязки как источник проблем, а не МК) в документации на каждую ИС всегда есть подробное описание состояния всех критических регистров по аппаратному сбросу, включению питания и выходу из режимов энергосбережения - просто прежде чем писать программу datasheet надо весьма внимательно изучить и свои заметки на распечатанном образце на лениться делать ![]() кстати, "чего прийдется" в программной памяти без ведома программиста быть также не может (исключение - "убитая" ИС) т.к. при стирании все ячейки заполняются кодом 0xFF, а при записи - тем чего мы сами нарисовали ![]() теперь о метках - фрагмент того-же m128def.inc: ; ***** INTERRUPT VECTORS ************************************************ .equ INT0addr = 0x0002 ; External Interrupt Request 0 .equ INT1addr = 0x0004 ; External Interrupt Request 1 и описание директивы .equ: The EQU directive assigns a value to a label. This label can then be used in later expressions. A label assigned to a value by the EQU directive is a constant and can not be changed or redefined. ![]() кстати, когда-то сам подобным образом таблицы векторов "забивал", пока не ознакомился с возможностями ассемблеров из avr studio, mplab и c51asm.exe - теперь использую лучшие решения из всего освоенного ![]() |
Автор: | Engineer_Keen [ Вт май 22, 2012 16:51:26 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
BOB51 писал(а): а с чего Вы взяли, что будут произвольно выполняться какие-либо из запрещенных прерываний? Имеется ввиду ошибка программиста-нуба. Кстати, давно хотел проверить в железе как выполняется опкод 0xFFFF? Протеус ругается и встает, AVR студия предупреждает, но едет дальше... Как до макетки доберусь, проверю. Что касается моего варианта - я просто перепечатываю таблицу прерываний из даташита и в ненужных строчках пишу RETI, а в нужных JMP/RJMP, может это и не удобно или не правильно, но мне пофиг, я в этом месте ни разу не накосячил, и все равно сначала все проверяю в симуляторе... Я не знал что в инклудах есть адреса векторов, с тех пор привык все писать сам. Код: .cseg
RJMP RESET ;RESET RETI ;INT0 RJMP PIN_READ ;PCINT RETI ;T0_OV RETI ;EE_RDY RETI ;ANA_COMP RJMP CALC_BEMF ;T0=A RETI ;T0=B RETI ;WDT RETI ;ADC RESET: |
Автор: | BOB51 [ Вт май 22, 2012 19:03:51 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
... ![]() ![]() хорошая штука, если предварительно прочитать тамошние erratы... припомнился недавный кошмар с таймером... ![]() макетка- последняя инстанция! ![]() |
Автор: | Alkul [ Вт май 22, 2012 19:30:43 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Engineer_Keen писал(а): BOB51 писал(а): а с чего Вы взяли, что будут произвольно выполняться какие-либо из запрещенных прерываний? Имеется ввиду ошибка программиста-нуба. Совершенно верно. К примеру, если в программе определен какой-то байт состояния, хранящийся, допустим, в ОЗУ, бит 0 которого, к примеру, определяет разрешение прерываний таймера 0. А другие биты определяют какие-то флаги состояния программы. Если забыть маскировать незначащие биты и напрямую занести содержимое байта состояния в регистр TIMSK, то окажутся разрешенными и другие прерывания таймеров. Ошибка, вполне достойная начинающего. Engineer_Keen писал(а): Что касается моего варианта - я просто перепечатываю таблицу прерываний из даташита и в ненужных строчках пишу RETI, а в нужных JMP/RJMP, Код: .cseg RJMP RESET ;RESET RETI ;INT0 RJMP PIN_READ ;PCINT Все верно, только следует помнить, что у контроллеров с объемом памяти программ больше 16 килобайт на каждый вектор отводится не одно слово, а два. Поэтому у неиспользуемых прерываний нужно писать не просто RETI, а NOP RETI на каждый вектор прерывания. А еще лучше делать так, как показал я. Сначала вся таблица векторов, состоящая из команд JMP или RJMP, в зависимости от типа контроллера, а потом ниже отдельный блок "заглушек". Engineer_Keen писал(а): Я не знал что в инклудах есть адреса векторов, с тех пор привык все писать сам. Вот именно, что в инклюдах есть только записи вида: Код: ; ***** INTERRUPT VECTORS ************************************************ .equ INT0addr = 0x0002 ; External Interrupt Request 0 .equ INT1addr = 0x0004 ; External Interrupt Request 1 .equ INT2addr = 0x0006 ; External Interrupt Request 2 //и так далее все адреса векторов Эта запись всего лишь определяет соответствие символьной строки, к примеру, INT0addr числу 0х0002. Это значит, что обратившись к памяти по адресу INT0addr, я обращусь к адресу 0х0002. Не более того. Это никоим образом не означает, что эти записи имеют хоть какое-то отношение к таблице векторов. |
Автор: | ILYAUL [ Вт май 22, 2012 19:54:38 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Внесу свою лепту в Ваш разговор . Я делаю так Код: .cseg .org 0 ;************************************************* ;* ;;/Initialization Interrupts;;* * ;************************************************* jmp RESET ; Reset Handler .org OC2addr jmp TIM2_COMP ; Timer2 Compare Handler .org URXC0addr jmp RS232_VESS; USART0 RX Complete Handler .org ADCCaddr jmp ADC_Complet .org URXC1addr jmp USART1_RXC; USART1 RX Complete Handler .org UDRE1addr jmp USART1_UDRE; USART1 TX Complete Handler Всё лишнее (не нужное для данной программы) для остаётся "за бортом" |
Автор: | Alkul [ Вт май 22, 2012 20:02:51 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Вот сейчас специально создал в AVR Studio проект на ATmega128 в режиме AVRSimulator2, подключил соответствующий инклюд. Компилирую, ошибок нет, хотя я специально написал команду Код: out TIMSK,R16 Если бы инклюд не подключился, то компилятор бы "ругнулся" на имя TIMSK, ан нет - принял. Вот такой "проект" я написал: Код: .include "m128def.inc" .cseg .org 0x00 jmp RESET .org 0x30 RESET: nop nop ldi R16,0x10 out TIMSK,R16 Запускаю симуляцию и что вижу - в памяти программ создался только один вектор - тот, который располагается с нулевого адреса и переходит на метку RESET. Дальше вместо таблицы сплошь 0xFF, чего и следовало ожидать. |
Автор: | Alkul [ Вт май 22, 2012 21:01:20 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
ILYAUL писал(а): Внесу свою лепту в Ваш разговор . Я делаю так Всё лишнее (не нужное для данной программы) для остаётся "за бортом" Если при этом Вы не описываете каждый вектор, а пишете только те, которые используете, то чем Ваш способ принципиально отличается от способа, предложенного BOB51? И все потенциальные возможности для ошибок, описанные мной, полностью относятся и к Вашему способу. |
Автор: | ILYAUL [ Вт май 22, 2012 21:22:37 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Alkul писал(а): [ли при этом Вы не описываете каждый вектор, а пишете только те, которые используете, то чем Ваш способ принципиально отличается от способа, предложенного BOB51? И все потенциальные возможности для ошибок, описанные мной, полностью относятся и к Вашему способу. Не внимательно посмотрел его код , да похоже. И полностью принимаю его аргументы в его защиту. От себя добавлю , ни разу не было ни одного сбоя при такой организации адресов прерывания, правда место это не зкономит во FLASH, но вы можете убрать в def адреса по умолчанию и присвоить свои тем же прерываниям расположив их как Вам удобно , например только используемые и подряд учитывая специфику адресации применяемого процессора |
Автор: | Alkul [ Вт май 22, 2012 21:36:05 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
ILYAUL писал(а): Не внимательно посмотрел его код , да похоже. И полностью принимаю его аргументы в его защиту. От себя добавлю , ни разу не было ни одного сбоя при такой организации адресов прерывания Вы невнимательно прочли то, что писал я о проблемах, могущих возникнуть при использовании такого способа. Разве я говорил о сбоях? Понятно, что не бывает таких сбоев, которые заставят перейти на запрещенное прерывание (иначе контроллер дефектный). Я говорил о возможных ошибках в программе, которые вполне может допустить начинающий программист (даже пример такой ошибки привел). А уже эти ошибки могут стать причиной того, что запрещенное прерывание будет разрешено. Мы же говорим о рекомендациях начинающему программисту! Такие ошибки будет очень сложно отлавливать, потому что не будет видна причинно-следственная связь ошибки и её внешних проявлений. Конечно, для профессионала такая предосторожность, возможно, и лишняя. Он отслеживает каждый бит в 16-ти килобайтной программе и в уме делает арифметические действия над шестнадцатеричными числами ![]() Но новичку этот способ записи таблицы векторов сэкономит много времени и нервов. |
Автор: | ILYAUL [ Вт май 22, 2012 21:44:26 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
![]() |
Автор: | Kavka [ Ср май 23, 2012 03:33:33 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Что-то опять, практически, холивар пошёл. ![]() Народ, нет чтобы скомбинировать всё лучшее, так вы воду толчёте. Между прочим вариант предложенный ILYAUL и дополненный как писал Alkul будет ещё лучше. (И об этом на форуме уже писали, и сдаётся мне, что уже не раз.) А именно - определить все точки входа в прерывания с помощью директивы .org с метками векторов прерываний из "инклюдника". В таком случае не имеет значения какая команда стоит непосредственно в векторе - jmp(там где допустимо), rjmp или reti. Так же не имеет значения последовательность определения векторов, так как есть директивы .org (обратите внимание на .org INT_VECTORS_SIZE перед основным кодом). В качестве примера чуть-чуть дополненный (но далеко не полный ![]() Код: .cseg
.org 0 ;************************************************* ;* ;;/Initialization Interrupts;;* * ;************************************************* jmp RESET ; Reset Handler .org OC2addr jmp TIM2_COMP ; Timer2 Compare Handler .org URXC0addr jmp RS232_VESS; USART0 RX Complete Handler .org ADCCaddr jmp ADC_Complet .org URXC1addr jmp USART1_RXC; USART1 RX Complete Handler .org UDRE1addr jmp USART1_UDRE; USART1 TX Complete Handler .org SPIaddr reti .org SPMRaddr reti .org INT_VECTORS_SIZE ; основной код |
Автор: | BOB51 [ Ср май 23, 2012 06:30:31 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
а замечания-то насчет ограничений симулятора относительно таймеров и прочего народ не воспринял... ![]() кстати о питичках... в коде от Alkul при компиляции должна была бы выскочить ошибка "двойное определение метки", но... второе определение по сути дублирует значения первого и... спасибо за обнаруженную "пакость" в работе асма ![]() теперь о "ошибках начинающих" "случайно" включить не тот бит конечно можно, если кто матчасть или двоичную математику перед тем, как лезть в программирование, не учил... только вот... стандартное правило - считай то, чего было, замени целевой бит и запиши назад - никто пока не отменял (да еще запрети на всякий случай все прерывания перед тем, как чего менять и флажки возможных "возмущений" скинь для страховки), а прямое управление битами для AVRок доступно только относительно портов 0x00-0x1F ![]() Kavka, а в случае применения "перемещенной" таблицы векторов такой подход всегда сработает?(см. адреса переконфигурации таблиц для "больших" мег - язва я) ![]() кстати об оформлении программ - весьма правильно описано в http://pic24.ru/doku.php/osa/articles/mpasm_formatting , хотя это и относительно PICов (там своя заморочка с прерываниями и довольно серьёзная) зато общий план подхода к вопросу очень хороший досадно, что обилие "грязи" и неполное знание возможностей ассемблера ( отчасти и за счет довольно смутного их описания) заставляет в дальнейшем "прыгать на С" при более-менее сложных проектах ![]() |
Автор: | ILYAUL [ Ср май 23, 2012 10:48:25 ] |
Заголовок сообщения: | Re: atmega 128 прерывание по таймеру |
Цитата: BOB51 а замечания-то насчет ограничений симулятора относительно таймеров и прочего народ не воспринял... Симмулятор Atmel "до ума" всё таки довести пока не может . И перед его использованием для любого MC надо обязательно лезть в его описание и смотреть , что он поддерживает , а что нет именно для данного MC. В том числе и прерывания. Вот математику ( о чём здесь писалось) да , можно его использовать для отладки матемаического куска кода. Ну ещё посмотреть , что пишется в порты и регистры переферии . Но доверять всецело его действиям с переферией я бы не стал. А для начинающих - один раз потратится ( если серьёзно хочется заниматься MC и писать свои программы) купить отладчик ( он же и программатор - как доп. функция) , коих кстати не так уж и много и под необходимый проект делать макетку. Что всестороне развивает навыки програмирования , чтения схем и держания паяльника. Кстати, их получится не так уж и много т.к. использование макросов позволяет перенести проект отработанный на одном MC на другой MC практически без серьёзной правки кода. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |