Неровная работа тактового генератора

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 72
Зарегистрирован: Вт апр 01, 2014 16:33:06
Откуда: Москва

Сообщение Против часовой »

В учебных целях написал маленькую программу для tiny2313: на порт B выводится код Морзе. Повесил на один из контактов пищалку - все работает. Однако, время от времени, то сигналы, то паузы между сигналами тянутся дольше положенного. Это заметно на слух. При чем такие сбои не имеют какой-то заметной регулярности. Происходят, когда захотят.
Все это дело работает на внутреннем тактовом генераторе, без использования внешнего кварца. Переключение сигнал/пауза происходит по прерыванию компаратора. Питание - 5 вольт через стабилизатор. Скачков напряжения не вижу.
Отчего же такая неровная работа МК? Проблема в генераторе или может быть другая причина?
Спойлер

Код: Выделить всё

  .cseg

  rjmp  RESET
  reti  ; INT0
  reti  ; INT1
  reti  ; TIMER1 CAPT
  rjmp  TIMER1_COMPA
  reti  ; TIMER1_OVF
  reti  ; TIMER0 OVF
  reti  ; USART0, RX
  reti  ; USART0, UDRE
  reti  ; USART0, TX
  reti  ; ANALOG COMP
  reti  ; PCINT0
  reti  ; TIMER1 COMPB
  reti  ; TIMER0 COMPA
  reti  ; TIMER0 COMPB
  reti  ; USI START
  reti  ; USI OVERFLOW
  reti  ; EE READY
  reti  ; WDT OVERFLOW
  reti  ; PCINT1
  reti  ; PCINT2

RESET:
  ; Резервируем R16 = 255, R17 = 0, R18 - текущее состояние PORTB, R19 - текущий индекс массива TONES (см. внизу).
  ser   R16
  clr   R17
  ser   R18
  clr   R19
  ; Определяем PB0-PB7 как источники тока.
  out   DDRB, R16
  out   PORTB, R18
  ; Настраиваем делитель таймера 1 на 1/64.
  ldi   R20, 3
  out   TCCR1B, R20
  ; Обрабатываем текущий элемент массива TONES.
  rcall READ_TONE
  ; Разрешаем прерывание компаратора 1.
  ldi   R20, 0x40
  out   TIMSK, R20
  ; Разрешаем прерывания.
  sei

LOOP:
  ; Уходим в цикл.
  rjmp  LOOP

TIMER1_COMPA:
  ; Инвертируем PORTB.
  com   R18
  out   PORTB, R18
  ; Обрабатываем текущий элемент массива TONES.
  rcall READ_TONE
  ; Выходим из обработчика.
  reti

READ_TONE:
  ; Загружаем адрес TONES в Z.
  ldi   ZH, HIGH(TONES * 2)
  ldi   ZL, LOW(TONES * 2)
  ; Переходим к элементу R19.
  add   ZL, R19
  adc   ZH, R17
  ; Обнуляем таймер 1.
  out   TCNT1H, R17
  out   TCNT1L, R17
  ; Присваиваем значение компаратору 1.
  lpm
  out   OCR1AH, R0
  out   OCR1AL, R16
  ; Инкрементируем индекс R19.
  inc   R19
  ; Проверяем переполнение индекса.
  cpi   R19, LENGTH
  brne  READ_TONE_RET
  clr   R19

READ_TONE_RET:
  ; Выходим из подпрограммы
  ret

; Массив воспроизводимых кодов Морзе размером LENGTH.
; Нечетные элементы - продолжительность сигналов, четные - продолжительность пауз между ними.
; Продолжительность - (TONES[i] + 1) * 0xFF тактов таймера.
TONES:
  ;     МУХА – – · · – · · · – · –
  .db   0x7F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F
  .db   0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF
  .equ  LENGTH = 22

  ;;     СОС · · · – – – · · ·
  ;.db   0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x7F
  ;.db   0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
  ;.equ  LENGTH = 18
Реклама
akl
Друг Кота
Сообщения: 4468
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Установите стек, выровняйте массив МУХА по словам в каждой строке.
Спойлер

Код: Выделить всё

; Массив воспроизводимых кодов Морзе размером LENGTH.
; Нечетные элементы - продолжительность сигналов, четные - продолжительность пауз между ними.
; Продолжительность - (TONES[i] + 1) * 0xFF тактов таймера.
TONES:
  ;     МУХА – – · · – · · · – · –
	.DB		0x7F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
	.DB		0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
	.DB		0x7F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF
TONES_END:
;	.db   0x7F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F
;	.db   0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Проблема в кривых руках! :)))

Вы думаете, что разработчики настолько лохи, что засунули в МК генератор, стабильность которого плавает фиг знает от чего, да еще и со скоростью в несколько кГц?
Последний раз редактировалось ИС-пытатель Пн апр 21, 2014 14:08:11, всего редактировалось 2 раза.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Спойлер
ИС-пытатель писал(а):скоростью в несколько кГц?
:facepalm:
Ставим плюсы: )
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Аватара пользователя
Сообщения: 577
Зарегистрирован: Ср июн 19, 2013 08:10:48
Откуда: Москва, СПб, Липецк, Рязань

Сообщение ИС-пытатель »

Скорость изменения частоты (частота изменения частоты). Вы прекрасно поняли, о чем я. Не надо тут ерничать.
Реклама
Открыл глаза
Сообщения: 72
Зарегистрирован: Вт апр 01, 2014 16:33:06
Откуда: Москва

Сообщение Против часовой »

Стек установил, массив выровнял. Пока никаких изменений. :(
Спойлер
ИС-пытатель писал(а):Вы думаете, что разработчики настолько лохи, что засунули в МК генератор, стабильность которого плавает фиг знает от чего, да еще и со скоростью в несколько кГц?
ИС-пытатель писал(а):Не надо тут ерничать.
P.S.: Для наглядности вот аудиозапись зуммера: http://file.qip.ru/file/p8jwpTfB/1.html.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15751
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Вложенная в прерывание от таймера подпрограмма в работе оказывается длиннее, чем интервал между прерываниями по таймеру.
:tea:
Открыл глаза
Сообщения: 72
Зарегистрирован: Вт апр 01, 2014 16:33:06
Откуда: Москва

Сообщение Против часовой »

На выполнение кода прерывания требуется не более 29 тактов. Плюс еще несколько на инициирование прерывания. А минимальное возможное расстояние между двумя прерываниями (в конкретном случае) - более 1 млн тактов. К тому же, подобные недочеты, равно как ошибки в коде, привели бы к какой-то заметной периодичности багов.
akl
Друг Кота
Сообщения: 4468
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Программа работает нормально. Смотрел осциллом. Чтобы синхронизировать посылку вывел импульс на PD0 и увеличил частоту в 64 раза. Тактирование tiny2313 от встроенного генератора 8МГц. Где-то сбоит в другом месте.
Спойлер

Код: Выделить всё

.include "tn2313Adef.inc"

.cseg

  rjmp  RESET
  reti  ; INT0
  reti  ; INT1
  reti  ; TIMER1 CAPT
  rjmp  TIMER1_COMPA
  reti  ; TIMER1_OVF
  reti  ; TIMER0 OVF
  reti  ; USART0, RX
  reti  ; USART0, UDRE
  reti  ; USART0, TX
  reti  ; ANALOG COMP
  reti  ; PCINT0
  reti  ; TIMER1 COMPB
  reti  ; TIMER0 COMPA
  reti  ; TIMER0 COMPB
  reti  ; USI START
  reti  ; USI OVERFLOW
  reti  ; EE READY
  reti  ; WDT OVERFLOW
  reti  ; PCINT1
  reti  ; PCINT2

RESET:
     ldi r16,low(RAMEND)       ;загрузка указателя стека
     out SPL,r16
  ; Резервируем R16 = 255, R17 = 0, R18 - текущее состояние PORTB, R19 - текущий индекс массива TONES (см. внизу).
  ser   R16
  clr   R17
  ser   R18
  clr   R19

	OUT	DDRD,R16
	OUT	PORTD,R17

  ; Определяем PB0-PB7 как источники тока.
  out   DDRB, R16
  out   PORTB, R18
  ; Настраиваем делитель таймера 1 на 1/64.
  ldi   R20,1
;  ldi   R20, 3
  out   TCCR1B, R20
  ; Обрабатываем текущий элемент массива TONES.
  rcall READ_TONE
  ; Разрешаем прерывание компаратора 1.
  ldi   R20, 0x40
  out   TIMSK, R20
  ; Разрешаем прерывания.
  sei

LOOP:
  ; Уходим в цикл.
  rjmp  LOOP

TIMER1_COMPA:
	CBI	PORTD,0
  ; Инвертируем PORTB.
  com   R18
  out   PORTB, R18
  ; Обрабатываем текущий элемент массива TONES.
  rcall READ_TONE
  ; Выходим из обработчика.
  reti

READ_TONE:
  ; Загружаем адрес TONES в Z.
  ldi   ZH, HIGH(TONES * 2)
  ldi   ZL, LOW(TONES * 2)
  ; Переходим к элементу R19.
  add   ZL, R19
  adc   ZH, R17
  ; Обнуляем таймер 1.
  out   TCNT1H, R17
  out   TCNT1L, R17
  ; Присваиваем значение компаратору 1.
  lpm
  out   OCR1AH, R0
  out   OCR1AL, R16
  ; Инкрементируем индекс R19.
  inc   R19
  ; Проверяем переполнение индекса.
  cpi   R19, LENGTH
  brne  READ_TONE_RET
  clr   R19
	SBI	PORTD,0
READ_TONE_RET:
  ; Выходим из подпрограммы
  ret

; Массив воспроизводимых кодов Морзе размером LENGTH.
; Нечетные элементы - продолжительность сигналов, четные - продолжительность пауз между ними.
; Продолжительность - (TONES[i] + 1) * 0xFF тактов таймера.
TONES:
  ;     МУХА - - · · - · · · - · -
	.DB		0x7F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
	.DB		0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
	.DB		0x7F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF
;  .db   0x7F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F
;  .db   0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF
  .equ  LENGTH = 22

  ;;     СОС · · · - - - · · ·
  ;.db   0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0x3F, 0x7F
  ;.db   0x3F, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
  ;.equ  LENGTH = 18
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

слухай, таймер останови, когда с ним работаешь.
Ответить

Вернуться в «AVR»