Это просто - см. схему. Главной прграмме остается только посматривать на флаг ДАННЫЕ ОБНОВЛЕНЫ, сбрасывать его, если установлен, принимать данные и делать с ними что хошь : усреднять, индицировать, на хлеб намазывать ...
вот чего то пытался написал код , по которому моргать светодиод должен, не получилось он просто тускло горит подскажите что не так? это первая попытка приручить таймер)
Спойлер
Код:
; по идее программа зажигает и гасит светодиод С0 (посажен светодиод на массу) по переполнению таймера Т0 ; ; ; .cseg .include "m8Adef.inc"
push r16 ; сохраняем используемые регистры r16 (этих пушей может быть много) push r17 ; сохраняем используемые регистры r17 (этих пушей может быть много) in r17, SREG ; сохраням флаги push r17 ; и запихиваем их в стек
sbis PORTC,0 ; читаем бит С0, если этот бит установлен, пропускает следующую команду sbi PORTC, 0 ; зажигаем светодиод на ножке С0 cbi PORTC, 0 ; гасим светодиод на ножке С0
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
sei ; разрешить прерывания
reti
_________________ глаза боятся, а руки что то не делают))
А где главный цикл программы? Куда она пойдет после первой команды sei? В прерывании не обязательно использовать запрет и разрешение прерываний. Это делается автоматически. Для того, чтобы что-то увидеть нужно ввести задержку между включением светодиода и его отключением. В противном случае у Вас получается, что тот включается и через 1 такт выключается. 1 такт ~ 1 мкс. Глазом такого не заметить. К тому же, ножка у Вас на выход сформирована. По умолчанию там 0. Т.е. команда зажигания светодиода у Вас будет всегда пропускаться. сбрасывать каждый раз предделители тоже не обязательно. В регистре SFIOR помимо сброса предделителей есть другие функции. Правильнее использовать команды чтения-модификации-записи, а не прямой записи. Сбрасывать можно и нужно предделитель того таймера, который используете. В прерывании регистр r17 Вы не используете - можно не сохранять. Операций, меняющих флаги тоже нет - регистр флагов можно также не трогать. Лучше попробуйте без всяких условий зажигать и гасить светодиод по таймеру Светодиод, надеюсь, через резистор подключили?
Последний раз редактировалось ИС-пытатель Вт май 06, 2014 00:31:03, всего редактировалось 1 раз.
push r16 ; сохраняем используемые регистры r16 (этих пушей может быть много) push r17 ; сохраняем используемые регистры r17 (этих пушей может быть много) in r17, SREG ; сохраням флаги push r17 ; и запихиваем их в стек
sbis PORTC,0 ; читаем бит С0, если этот бит установлен, пропускает следующую команду RJMP KUKA ; зажигаем светодиод на ножке С0 cbi PORTC, 0 ; гасим светодиод на ножке С0
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
sei ; разрешить прерывания
RJMP MAIN
вроде исправил) моргает) Испытатель да, через резистор 300 ом)
_________________ глаза боятся, а руки что то не делают))
Последний раз редактировалось sergo80zxc Вт май 06, 2014 00:33:47, всего редактировалось 1 раз.
push r16 ; сохраняем используемые регистры r16 (этих пушей может быть много) push r17 ; сохраняем используемые регистры r17 (этих пушей может быть много) in r17, SREG ; сохраням флаги push r17 ; и запихиваем их в стек
sbis PORTC,0 ; читаем бит С0, если этот бит установлен, пропускает следующую команду RJMP KUKA ; зажигаем светодиод на ножке С0 cbi PORTC, 0 ; гасим светодиод на ножке С0
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
pop r16 ; выдергиваем 2 байта ркаловских) так как выходим через жопу) pop r16
sei ; разрешить прерывания
RJMP MAIN
выровнял стек вроде работает) ваше учение о 2 байтах испытатель вспомнил)
все равно чето не то, что то намудрил
или вот так через рети?
Спойлер
Код:
; по идее программа зажигает и гасит светодиод С0 (посажен светодиод на массу) по переполнению таймера Т0 ; ;работает программа ; .cseg .include "m8Adef.inc"
push r16 ; сохраняем используемые регистры r16 (этих пушей может быть много) push r17 ; сохраняем используемые регистры r17 (этих пушей может быть много) in r17, SREG ; сохраням флаги push r17 ; и запихиваем их в стек
sbis PORTC,0 ; читаем бит С0, если этот бит установлен, пропускает следующую команду RJMP KUKA ; зажигаем светодиод на ножке С0 cbi PORTC, 0 ; гасим светодиод на ножке С0
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
ldi r16, 0b00000011 out SFIOR, r16 ; сброс предделителей (0 бит) PSR10 (1 бит) PSR2 установкой в них 1
pop r17 ; извлекаем из стека флаги в r17 (обратный порядок при извлечении из стека) out SREG, r17 ; отправляем их обратно в регистр флагов pop r17 ; восстанавливаем регистр r17 pop r16 ; восстанавливаем регистр r16
sei ; разрешить прерывания
reti
Испытатель ваши фразы
сбрасывать каждый раз предделители тоже не обязательно. В регистре SFIOR помимо сброса предделителей есть другие функции. Правильнее использовать команды чтения-модификации-записи, а не прямой записи. Сбрасывать можно и нужно предделитель того таймера, который используете.
((команды чтения-модификации-записи, а не прямой записи )) это вы о чем?
((Сбрасывать можно и нужно предделитель того таймера, который используете.)) как?
((В регистре SFIOR помимо сброса предделителей есть другие функции)) какие?
_________________ глаза боятся, а руки что то не делают))
Последний раз редактировалось Gudd-Head Вт май 06, 2014 10:43:35, всего редактировалось 1 раз.
Оба варианта рабочие. Загляните в даташит. Раздел Register Summary. Найдите там регистр SFIOR. В нем используются 4 бита. 3-й бит относится к компаратору. 2-й бит - общее отключение подтягивающих резисторов. 1-й и 0-й биты - сброс предделителей. Причем, 1-й бит PSR2 (видите циферку 2?) сбрасывает предделитель таймера 2, а 0-й бит PSR10 (опять-таки циферки нам подсказывают, к чему относится) сбрасывает предделители таймеров 0 и 1. Вы используете только таймер 0. Бит PSR2 можно не трогать. Сбросить достаточно 1 раз во время инициализации. И вообще сброс нужен для одновременного старта таймеров. В Вашем случае сброс не уместен (хотя не является ошибкой). Далее, т.к. регистр SFIOR содержит другие управляющие биты, то правильнее делать не прямую запись
Код:
ldi r16, xxxxx out SFIOR, r16
а чтение-модификацию-запись (это дословно). Смотрите:
Код:
in r16, SFIOR; чтение ori r16, 0b1 ; модификация. установим крайний бит. лишние нули слева можно не писать out SFIOR, r16; запись
При таком обращении Вы измените только младший бит (сбросите предделитель таймеров 0 и 1), оставив остальные без изменений. сделайте такой код в прерывании: Спойлер
Код:
TIM0_OVF: in r16, PINC; читаем состояние ножек порта ldi r17, 1; 0b00000001 eor r16, r17; меняем значение 0-й ножки на противоположное out PORTC, r16; отправляем обратно в порт reti
ldi r16, 0b00000001 ; out TIFR, r16 ; сбрасываем флаг
ldi r16, 0b00000101 ; out TCCR0, r16 ; ;
in r16, SFIOR ; читаем порт регистра ori r16, 0b1 ; логическое или, устанавливаем в бит 0 еденицу out SFIOR, r16 ; пишем в бит 0 еденицу, сбрасываем предделитель Т0 и Т1
ldi r16, 0b00000001 out DDRC, r16 ; бит 0 порта С на выход sei ;
;********************************************************************************************************************** MAIN: RJMP MAIN
in r16, PINC ; читаем порт ldi r17, 1 ; присваеваем 0b00000001 eor r16, r17 ; исключаещее или, если бит 0 порта С =1, то результат =0, если бит =0, то результат =1 out PORTC, r16 ; пишем результат в порт С reti
Я ж Вас учил: сначала настройка - потом разрешение прерываний. У Вас наоборот. С портом аналогично. Сначала настройка порта - потом запуск прерывания, которое его менять будет. После out PORTC,r16 еще команду nop добавить - и вообще шик будет! См. даташит или Евстифеева. Глава про порты. Но в Вашей проге не критично.
Цитата:
я все переправил)
Осталось только орфографию в русских комментах исправить - и вообще не придерешься. P.S. Так как, заработало? )
Зарегистрирован: Сб май 10, 2014 00:39:35 Сообщений: 4
Рейтинг сообщения:0
Приветы . Вопрос по счётчикам - что можно почитать для тупых ? А то уже руки опускаются - читаю , читаю - и ничего не понимаю . Тему всю прочёл , по ссылкам ходил , в гугл ходил , к яндексу ходил .... я нипанимат !
возьмём просто (нулевой) таймер . TCNT0 8-ми разрядный таймер счётчик. TCCR0 - его делитель. если объявить делитель : TCCR0=1 // или =0b00000001 ? или =0x01 ? или TCCR0 = (1<<CS0X) где X - 1-3 ?а если 0 то таймер не работает ?
то-есть TCNT0 будет бегать от 0 до 255 (от 0x00 до 0xhh , или от 0b00000000 - до 0b11111111 ) ? его можно прочитать ? записать ? сравнить ? что-то сделать по переполнению ?
Предполагаю, что речь идёт о самом простом Т0 на борту mega8. Тогда
sevpers писал(а):
TCNT0 8-ми разрядный таймер счётчик.
да
sevpers писал(а):
TCCR0 - его делитель.
это регистр управления таймера. Для Т0 mega8 осуществляет разрешение/запрет счёта Т0 импульсов от общего с Т1 предделителя или внешних импульсов по заданному перепаду. Для других камней, у которых возможности Т0 гораздо шире, состояний TCCR0x значительно больше.
sevpers писал(а):
его можно прочитать ? записать ? сравнить ? что-то сделать по переполнению ?
на первые 3 вопроса - да; на последний - для определения переполнения лучше пользоваться регистром TIFR и TIMSK, если событие будет обрабатываться прерыванием.
Теория не закреплённая практикой - время на ветер.
// Declare your global variables here unsigned char Tim; // Объявляем переменную-аргумент для wait1
// Описываем функцию задержки на "Tim" тактов void wait1 (void) { TCNT1=0; while (TCNT1<Tim) {}; } void main(void) // Главная функция программы { // Declare your local variables here
Вообще, у Вас все реализовано как-то.. мягко говоря через анальный проход. проще было бы через прерывание сделать. Ну, если фузы выставили правильно, то у Вас получается, что задержка реализует частоту 7,372800 MHz / 1024 (коэффициент деления таймера) / 1 (значение переменной Tim, с которой сравниваете) = 7200 герц. А так как у Вас используются 2 задержки для 1 цикла, то результирующая частота = 7200 / 2 = 3600 Гц. Уменьшайте коэффициент деления таймера и подбирайте Tim нужную частоту
Сейчас этот форум просматривают: Majestic-12 [Bot] и гости: 29
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения