Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема в работе Timer1 при подсчете внеш.имп.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Stas633
Собрал устройство определения угла поворота сельсина. Принцип основан на измерении разности фаз между образцовым сигналом и сигналом с датчика (якорная обмотка). На ПЛИС из этих сигналов формируется пачка импульсов, число которых зависит от разности фаз (угла поворота), по окончанию "периода измерения" ПЛИС формирует одиночный импульс.
Алгоритм работы AVR (ATmega8) такой:
1. Режим ТС1 - подсчет импульсов на входе Т1 (PD5);
2. По приходу одиночного импульса на ICP1 (PB0) происходит "захват" ТС1 и в прерывании по "захвату" - запоминание захваченного значения, обнуление ТС1;
3. Запомненное значение передается по UART'ту. По запросу от РС.

При работе младший байт ТС1 считает только до 127 (0х7F). При этом старший байт инкриминируется правильно, то есть, как если бы младший считал до 255.

При этом ошибка проявляется не сразу, а через несколько часов (8...20) после обесточивания схемы.

Для устранения ошибки делал следующее:
- менял способ (внешний, внутренний) и частоту (2...16МГц) тактирования AVR;
- заменил сам кристалл (ATmega);
- программу написанную на Си переписал на ASM'e....
....результата нет. На Си программа передачи данных по UART была написана с применением "printf" - все работало... На следубщий вечер - ошибка. Переписал через "UDR=.." - все пошло... На следующий вечер - опять ошибка... Перепаял AVR, прошил - норма (и с "UDR=..", и с "printf")... На следующий вечер - снова ошибка.... Переписал программу на ASM - нормально, но опять прошел день и ошибка появилась...
Частота следования счетных импульсов 500 кГц, менял на 1МГц - ошибка оставалась.
На ASM (AlgBlb) программа обработки прерывания по захвату такая:

Нажмите для просмотра прикрепленного файла

Подскажите в чем проблема?
otrog
Мне кажется, что между
Код
R18 -> UDR
R17 -> UDR
Надо вставить что-то типа (для си)
Код
while ( !( UCSRA & (1<<UDRE)) ){} /* Wait for empty transmit buffer */

Такое ощущение что у вас сбои происходят при передаче по УАРТ.
Stas633
Цитата(otrog @ Jul 26 2006, 10:38) *
Мне кажется, что между
Код
R18 -> UDR
R17 -> UDR
Надо вставить что-то типа (для си)
Код
while ( !( UCSRA & (1<<UDRE)) ){} /* Wait for empty transmit buffer */

Такое ощущение что у вас сбои происходят при передаче по УАРТ.


Скорость передачи по UART менял , "паузы" вводил - не помогает. Да и, в UART буфер (стек) 3-х байтный есть. И при использовании prinf - все через прерывания делается ... поэтому искажения от UART маловероятны. Пытался даже один младший байт передавать по UART.... результат тот же - до 0x7F...
_Bill
Цитата(Stas633 @ Jul 26 2006, 10:11) *
Цитата(otrog @ Jul 26 2006, 10:38) *

Мне кажется, что между
Код
R18 -> UDR
R17 -> UDR
Надо вставить что-то типа (для си)
Код
while ( !( UCSRA & (1<<UDRE)) ){} /* Wait for empty transmit buffer */

Такое ощущение что у вас сбои происходят при передаче по УАРТ.


Скорость передачи по UART менял , "паузы" вводил - не помогает. Да и, в UART буфер (стек) 3-х байтный есть. И при использовании prinf - все через прерывания делается ... поэтому искажения от UART маловероятны. Пытался даже один младший байт передавать по UART.... результат тот же - до 0x7F...

Вы попробуйте сначала проверить передачу данных через UART, но данные не от таймера, а просто набор символов. Проверьте согласование форматов данных, скорости и т.д. После этого будете с таймером разбираться. Можно и с таймера начать, но тогда для начала лучше содержимое таймера выводить в порт и индицировать с помощью светодиодов, например.
Stas633
Цитата
Вы попробуйте сначала проверить передачу данных через UART, но данные не от таймера, а просто набор символов. Проверьте согласование форматов данных, скорости и т.д. После этого будете с таймером разбираться. Можно и с таймера начать, но тогда для начала лучше содержимое таймера выводить в порт и индицировать с помощью светодиодов, например.


И это делал... UART ошибок не вносит! Во всяком случае при передаче.
А вот, на счет вывода в порт AVR - спасибо, попробую.
Petka
И ещё одна шальная мысль: UART выделяет начало байта ориентируясь по стартовому биту. Если идёт непрерывный поток данных, то UART может принять за стартовый какой-нибудь бит из передаваемого байта и тогда вся синхронизация по началу байта пудет потеряна (точнее синхронизация будет ложной). и будете получать левую информацию. особенно часто это происходит, когда переодически без промежутков шлётся один и тот-же байт. для того, что бы синхронизация сама по себе восстанавливалась я между пакетами шлю 0x00 а затем 0xff т.е. такие байты, что внутри одного нет бита, который можно принять за стоп, а внутри друго нельзя найти ложный старт =). вдруг у Вас такая же "фича"?
Stas633
Цитата(Petka @ Jul 26 2006, 12:24) *
И ещё одна шальная мысль: UART выделяет начало байта ориентируясь по стартовому биту. Если идёт непрерывный поток данных, то UART может принять за стартовый какой-нибудь бит из передаваемого байта и тогда вся синхронизация по началу байта пудет потеряна (точнее синхронизация будет ложной). и будете получать левую информацию. особенно часто это происходит, когда переодически без промежутков шлётся один и тот-же байт. для того, что бы синхронизация сама по себе восстанавливалась я между пакетами шлю 0x00 а затем 0xff т.е. такие байты, что внутри одного нет бита, который можно принять за стоп, а внутри друго нельзя найти ложный старт =). вдруг у Вас такая же "фича"?


Трудно согласиться. Обмен по UART был сложнее, чем в приведенном примере: AVR ждал "запроса" от PC на передачу. После получения запроса передавал 3 байта, последний из которых - 0х00. В другом устройстве (измерение частоты) обмен данными по UART по такому алгоритму не вызывает нареканий.
Вот только, ТС1 работает там не в режиме подсчета внешних импульсов. Да и, повторю, программа была написана через getchar() и printf(), а компилятор CV_AVR эти функции "отрабатывает" с использованием прерываний, т.е. "наслоение" маловероятно... С другой стороны, возможность неправильной работы одного бита ТС1, причем, только на чтение, в двух микросхемах...еще менее вероятна...

Одним словом, попробую сегодня выводить "ошибочный" бит в порт AVR для анализа, при этом, те же данные будут передаваться по UART.

В любом случае, спасибо!!!
Petka
ещё мысль. тактируется МК от RC или от кварца? может немного не совпадают частоты и старший бит просто "наползает" на стоповый?
Stas633
Цитата(Petka @ Jul 26 2006, 14:27) *
ещё мысль. тактируется МК от RC или от кварца? может немного не совпадают частоты и старший бит просто "наползает" на стоповый?


Очень возможно! Сейчас МК тактируется от внутр. RC на частоте 2 МГц. При этом, калибровочный байт я не загружаю.
Частота работы UART - 4800, а это "по-умолчанию" 0,2% ошибок при 2МГц, да еще и Int.RC не точен!
В старшем байте старший бит всегда 0, поэтому ошибки не возникает, а с младшим - проблемы.
Но с другой стороны, при передаче констант 0xAA и 0x55 - ошибок нет. Нужен эксперимент! Вечером попробую..
МК тактировался изначально от внешнего "Clock" 16МГц - ошибка была. Потом уже начались "поиски" с выбором источника тактирования, скоростью UART, "упрощением" программы...

Спасибо, еще раз.
Stas633
Попробовал и выяснил следующее, опосториорное мнение, так сказать...

Цитата(Petka @ Jul 26 2006, 14:27) *
..... может немного не совпадают частоты и старший бит просто "наползает" на стоповый?

Проблема именно в этом. При уменьшении частоты UART, относительно номинальной, происходит потеря (обнуление) старшего бита.
Таким образом, при использовании UART желательно применение кварцевой стабилизации МК, и использование той из стандартных частот (предделитель в регистре UBRR), на которой процент ошибок минимален.

Спасибо за помощь!

Удачи!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.