ПО измерителя длительности сигнала
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: ПО измерителя длительности сигнала
Вот, лови. Этот код взят из моего старого проекта на tiny2313. Портировать на мегу легко - замени таблицу векторов прерываний и фсё 
- Вложения
-
- uart.asm.zip
- (1.59 КБ) 156 скачиваний
Все будет только лучше, в крайнем случае - хуже.
- Реклама
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Вроде что-то написал. Подсмотрел пример в книге Ю.Ревича. Описывается программа для Периодомера стр.180.
Вот что получилось:
Должно работать так: Измеряем промежуток времени между фронтом и спадом. Следовательно, устанавливаем захват по фронту и разрешаем прерывания. Прерывание наступает, запускаем таймер и устанавливаем захват по спаду. Прерывание по спаду срабатывает, останавливаем таймер и запоминаем содержимое регистра захвата. Вроде бы так...
Если нет поправьте.
Входной сигнал подаю на вывод ICP1.
Скорее всего работать нормально не будет.
Не знаю что делать с count2, туда ли я её вообще засунул???
И как говорит господин ARV частота должна быть 1Мгц, а у меня получается 2МГц, потому что Тактовая частота = 16МГц. Величина предделителя 1/8.
И как поставить диапазон измерений от 10мкс до 1с
И надо ли переводить значения регистров count[0:2] в 10-ую сист. счисления? и как это сделать?
Ещё нужно подсчитать число тактов приходящихся на выполнение команд, чтобы погрешность довести до минимума.
Сильно не ругайте, это моя первая так сказать программа с использованием прерываний и переферии.
Вот что получилось:
Код: Выделить всё
.include "m16def.inc"
.def temp = R16
.def count0 = R17
.def count1 = R18
.def count2 = R19
;============векроты прерываний=============
rjmp RESET ; Reset Handler
reti ;rjmp EXT_INT0 ; IRQ0 Handler
reti ;rjmp EXT_INT1 ; IRQ1 Handler
reti ;rjmp TIM2_COMP ; Timer2 Compare Handler
reti ;rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler
reti ;rjmp TIM0_OVF ; Timer0 Overflow Handler
reti ;rjmp SPI_STC ; SPI Transfer Complete Handler
reti ;rjmp USART_RXC ; USART RX Complete Handler
reti ;rjmp USART_UDRE ; UDR Empty Handler
reti ;rjmp USART_TXC ; USART TX Complete Handler
reti ;rjmp ADC ; ADC Conversion Complete Handler
reti ;rjmp EE_RDY ; EEPROM Ready Handler
reti ;rjmp ANA_COMP ; Analog Comparator Handler
reti ;rjmp TWSI ; Two-wire Serial Interface Handler
reti ;rjmp EXT_INT2 ; IRQ2 Handler
reti ;rjmp TIM0_COMP ; Timer0 Compare Handler
reti ;rjmp SPM_RDY ; Store Program Memory Ready Handler
RESET:
ldi temp,low(ramend)
out SPL,temp
ldi temp,high(ramend)
out SPH,temp
ldi temp, 0b10111111; настроить ICP1 на вход (вывод PD6)
out DDRD,temp
clr count2
clr count1
clr count0
ldi temp,(1<<TICIE1)|(1<<TOIE1); разрешить прерывание по захвату
out TIMSK,temp; и переполнение таймера
clr temp
out TCNT1H,temp; обнулить таймер
out TCNT1L,temp
ldi temp, 0b01000000; разрешить захват по фронту,
out TCCR1B,temp ; но таймер остановлен
sei
TIM1_OVF:
inc count2
reti
TIM1_CAPT: ;процедура захвата (произошло прерывание)
ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
out TCCR1B,temp; и запуск таймера
ldi temp, 0b00000010; разрешить захват по спаду, частота 2МГц
out TCCR1B,temp; таймер не останавливаем
in count0,ICR1L; запомнить содержимое таймера
in count1,ICR1H
ldi temp, 0b01000000; остановить таймер
out TCCR1B,temp
clr temp; и очистить таймер
out TCNT1H,temp
out TCNT1L,temp
// записать значения count0,count1,count2 в память для
// последущей выдачи по UART
reti //выйти из подпрограммы обработки прерывания
Если нет поправьте.
Входной сигнал подаю на вывод ICP1.
Скорее всего работать нормально не будет.
Не знаю что делать с count2, туда ли я её вообще засунул???
И как говорит господин ARV частота должна быть 1Мгц, а у меня получается 2МГц, потому что Тактовая частота = 16МГц. Величина предделителя 1/8.
И как поставить диапазон измерений от 10мкс до 1с
И надо ли переводить значения регистров count[0:2] в 10-ую сист. счисления? и как это сделать?
Ещё нужно подсчитать число тактов приходящихся на выполнение команд, чтобы погрешность довести до минимума.
Сильно не ругайте, это моя первая так сказать программа с использованием прерываний и переферии.
Re: ПО измерителя длительности сигнала
Здравствуйте.
-таблица векторов прерываний не соответствует mega16 -после SEI нужно дождаться признака измерения, который устанавливать в прерывании CAPT
например
-длительность импульса, для Вашего случая, равна T=COUNT2...0/(Fcpu/8) и для 10 секундной длительности емкости count2 не хватит. Под count2 отвести регистровую пару XH:XL и наращивание count2 осуществлять ADIW XL,1. Тогда и предделитель таймера не нужно устанавливать, а считать 16-мегагерцовые тики
-примерно тоже самое решается здесь
http://radioded.ru/content/view/95/1/
http://radioded.ru/forum/viewtopic.php?p=1692#p1692
-таблица векторов прерываний не соответствует mega16 -после SEI нужно дождаться признака измерения, который устанавливать в прерывании CAPT
например
Код: Выделить всё
.EQU END=0
.EQU BEGIN=7
; .
; .
clr temp
out TCNT1H,temp; обнулить таймер
LDI TEMP,8
out TCNT1L,temp;загрузить начальное значение, устраняющее задержку включения таймера
; .
CLR R20 ; очистить регистр признаков
SER TEMP
OUT TIFR,TEMP ;!!!!!!!!!!!!очистить флаги таймеров чтобы исключить предысторию их появления
SEI
WAIT:
SBRS R20,END ;измерение закончено?
RJMP WAIT ;нет. Ждем
;да. Обрабатываем полученный результат
; .
; .
; .
; .
RJMP RESET
TIM1_CAPT: ;процедура захвата (произошло прерывание)
SBRC R20,BEGIN; начало измерения было?
RJMP IZMER ;да
;начало измерения
; ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
; out TCCR1B,temp; и запуск таймера
ldi temp, 0b00000010; разрешить захват по спаду, частота 2МГц
out TCCR1B,temp; таймер не останавливаем
SBR R20,BEGIN; установить признак начала измерения
RETI
IZMER:
in count0,ICR1L; запомнить содержимое таймера
in count1,ICR1H
ldi temp, 0b01000000; остановить таймер
out TCCR1B,temp
;clr temp; и очистить таймер
;out TCNT1H,temp
;out TCNT1L,temp
SBR R20,END ;установить признак измерения
// записать значения count0,count1,count2 в память для
// последущей выдачи по UART
reti //выйти из подпрограммы обработки прерывания
-примерно тоже самое решается здесь
http://radioded.ru/content/view/95/1/
http://radioded.ru/forum/viewtopic.php?p=1692#p1692
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Спасибо за помощь. Но возникло много вопросов))
И всё-таки переменную count2 оставить в TIM1_OVF: inc count2 reti; ??
Не много не понятно, как Вы отслеживаете признак измерения. Почему BEGIN равно именно 7 ?
Там где Вы поставили комментарии на моём коде, значит оно не нужно?
Мляя, я думал, что разницы не будет, какое прерывание инициализировать раньше, а какое позже.akl писал(а): -таблица векторов прерываний не соответствует mega16
А ёмкости count2 хватит для длительности в 1секунду? У меня предел 1с. Запись COUNT2...0, Вы имеете ввиду это надо как-то склеить три регистра count2 +count1+count0 ???akl писал(а): длительность импульса, для Вашего случая, равна T=COUNT2...0/(Fcpu/8) и для 10 секундной длительности емкости count2 не хватит
И всё-таки переменную count2 оставить в TIM1_OVF: inc count2 reti; ??
Почему флаги таймеров очищаются заполнением единиц??akl писал(а): SER TEMP
OUT TIFR,TEMP ;!!!!!!!!!!!!очистить флаги таймеров чтобы исключить предысторию их появления
Не много не понятно, как Вы отслеживаете признак измерения. Почему BEGIN равно именно 7 ?
Там где Вы поставили комментарии на моём коде, значит оно не нужно?
Re: ПО измерителя длительности сигнала
"...я думал, что разницы не будет, какое прерывание инициализировать раньше, а какое позже."
У каждого представителя AVR-семейства своя жестко фиксированная таблица векторов прерываний.
"Почему флаги таймеров очищаются заполнением единиц??"
Так принято разработчиком, описано в DS и новации здесь не катят.
"А ёмкости count2 хватит для длительности в 1секунду? У меня предел 1с. Запись COUNT2...0, Вы имеете ввиду это надо как-то склеить три регистра count2 +count1+count0 ???
И всё-таки переменную count2 оставить в TIM1_OVF: inc count2 reti; ??"
Да, для 1-й секунды емкости count2 хватит. Значение длительности будет равно 65536*count2+256*count1+1*count0
"Почему BEGIN равно именно 7 ?"
Это мой произвольный выбор. Естественно, Вы можете его не придерживаться. Просто признаки BEGIN и END должны быть различными.
"Там где Вы поставили комментарии на моём коде, значит оно не нужно?"
Нет, мною только закомментированы команды, лишние и добавлены нужные, на мой взгляд.
У каждого представителя AVR-семейства своя жестко фиксированная таблица векторов прерываний.
"Почему флаги таймеров очищаются заполнением единиц??"
Так принято разработчиком, описано в DS и новации здесь не катят.
"А ёмкости count2 хватит для длительности в 1секунду? У меня предел 1с. Запись COUNT2...0, Вы имеете ввиду это надо как-то склеить три регистра count2 +count1+count0 ???
И всё-таки переменную count2 оставить в TIM1_OVF: inc count2 reti; ??"
Да, для 1-й секунды емкости count2 хватит. Значение длительности будет равно 65536*count2+256*count1+1*count0
"Почему BEGIN равно именно 7 ?"
Это мой произвольный выбор. Естественно, Вы можете его не придерживаться. Просто признаки BEGIN и END должны быть различными.
"Там где Вы поставили комментарии на моём коде, значит оно не нужно?"
Нет, мною только закомментированы команды, лишние и добавлены нужные, на мой взгляд.
- Реклама
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Хорошо. Учту Ваши дополнения и замечания, и попробую написать нормальный код. Обязательно выложу.
Ещё небольшой вопросец:
Эта запись
ldi temp, 0b01000000;
out TCCR1B,temp
Устанавливает захват по фронту, а вот таймер запустится или нет??
Он запустится только при такой записи?:
ldi temp, 0b01000010
out TCCR1B,temp
Т.е. без коэффициента предделителя или внешней частоты синхронизации таймер не запуститься ведь?
Имею ввиду запустится, т.е. начнёт считать такты процессора.
Ещё небольшой вопросец:
Эта запись
ldi temp, 0b01000000;
out TCCR1B,temp
Устанавливает захват по фронту, а вот таймер запустится или нет??
Он запустится только при такой записи?:
ldi temp, 0b01000010
out TCCR1B,temp
Т.е. без коэффициента предделителя или внешней частоты синхронизации таймер не запуститься ведь?
Имею ввиду запустится, т.е. начнёт считать такты процессора.
Re: ПО измерителя длительности сигнала
Запись
удерживает таймер в остановленном состоянии. Все другие комбинации 3-х младших бит разрешают работу таймера
Бит ICES1 регистра TCCR1B определяет перепад, по которому содержимое таймера будет копироваться в ICR1 и при этом будет взводиться флаг
ICF1 регистра TIFR. Собственно прерывание по захвату разрешается битом TICIE1 регистра TIMSK. Важный момент! Прерывание CAPT будет вызвано независимо от состояния таймера. Считает он или нет- неважно.
Код: Выделить всё
ldi temp, 0b01000000;
out TCCR1B,temp
Бит ICES1 регистра TCCR1B определяет перепад, по которому содержимое таймера будет копироваться в ICR1 и при этом будет взводиться флаг
ICF1 регистра TIFR. Собственно прерывание по захвату разрешается битом TICIE1 регистра TIMSK. Важный момент! Прерывание CAPT будет вызвано независимо от состояния таймера. Считает он или нет- неважно.
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Вот, изменил как Вы сказали
Но многое неясно. 
1. Почему в метке TIM1_CAPT: таймер не запускается с захватом по фронту?
;ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
;out TCCR1B,temp; и запуск таймера
В RESET ведь таймер не запустили, а просто разрешили захват по фронту.
Получается, нигде нет строки на запуск таймера.
Я так понимаю, чтобы таймер запустить нужно выставить бит предделителя (их 3 - младших в регистре TCCR1B)
2. Что Вы подразумеваете под:
; обрабатываем полученный результат
в метке WAIT?
3. Метка WAIT. Она же идёт сразу после цикла RESET. Какой от неё смысл? Ведь измерение ещё не началось, а там уже проверяется на конец измерения...
4. 65536*count2+256*count1+1*count0 И вот эту запись придётся реализовать и выдать по УАРТ? Или она уже будет содержаться в регистрах перед отправкой?
Как всё сложно то...
Код: Выделить всё
.include "m16def.inc"
.equ end = 0
.equ begin = 7
.def temp = R16
.def count0 = R17
.def count1 = R18
.def count2 = R19
.def flg = R20
;============векроты прерываний=============
rjmp RESET ; Reset Handler
reti ;rjmp EXT_INT0 ; IRQ0 Handler
reti ;rjmp EXT_INT1 ; IRQ1 Handler
reti ;rjmp TIM2_COMP ; Timer2 Compare Handler
reti ;rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
reti ;rjmp TIM0_OVF ; Timer0 Overflow Handler
reti ;rjmp SPI_STC ; SPI Transfer Complete Handler
reti ;rjmp USART_RXC ; USART RX Complete Handler
reti ;rjmp USART_UDRE ; UDR Empty Handler
reti ;rjmp USART_TXC ; USART TX Complete Handler
reti ;rjmp ADC ; ADC Conversion Complete Handler
reti ;rjmp EE_RDY ; EEPROM Ready Handler
reti ;rjmp ANA_COMP ; Analog Comparator Handler
reti ;rjmp TWSI ; Two-wire Serial Interface Handler
reti ;rjmp EXT_INT2 ; IRQ2 Handler
reti ;rjmp TIM0_COMP ; Timer0 Compare Handler
reti ;rjmp SPM_RDY ; Store Program Memory Ready Handler
RESET:
ldi temp,low(ramend)
out SPL,temp
ldi temp,high(ramend)
out SPH,temp
ldi temp, 0b10111111; настроить ICP1 на вход (вывод PD6)
out DDRD,temp
clr count2
clr count1
clr count0
ldi temp,(1<<TICIE1)|(1<<TOIE1); разрешить прерывание по захвату
out TIMSK,temp; и переполнение таймера
clr temp
out TCNT1H,temp; обнулить таймер
ldi temp,8
out TCNT1L,temp; загрузить начальное значение, устраняющее задержку включения таймера
ldi temp, 0b01000000; разрешить захват по фронту,
out TCCR1B,temp ; но таймер остановлен
clr flg; очистить регистр признаков
ser temp
out TIFR,temp; очистить флаги таймеров чтобы исключить предысторию их появления
sei
WAIT:
sbrs flg,end; измерение закончено?
rjmp WAIT; нет, ждём
; обрабатываем полученный результат
rjmp RESET
TIM1_OVF:
inc count2
reti
TIM1_CAPT: ;продцедура захвата (произошло прерывание)
sbrc flg,begin; начало измерения было?
rjmp IZMER; да
;ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
;out TCCR1B,temp; и запуск таймера
ldi temp, 0b00000010; разрешить захват по спаду, частота 2МГц
out TCCR1B,temp; таймер не останавливаем
sbr flg,begin; установить признак начала измерения
reti
IZMER:
in count0,ICR1L; запомнить содержимое таймера
in count1,ICR1H
ldi temp, 0b01000000; остановить таймер
out TCCR1B,temp
sbr flg,end; установить признак измерения
// записать значения count0,count1,count2 в память для
// последущей выдачи по UART
rjmp RESET
1. Почему в метке TIM1_CAPT: таймер не запускается с захватом по фронту?
;ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
;out TCCR1B,temp; и запуск таймера
В RESET ведь таймер не запустили, а просто разрешили захват по фронту.
Получается, нигде нет строки на запуск таймера.
Я так понимаю, чтобы таймер запустить нужно выставить бит предделителя (их 3 - младших в регистре TCCR1B)
2. Что Вы подразумеваете под:
; обрабатываем полученный результат
в метке WAIT?
3. Метка WAIT. Она же идёт сразу после цикла RESET. Какой от неё смысл? Ведь измерение ещё не началось, а там уже проверяется на конец измерения...
4. 65536*count2+256*count1+1*count0 И вот эту запись придётся реализовать и выдать по УАРТ? Или она уже будет содержаться в регистрах перед отправкой?
Как всё сложно то...
Re: ПО измерителя длительности сигнала
Здравствуйте.
-обратите внимание на таблицу векторов прерываний для mega16!!!!! Она по прежнему неправильная
1. Почему в метке TIM1_CAPT: таймер не запускается с захватом по фронту?
;ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
;out TCCR1B,temp; и запуск таймера
В RESET ведь таймер не запустили, а просто разрешили захват по фронту.
Получается, нигде нет строки на запуск таймера.
Я так понимаю, чтобы таймер запустить нужно ыставить бит предделителя (их 3 - младших в регистре TCCR1B)
-захват по фронту был подготовлен ранее до метки WAIT. А вот когда он произошел, то, анализируя признак BEGIN, который еще равен 0, командамиразрешается работа таймера в режиме счета Fcpu/8 и изменяется разрешение захвата по спаду. Также устанавливается признак начала измерения BEGIN, по которому программа и определит, что следующее прерывание захвата будет концом измерения. Для этого устанавливается признак END...
2. Что Вы подразумеваете под:
; обрабатываем полученный результат
в метке WAIT?
-нет, после установки признака END
3. Метка WAIT. Она же идёт сразу после цикла RESET. Какой от неё смысл? Ведь измерение ещё не началось,
а там уже проверяется на конец измерения...
-совершенно верно, программа уйдет с метки WAIT по установленному признаку END. Это будет возможно после измерения,
т.е. ожидаем передний фронт->когда прошел передний фронт запускаем счетчик, разрешаем ожидание спада импульса и устанавливаем признак начала измерения BEGIN-> когда прошел спад импульса устанавливаем признак END->считываем значения count2,count1,count0
4. 65536*count2+256*count1+1*count0 И вот эту запись придётся реализовать и выдать по УАРТ?
Или она уже будет содержаться в регистрах перед отправкой?
- да, значение count2,count1,count0 имеет такие веса
Должен уточнить, что счетчик запускается с тактированием Fcpu/8 и значение задержки запуска счетчика нужно установить равным 1, а не 8.
-обратите внимание на таблицу векторов прерываний для mega16!!!!! Она по прежнему неправильная
1. Почему в метке TIM1_CAPT: таймер не запускается с захватом по фронту?
;ldi temp, 0b01000010; разрешить захват по фронту, частота 2МГц
;out TCCR1B,temp; и запуск таймера
В RESET ведь таймер не запустили, а просто разрешили захват по фронту.
Получается, нигде нет строки на запуск таймера.
Я так понимаю, чтобы таймер запустить нужно ыставить бит предделителя (их 3 - младших в регистре TCCR1B)
-захват по фронту был подготовлен ранее до метки WAIT. А вот когда он произошел, то, анализируя признак BEGIN, который еще равен 0, командами
Код: Выделить всё
ldi temp, 0b00000010; разрешить захват по спаду, частота 2МГц
out TCCR1B,temp; таймер не останавливаем
SBR R20,BEGIN
2. Что Вы подразумеваете под:
; обрабатываем полученный результат
в метке WAIT?
-нет, после установки признака END
3. Метка WAIT. Она же идёт сразу после цикла RESET. Какой от неё смысл? Ведь измерение ещё не началось,
а там уже проверяется на конец измерения...
-совершенно верно, программа уйдет с метки WAIT по установленному признаку END. Это будет возможно после измерения,
т.е. ожидаем передний фронт->когда прошел передний фронт запускаем счетчик, разрешаем ожидание спада импульса и устанавливаем признак начала измерения BEGIN-> когда прошел спад импульса устанавливаем признак END->считываем значения count2,count1,count0
4. 65536*count2+256*count1+1*count0 И вот эту запись придётся реализовать и выдать по УАРТ?
Или она уже будет содержаться в регистрах перед отправкой?
- да, значение count2,count1,count0 имеет такие веса
Должен уточнить, что счетчик запускается с тактированием Fcpu/8 и значение задержки запуска счетчика нужно установить равным 1, а не 8.
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Значит вот так:
Ну сделал такую таблицу, выдаёт ошибки
вот ошибка
C:\qq\2.asm(10): error: Use of undefined or forward referenced symbol 'EXT_INT0' in .org
C:\qq\2.asm(11): error: Overlap in .cseg: addr=0x0 conflicts with 0x0:0x1
и таких ещё для каждого прерывания., конфликт с соседними адресами...
Код: Выделить всё
ldi temp,1
out TCNT1L,temp; загрузить начальное значение, устраняющее задержку включения таймера
Код: Выделить всё
.cseg
.org 0x0000
rjmp RESET ; Reset Handler
.org EXT_INT0 ; IRQ0 Handler
reti
.org EXT_INT1 ; IRQ1 Handler
reti
.org TIM2_COMP ; Timer2 Compare Handler
reti
.org TIM2_OVF ; Timer2 Overflow Handler
reti
.org TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_CAPT
.org TIM1_COMPA ; Timer1 CompareA Handler
reti
.org TIM1_COMPB ; Timer1 CompareB Handler
reti
.org TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM1_OVF
.org TIM0_OVF ; Timer0 Overflow Handler
reti
.org SPI_STC ; SPI Transfer Complete Handler
reti
.org USART_RXC ; USART RX Complete Handler
reti
.org USART_UDRE ; UDR Empty Handler
reti
.org USART_TXC ; USART TX Complete Handler
reti
.org ADC ; ADC Conversion Complete Handler
reti
.org EE_RDY ; EEPROM Ready Handler
reti
.org ANA_COMP ; Analog Comparator Handler
reti
.org TWSI ; Two-wire Serial Interface Handler
reti
.org EXT_INT2 ; IRQ2 Handler
reti
.org TIM0_COMP ; Timer0 Compare Handler
reti
.org SPM_RDY ; Store Program Memory Ready Handler
reti
C:\qq\2.asm(10): error: Use of undefined or forward referenced symbol 'EXT_INT0' in .org
C:\qq\2.asm(11): error: Overlap in .cseg: addr=0x0 conflicts with 0x0:0x1
и таких ещё для каждого прерывания., конфликт с соседними адресами...
Re: ПО измерителя длительности сигнала
В m16def.inc вектора названы по другому.
Если Вы любитель символики, то вместо
пишите
Код: Выделить всё
.equ INT0addr=$002 ;External Interrupt0 Vector Address
.equ INT1addr=$004 ;External Interrupt1 Vector Address
.equ OC2addr =$006 ;Output Compare2 Interrupt Vector Address
.equ OVF2addr=$008 ;Overflow2 Interrupt Vector Address
.equ ICP1addr=$00A ;Input Capture1 Interrupt Vector Address
.equ OC1Aaddr=$00C ;Output Compare1A Interrupt Vector Address
.equ OC1Baddr=$00E ;Output Compare1B Interrupt Vector Address
.equ OVF1addr=$010 ;Overflow1 Interrupt Vector Address
.equ OVF0addr=$012 ;Overflow0 Interrupt Vector Address
.equ SPIaddr =$014 ;SPI Interrupt Vector Address
.equ URXCaddr=$016 ;UART Receive Complete Interrupt Vector Address
.equ UDREaddr=$018 ;UART Data Register Empty Interrupt Vector Address
.equ UTXCaddr=$01A ;UART Transmit Complete Interrupt Vector Address
.equ ADCCaddr=$01C ;ADC Interrupt Vector Address
.equ ERDYaddr=$01E ;EEPROM Interrupt Vector Address
.equ ACIaddr =$020 ;Analog Comparator Interrupt Vector Address
.equ TWIaddr =$022 ;Irq. vector address for Two-Wire Interface
.equ INT2addr=$024 ;External Interrupt2 Vector Address
.equ OC0addr =$026 ;Output Compare0 Interrupt Vector Address
.equ SPMRaddr=$028 ;Store Program Memory Ready Interrupt Vector Address
Код: Выделить всё
.org $02Код: Выделить всё
.org INT0addr ; (во щасьте то)- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Мляяя, ну не знал я такого...)
А переходить на обработчик прерывания нужно командой rjmp? если оставить reti к обработчику не перейдёт?
Ладно, теперь буду колдовать с выводом данных по UART
А переходить на обработчик прерывания нужно командой rjmp? если оставить reti к обработчику не перейдёт?
Ладно, теперь буду колдовать с выводом данных по UART
Re: ПО измерителя длительности сигнала
Для mega16 лучше, ИМХО прыгать JMP в пределах всего адресного пространства. Возвращаться, на первых порах, RETI (I-бит SREG аппаратно взводится)
- Meteor
- Друг Кота
- Сообщения: 3961
- Зарегистрирован: Пн июл 13, 2009 14:37:39
- Откуда: Московская область, наукоград.....
- Контактная информация:
Re: ПО измерителя длительности сигнала
Еще один советик.
В обработке прерываний, лучше в самом начале сохранить содержимое регистра SREG в стеке, а в окончании обработки восстановить. Это позволит не наступать на грабли с нестандартной и неожиданной обработкой данных вне прерываний
В обработке прерываний, лучше в самом начале сохранить содержимое регистра SREG в стеке, а в окончании обработки восстановить. Это позволит не наступать на грабли с нестандартной и неожиданной обработкой данных вне прерываний
Загружая на вход компьютера "мусор", на выходе получим "мусор^32".
PS. Не работаю с: Proteus, Multisim, EWB, Micro-Cap... не спрашивайте даже
PS. Не работаю с: Proteus, Multisim, EWB, Micro-Cap... не спрашивайте даже
Re: ПО измерителя длительности сигнала
Не лучше всего, а ОБЯЗАТЕЛЬНО. Более того, в некоторых микропроцессорных системах ( Intel x86, PDP-11 ) слово состояния сохраняется и при выходе восстанавливается автоматически. Почему Атмели съэкномили - ХЗ. Но, как правильно замечено, новичок на этих граблях может получить немало неприятностей.Meteor писал(а): В обработке прерываний, лучше в самом начале сохранить содержимое регистра SREG в стеке, а в окончании обработки восстановить.
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Вот. А я думал, что в Атмеле тоже самое - аппаратное сохранение регистра флагов в стек.Jack_A писал(а): Не лучше всего, а ОБЯЗАТЕЛЬНО. Более того, в некоторых микропроцессорных системах ( Intel x86, PDP-11 ) слово состояния сохраняется и при выходе восстанавливается автоматически.
Ну тогда так:
Код: Выделить всё
.def sflag = R21
;---начало обработчика---
in sflag,SREG
push sflag
;---код обработчика---
pop sflag
out SREG,sflag
reti
Тогда в процессорах х86 не надо инициализировать стек))
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Наткнулся на сайт http://easyelectronics.ru/avr-uchebnyj- ... -uart.html
Пытаюсь вывести строку String: .db "TEST: send data to UART",0
но выдаёт ошибку error: Invalid directive: '.data'
Ниже код, покажите пожалуйста чего не хватает, и что лишнее. Буфер пока не формирую, сейчас хочу просто выдать строку по УАРТ, для проверки.
Пытаюсь вывести строку String: .db "TEST: send data to UART",0
но выдаёт ошибку error: Invalid directive: '.data'
Ниже код, покажите пожалуйста чего не хватает, и что лишнее. Буфер пока не формирую, сейчас хочу просто выдать строку по УАРТ, для проверки.
Код: Выделить всё
.include "m16def.inc"
.equ XTAL = 16000000
.equ baudrate = 115200
.equ bauddivider = XTAL/(16*baudrate)-1
.equ begin = 2; переменная признак, для сравнения с UDR
.macro PUSHF ; Макрос, помещающий в стек SREG и R16
in R20,SREG
push R20
push R16
.endmacro
.macro POPF ; Макрос, восстановления из стека SREG и R16
pop R16
pop R20
out SREG,R20
.endmacro
;***********************************************
String: .db "TEST: send data to UART",0
.DSEG
StrPtr: .data 2
;***********************************************
.cseg
.org 0x0000
rjmp RESET ; Reset Handler
;============векроты прерываний=============
.org INT0addr ; IRQ0 Handler
reti
.org INT1addr ; IRQ1 Handler
reti
.org OC2addr ; Timer2 Compare Handler
reti
.org OVF2addr ; Timer2 Overflow Handler
reti
.org ICP1addr ; Timer1 Capture Handler
reti
.org OC1Aaddr ; Timer1 CompareA Handler
reti
.org OC1Baddr ; Timer1 CompareB Handler
reti
.org OVF1addr ; Timer1 Overflow Handler
reti
.org OVF0addr ; Timer0 Overflow Handler
reti
.org SPIaddr ; SPI Transfer Complete Handler
reti
.org URXCaddr ; USART RX Complete Handler
rjmp RX_OK
.org UDREaddr ; UDR Empty Handler
rjmp UD_OK
.org UTXCaddr ; USART TX Complete Handler
reti
.org ADCCaddr ; ADC Conversion Complete Handler
reti
.org ERDYaddr ; EEPROM Ready Handler
reti
.org ACIaddr ; Analog Comparator Handler
reti
.org TWIaddr ; Two-wire Serial Interface Handler
reti
.org INT2addr ; IRQ2 Handler
reti
.org OC0addr ; Timer0 Compare Handler
reti
.org SPMRaddr ; Store Program Memory Ready Handler
reti
.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний
RESET:
PUSHF
uart_init: LDI R16, low(bauddivider)
OUT UBRRL,R16
LDI R16, high(bauddivider)
OUT UBRRH,R16
LDI R16,0
OUT UCSRA, R16
; Прерывания запрещены, прием-передача разрешен.
LDI R16, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(0<<UDRIE)
OUT UCSRB, R16
; Формат кадра - 8 бит, пишем в регистр UCSRC, за это отвечает бит селектор
LDI R16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
OUT UCSRC, R16
POPF
RETI
RX_OK:
PUSHF ; Макрос, пихающий в стек SREG и R16
IN R16,UDR ; Тут главное забрать байт из UDR иначе
; флаг прерывания не снимется
; Дальше, если время позволяет, можно и обработать
CPI R16,begin
BRNE Rx_Exit
Rx_Exit:
POPF ; Достаем SREG и R16
RETI
Main:
LDI R17,low(2*String) ; Берем младший байт
LDI R18,High(2*String) ; Берем старший байт
STS StrPtr,R17 ; Сохраняем Младший байт
STS StrPtr+1,R18 ; Сохраняем Сташрий байт
LDI R16, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(1<<UDRIE)
OUT UCSRB, R16
RJMP UD_OK
UD_OK: PUSHF ; Макрос, сохраняющий SREG и R16
PUSH ZL ; Сохраняем в стеке Z
PUSH ZH
LDS ZL,StrPtr ; Грузим указатели в индексные регистры
LDS ZH,StrPtr+1
LPM R16,Z+ ; Хватаем байт из флеша. Из нашей строки
CPI R16,0 ; Если он не ноль, значит читаем дальше
BREQ STOP_RX ; Иначе останавливаем передачу
OUT UDR,R16 ; Выдача данных в усарт.
STS StrPtr,ZL ; Сохраняем указатель
STS StrPtr+1,ZH ; обратно, в память
Exit_RX: POP ZH ; Все достаем из стека, выходим.
POP ZL
POPF
RETI
; глушим прерывание по опустошению, выходим из обработчика
STOP_RX: LDI R16, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(0<<UDRIE)
OUT UCSRB, R16
RJMP Exit_RX
- Uklunok
- Вымогатель припоя
- Сообщения: 561
- Зарегистрирован: Сб апр 03, 2010 10:12:41
- Откуда: Хабаровск
Re: ПО измерителя длительности сигнала
Всё, я сдаюсь
Взял прогу господина coredumped, изменил таблицу прерываний и инициализировал стек для атмеги16. Остальное осталось тоже самое. Залил программу в СТК500. Закрыл AVR-STUDIO. Запустил прогу для мониторинга COM ПОРТА compt39_setup. - Ничего. Потом запустил serial_port_monitor - тоже ничего. Потом запустил ComVC. Никакая из этих программ не показали мне строку, которую передавал по УАРТ "HI!" Может у меня руки не от куда надо растут? Но мне это уже порядком поднадоело. Никто не скажет почему не работает? А лучше - сколько стоит такой проект на интеллектуальном рынке?
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: ПО измерителя длительности сигнала
Рано сдаешься. Программа не заработала, тк написана для tiny2313, а в mega16 есть один ньюанс при записи в регистр UCSRC - старший бит должен быть равен 1, он называется URSEL. Сорри, что забыл предупредитьUklunok писал(а):Всё, я сдаюсь![]()
То, что для tiny2313 выглядит так:
ldi A, (1<<USBS)|(3<<UCSZ0) ; set frame format: 8data, 1stop bit
out UCSRC,A
А для mega16 будет так:
ldi A, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0) ; set frame format: 8data, 1stop bit
out UCSRC,A
В приложении исправленная программка под mega16, уже с правильными векторами прерываний. Я ее скомпилил и проверил "в железе" - все работает, можешь не сомневаться. Кварц у меня на 3.6864МГц, скорость 9600. Если у тебя другой кварц - подправь эту строчку (частота в герцах!):
.equ clock = 3686400 ;clock frequency
Еще учти, что RS232 - капризная штука. При выборе кварца и скорости обмена обрати внимание на таблицу "Examples of UBRR Settings for Commonly Used Oscillator Frequencies" в даташите на мегу. Там есть колонка Error - в идеале должно быть = 0 или как можно меньше. Если значение Error>5% возможны ошибки (искажения и пропадания символов), но это проявляется обычно на высоких скоростях и при больших объемах передаваемых данных. Те работать будет, но возможны глючки. У тебя какой кварц кстати?
- Вложения
-
- uart.asm.zip
- (1.6 КБ) 142 скачивания
Все будет только лучше, в крайнем случае - хуже.
Re: ПО измерителя длительности сигнала
Стек надо инициализировать в любом случае, неважно - используются ли обработчики прерываний, или вызовы подпрограмм, или Push - Pop -- в любом случае, не безразлично, в каком месте памяти будут происходить эти операции, потому что происходить они должны в конце памяти ( если, конечно, автор - не любитель извратов ).Uklunok писал(а):Ведь для этих целей в начале программы инициализируем стек??? Или для чего то ещё?
Тогда в процессорах х86 не надо инициализировать стек))
В х86 - это компьютерные микропроцессоры - этим занимается при загрузке операционная система.


