|
Портится старший бит при приёме через UART, atmega1281 |
|
|
|
Feb 29 2008, 07:10
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Используется бридж USB to UART СР2101 silabs. Запускаю передачу файла через гипиертерминал. Файл состоит из последовательности ASCII цифорок. На меге творится что-то странное. На 9600 иногда принимается нормально, иногда через байт то есть например передаю несколько раз 2. на приёме вижу 0х32 0хb2 0x32 0xb2 ... и т.д. со всеми цифрами. Ситауация исправилась, когда на гипертерминале ставлю два стоп бита. На скорости 38400 два стоп бита уже не спасают. Мега работаёт на внутреннем RC генераторе на 4 Мгц. При старте программы генератор калибруется по внешнему часовому кварцу, который для асинхронного таймера. бодрейт считается так. Код #define UART_DOUBLE_SPEED 1ul
enum { UART_BAUDRATE_9600 = (unsigned)((F_CPU * (UART_DOUBLE_SPEED + 1ul)) / (16ul * 9600ul) - 1ul), UART_BAUDRATE_38400 = (unsigned)((F_CPU * (UART_DOUBLE_SPEED + 1ul)) / (16ul * 38400ul) - 1ul) } Вообще что это такое может быть? З.Ы. Гоняю данные другой терминальной программой всё ок и на приём и на передачу.
|
|
|
|
|
Feb 29 2008, 09:56
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Ну затактировать от кварца к сожалению не могу. Изделия уже были разработаны до моего появления в компании. Управление потоком тоже отключить не могу, так используется в данном Application. Все мои тестовые аппликейшены по несколько часов работали на приём/передачу с компом без ошибок. Калибровка производится правильно. Хотя... Вот код на поругание общественностью Код #define INTERNAL_CLOCK F_CPU
#define EXTERNAL_TICKS 2*4 #define CYCLE_LENGTH 7 #define REFERENCE_CLOCK 32768 #define REFERENCE_COUNT (INTERNAL_CLOCK * EXTERNAL_TICKS) / (REFERENCE_CLOCK * CYCLE_LENGTH)
static uint16_t Measurement(void) { uint16_t cnt = 0; ASSR |= (1 << AS2); TCCR2B = 1 << CS20; ATOMIC_SECTION_ENTER TCNT2 = 0; while (ASSR & 0x1B); do { cnt++; } while (TCNT2 < EXTERNAL_TICKS); ATOMIC_SECTION_LEAVE return cnt; }
void CalibrateInternalRc(void) { uint16_t count; uint8_t cycles = 0x80; do { count = Measurement(); if (count > REFERENCE_COUNT) OSCCAL--; if (count < REFERENCE_COUNT) OSCCAL++; if (count == REFERENCE_COUNT) { break; } } while (--cycles); }
|
|
|
|
|
Feb 29 2008, 10:50
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Цитата Ну затактировать от кварца к сожалению не могу. Изделия уже были разработаны до моего появления в компании. А на ноги припаять кварц нельзя чтоли? Я ж говорю, для теста. Цитата Все мои тестовые аппликейшены по несколько часов работали на приём/передачу с компом без ошибок. А в чем тогда вообще проблема? В том что не работает с конкретным гипертерминалом? На другом компе можно еще попробовать, может это глюк конкретного компа.
--------------------
|
|
|
|
|
Feb 29 2008, 11:27
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(xelax @ Feb 29 2008, 09:56)  Калибровка производится правильно. Хотя... Вот код на поругание общественностью  С первого взгляда вроде бы всё в порядке с программой калибровки, но создаётся такое впечатление, что частота откалибрована немного неверно, поскольку иногда вы принимаете стоп-бит посылки в качестве последнего бита. Возможно, это связано с тем, что программа калибровки написана на си, и в вашем частном случае количество МЦ в цикле измерения не совпадает с заданными в программе 7-ю МЦ, может быть из-за уровня оптимизации, может быть из-за различных версий компилятора или даже другого компилятора... Попробуйте напрямую выдать сигнал на ножку OC2A (или OC2B) в режиме output compare match и померить частоту сигнала с помощью частотомера. Отсюда легко будет вычислить скорость приёма по рс232.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 29 2008, 12:09
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Кроме отклонения RC от номинального значения есть ещё и отклонение частоты UART от номинала за счёт "неUART-ности" частоты в 4МГц. Я на меге64 внутренний RC 8MHz калибровал по часовому кварцу на 7,373MHz (по апнотам по калибровке можно калибровать в пределах +-10% от базовой частоты) и на 115200 работало без проблем. Но я калибровал не при старте, а постоянно - SQW от DS1338 было заведено на прерывание и замерялось внутренним таймером расстояние между перепадами (0,5с), подкалибровывался OSCCAL. Даже "на столе" RC немного плывёт, особенно после старта, поэтому однократная калибровка сразу после включения может быть недостаточной для работы. А уж при изменении температуры... Но при подкалибровке каждые 0,5секунды работало в том числе при нагреве феном и при охлаждении FREEZ-ом вплоть до образования инея на плате.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 29 2008, 23:44
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Попробуйте "сменить" ПО на РС. AVR, наверняка, не при чем, потому что...: Примерно год назад столкнулся с аналогичной проблемой. Даже тему по этому поводу открывал. Причем я был в полной уверенности, что неправильно работает контроллер. Вроде бы, нашел причину (скорость снизил), сказал "спасибо", а на следующий день проблема вернулась... ..... Причина, на мой взгляд, не в контроллере и его инициализации, а в работе, настройках и инициализации последовательного порта, или VCP в Вашем случае, на PC. Я писал свою программу на Borland'e, при этом для RS232 использовал класс ПП (Последовательного Порта) от "comspy" (freeofcharge). Точно так же "болел" старший бит. Причем болезнь была приходящей (плавающей). Не помогало ни чего... Ни изменение скорости обмена, ни замена контроллера, ни смена компьютера, ни экранировка каждого провода в соединительном кабеле (до "маразма" доходил в попытках понять причину болезни  ) Вылечил, заменив класс ПП от comspy на аналогичный от г-на Горского. Все написанные позже проги с использованием класса от Горского работают с ПП (во всех его видах) на "Ура". .... В "описании" происходящего процесса целиком и полностью согласен с =GM=: Цитата(=GM= @ Feb 29 2008, 14:27)  ... иногда вы принимаете стоп-бит посылки в качестве последнего бита.... А вот чего я понять не смог, так это того в чем все-таки разница в инициализации ПП на РС. Оба указанных класса инициализируют ПП "классически" и фактически одинаково. .... И еще по этому поводу... http://electronix.ru/forum/index.php?act=S...f=48&t=7846
|
|
|
|
|
Mar 1 2008, 14:18
|

Частый гость
 
Группа: Свой
Сообщений: 105
Регистрация: 6-01-06
Пользователь №: 12 901

|
Цитата(zltigo @ Mar 1 2008, 13:11)  Не верю! Читайте написанное ReAl. Полемику по этому поводу считаю бессмысленной. Я, безусловно, могу ошибаться. Во всяком случае, для поисков неисправности "в" контроллере сначала необходимо убедиться в правильной работе интерфейса. Именно о таких "граблях" я хочу предупредить. Советуя обратить внимание на ПО РС, я исходил из: Цитата(xelax @ Feb 29 2008, 10:10)  ... З.Ы. Гоняю данные другой терминальной программой всё ок и на приём и на передачу. А необходимость правильной установки/калибровки скорости обмена, конечно же, является условием первостепенной значимости для надежной, без сбоев работы интерфейса. P.S. Вот comspy от г-на М.Белоусова. А вот статья и собственно класс для работы с ПП от г-на Ю.Горского.
Gorsky.rar ( 2.42 килобайт )
Кол-во скачиваний: 131
|
|
|
|
|
Mar 3 2008, 06:59
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
К стати баг проявляется только в гипертерминале, тестеры погоняли данные Zoc'ом и там всё ок. Мне кажется, что здесь скорее зависит всё от дров которые на писишке применяются. Потому что мелкосхемы UART'ов имеют множество дополнительной функциональности. А юзеру писишки предоставляется некий стандартный интерфейс, который обеспечивается виндовыми дровами и который множество функций просто не задействует. Сам с подобным сталкивался, когда писал софт на писишке для управления микросхемой расширения ISA шины в 4 UARTа. И когда решил применить свой код к UARTу, который стоял на материнке, то к удивлению аппаратные FIFO буферы, документированные для микросхемы, заработали и на материнке. Я думаю, что проблема комплексная гипертерминал кривой и калибровку генератора криво провожу. Посмотрел дизасм кода калибровки в раличных режимах оптимизации. В -O0 она действительно 7 тактов, а при -Os я так и не смог в процедуре понять где она эта калибровка начинается, а где заканчивается, но есть большое подозрение, что она уже не 7 тактов.
Сообщение отредактировал xelax - Mar 3 2008, 07:00
|
|
|
|
|
Mar 3 2008, 08:01
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(xelax @ Mar 3 2008, 08:59)  И когда решил применить свой код к UARTу, который стоял на материнке, то к удивлению аппаратные FIFO буферы, документированные для микросхемы, заработали и на материнке.  Насколько я помню, были чипы 16450 без FIFO, 16550 с глючным FIFO и 16550A с поправленным. И не помню - можна ли было определить разницу между 16550 и 16550А программно. В свойствах порта у винды можна было поставить/снять галку "использовать FIFO" и подвигать ползунки порога прерывания на приём и передачу - может, просто в Вашем случае драйвер сам не понял, стоит у него чип с нормальным FIFO или с глючным и галка по умолчанию была снята. Я сам иногда снимал, когда приходилось работать с чужим оборудованием с встроенной программой, которая захлёбывалась, если от компа валил "зафифошенный" поток без пауз. Цитата(xelax @ Mar 3 2008, 08:59)  Посмотрел дизасм кода калибровки в раличных режимах оптимизации. В -O0 она действительно 7 тактов, а при -Os я так и не смог в процедуре понять где она эта калибровка начинается, а где заканчивается, но есть большое подозрение, что она уже не 7 тактов. А зачем было вообще так делать? Сделайте так: Прерывание по таймеру2, когда он отсчитал нужное число циклов (причём это можно делать не только при старте, см. мой предыдущий пост), в этом прерывании чтение нового состояния таймера1, определение дельты с предыдущим состоянием таймера1 и подкоррекция OSCCAL прямо в прерывании. Разброс времени входа в прерывание чепуха по сравнению с периодом прерываний, RC-генератор всё равно грубее шаг имеет. Я метки времени от внешних часов даже не на ICP заводил а на обычное прерывание, смысла нет выжимать лучше нескольких сот микросекунд на фоне 0,5секунды (это 0,1%, куда тому RC). И никакой зависимости от оптимизатора (если работа программы зависит от установленного уровня оптимизации компилятора, то в 99.9% случаев это ляп или как минимум недоработка разработчика программы).
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 3 2008, 11:48
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(ReAl @ Mar 3 2008, 11:01)  И никакой зависимости от оптимизатора (если работа программы зависит от установленного уровня оптимизации компилятора, то в 99.9% случаев это ляп или как минимум недоработка разработчика программы). Полностью согласен.  В свою защиту хочу сказать, что код достался мне по наследству, а посему досконально не проверялся. А по поводу таймеров идея хорошая, но в моих условиях нереализуемая. Так как поверх моих функций народ пишет свои приложения и запросто может так совпасть, что прерывание от таймера возникнет в момент длинной по времени критической секции. Тогда все тайминги уплывут и откалибруется неправильно. Надо существующий вариант доделывать до верного. Например переписать на асме, чтобы не зависеть от уровня оптимизации.
|
|
|
|
|
Mar 6 2008, 15:53
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(xelax @ Mar 3 2008, 13:48)   В свою защиту хочу сказать, что код достался мне по наследству, а посему досконально не проверялся. Такой код надо проверят в первую очередь  Цитата запросто может так совпасть, что прерывание от таймера возникнет в момент длинной по времени критической секции. Тогда все тайминги уплывут и откалибруется неправильно. Если "критическая секция" займёт аж милисекунду, то что-то очень неправильно в Датском королевстве. Но даже в этом случае ошибка будет на уровне 1мс/500мс = 0,2% - при шаге перестройке RC на единичку OSCCAL в несколько раз больше эта ошибка не повлияет на калибровку. Цитата Надо существующий вариант доделывать до верного. Например переписать на асме, чтобы не зависеть от уровня оптимизации. Существующий вариант - с однократной калибровкой в начале - до верного можно доделать только методом переписывания на прерывания, чтобы обеспечить постоянную подкалибровку. Пальца на микроконтроллер достаточно, чтобы RC поплыл и понадобилось OSCCAL изменить. На этом фоне даже такой ужас, как критическая секция на четыре-восемь тысяч циклов процессора при постоянной подкалибровке повлияет меньше, чем открытое окно зимой при однократной калибровке.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|