лекция 343. Atmega8 применение таймера0

preview_player
Показать описание
Показано, как программировать таймер-счетчик 0 контроллера на примере динамической индикации. В основу положена лекция 335, к которой добавлены элементы прерывания. Для использования таймера 0 достаточно задать функцию обработки, частоту срабатывания и разрешить прерывания контроллера. Предварительно необходимо установить указатель стека. Список всех лекций на сайте автора в описании канала.
Рекомендации по теме
Комментарии
Автор

Настоящий специалист! И очень хороший педагог!

dimadavidkov
Автор

Отличный канал. Всегда с удовольствием смотрю.

igorkudashev
Автор

Спасибо. Вспомнил как разрабатывал первое устройство с семисегментником, в один момент нам стало жутко не хватать лап, но менять контроллер не хотелось, т.к. 48я мега уже была под рукой, а новый требовалось еще купить. И тут пришла мысль про динамическую развертку, что освободило сразу 7 лап контроллера. Просто ностальгия.

NordFawkes
Автор

мне кажется актуальней если бы код писали на Си. А за уроки большое спасибо !

esthetik_life
Автор

Добрый день. Спасибо за Ваши лекции очень интересно и познавательно. Подскажите пожалуйста почему для разрешения прерываний не использовали команду SEI

АндрейГвоздюк-лэ
Автор

Спасибо за лекцию! Подскажите, это вы на ассемблере делаете, верно?

sancholife
Автор

Спасибо Вам за отличные уроки!
Изучая Ваши лекции по Atmega8 я параллельно интерпретирую их для Atmega328P.
Код в AVR Studio v.4.19 выполняется без проблем. А в Proteus v.8.4 выдает ошибку
Invalid opcode 0xFFFF at PC=0xEA12
Хочу разобраться: это я не до конца разобрался с темой таймеры/прерывания или Протеус глючит?
Помогите разобраться! Вот код измененный мной под Atmega328P:

;(0)подключить описание макросов
.include "abg.inc"

;(1)блок данных
.dseg
.org $100
segments: .BYTE 4 ;- байты для индикатора
segm_num: .BYTE 1 ;- номер текущего сегмента
number: .BYTE 1 ;- изменяемое число

;(2)начало блока кода
.cseg
rjmp start
reti ; rjmp int0
reti ; rjmp int1
reti ; rjmp pcint0
reti ; rjmp pcint1
reti ; rjmp pcint2
reti ; rjmp wdt
reti ; rjmp timer2compA
reti ; rjmp timer2compB
reti ; rjmp timer2ovf
reti ; rjmp timer1capt
reti ; rjmp timer1compA
reti ; rjmp timer1compB
reti ; rjmp timer1ovf
reti ; rjmp timer0compA
reti ; rjmp timer0compA
rjmp timer0ovf
reti ; rjmp spi_stc
reti ; rjmp usart_rx
reti ; rjmp usart_udre
reti ; rjmp usart_tx
reti ; rjmp adc
reti ; rjmp ee_ready
reti ; rjmp analog_comp
reti ; rjmp twi
reti ; rjmp spm_rdy
;(3)обработчики прерываний
timer0ovf: ;;обработчик прерываний таймера 0
;сохранить затираемые регистры
push r30
push r31
push r25
push r20

in r20, $3f ;- сохранить состояние регистра признаков ($3f)
push r20

;получить номер сегмента для вывода символа
lds r20, segm_num
inc r20 ;- перейти к следующему символу
andi r20, $3
sts segm_num, r20
;включить заданный сегмент
get_srambyte r25, segments, r20 ;- выводимый символ
get_flashbyte r20, cathodtabl, r20 ;- байт выбора катода
out $05, r20 ;- вывели в порт B номер катода
out $0B, r25 ;- вывели в порт D символ
;закончить обраборку прерывания
pop r20
out $3f, r20 ;- восстановить регистр признаков

pop r20
pop r25
pop r31
pop r30
reti

;(4)резерв

;(5)подключить таблицы и подпрограммы
;; 5.A таблица переходов по коду клавиши
adrtabl: .dw begin, lreset, lincr, begin, ldecr, begin, begin, begin, lshift, begin, begin, begin, begin, begin, begin, begin
;; 5.B таблица кодов 7-сегментного индикатора
segmtabl: .db $3F, $06, $5B, $4F, $66, $6D, $7D, $07, $7F, $6F, $77, $7C, $39, $5E, $79, $71
;; 5.C таблица перекодирования номера сегмента
cathodtabl: .db $FE, $FD, $FB, $F7

;(6)подпрограмма формирования сегмента 0 из r20
form_segm0:
lds r20, number
andi r20, $0f
get_flashbyte r20, segmtabl, r20
sts segments, r20
ret

start:
;(7)настроить проты для вода и вывода
init_stack ;- установить стек на конец SRAM
mouti $04, $0f ;- PORTB на ввод-вывод
mouti $05, $f0
mouti $0A, $ff ;- PORTD только на вывод
mouti $0B, $00
mouti $25, $03 ;- выбрать частоту таймера0 = 32 тактов (TCCR0)
; mouti $39, 1 ;- разрешить прерывания таймера0 (TIMSK)
ldi r25, 1
sts $6e, r25
mouti $3f, $80 ;- разрешить все прерывания

;(8)выполнить начальные установки
ldi r20, $05
sts number, r20
get_flashbyte r20, segmtabl, r20
sts segments, r20
sts segments+1, r20
sts segments+2, r20
sts segments+3, r20

;(9)подождать нажатия клавиши
begin:
in r25, $03 ;-- get keys
andi r25, $f0
breq begin

;(10)подождать отпускания клавиши и перейти на (11)
wait_up: ;-- delay for 5ms
delay5 1000 ;-- delay for 5000 tacts
;-- wait for empty keys
in r19, $03 ;-- get keys
andi r19, $f0
breq table_transition
or r25, r19
rjmp wait_up

;(11)перейти по таблице (5A) adrtabl и коду полученной клавиши
table_transition:
swap r25
andi r25, $0f
get_flashword adrtabl, r25
ijmp

;(5A1)сбросить счетчик и перейти на (9)
lreset:
ldi r20, 0
sts number, r20
rcall form_segm0
rjmp begin

;(5A2)увеличить счетчик на 1 и перейти на (9)
lincr:
lds r20, number
inc r20
sts number, r20
rcall form_segm0
rjmp begin

;(5A4)уменьшить счетчик на 1 и перейти на (9)
ldecr:
lds r20, number
dec r20
sts number, r20
rcall form_segm0
rjmp begin

;(5A8)сдвинуть сегменты и перейти на (9)
lshift:
lds r20, segments + 2
sts segments + 3, r20
lds r20, segments + 1
sts segments + 2, r20
lds r20, segments
sts segments + 1, r20
ldi r20, 0
sts number, r20
rcall form_segm0
rjmp begin

ВладимирВладимирович-оиь
Автор

Не понимаю в обработчике прерываний этих строк:
lds r20, segm_num ; - тут понятно, загружаем номер катода из sram
inc r20 ; - переходим на следующий
andi r20, 3 ; А вот это не понятно, зачем делать.
; Объясните пожалуйста!

ultexplorer
Автор

Скромное мнение от начинающего - все же когда простые команды ввода в РОН и потом в РВВ, т.е. ldi и out заменяются макросами, то программа смотрится как-то не комфортно. Также и когда пишутся адреса, а могли бы писаться и названия регистров, то тоже лишний раз возникают так сказать "напряги" (т.е. зачем писать адрес регистра, например, s16, когда можно написать PINB ?). Ассемблер для AVR по сравнению с PIC и так имеет через чур много команд, свыше 130, то лишний раз загружать голову не хочется). Пара лишних строк, вместо замены их макросами, на мой взгляд "погоды не сделает". Надо наоборот стремиться упрощать программы, чтобы при взгляде на них "полюбить" ассемблер). А так - автор большой молодец и спец, желаю ему успешно довести начатое нелегкое это дело обучения))).

Александр-ьо