Перейти к содержанию
    

проблема с уарт Mega64

не могу понять в чем дело:

 

устройство: Мега->485->Adam->PC

 

софт: iccAVR6.31a, AVRstudio, jtag ice mk2 (не совсем софт), на PC самописный модбас-мастер (проверен временем), а также терминалка.

 

протокол модбас RTU, чтение регистров (03) идет на ура, запись (06) в регистр значение 511 - все отвечает правильно. запись значения 512 - вместо ответа какая-то хрень, число байт хрени совпадает с числом байт в ответе. причем эта самая хрень каждый раз разная. хотя запрос один и тот же.

 

смотрю в авр студии.

пакет приходит, регистр меняется на нужное значение, формируется в буферном массиве frame1 ответ (правильный ответ).

Портится на этапе UDR1=frame1[0], UDR1=frame1[outbytecnt]. т.е. в UDR1 или пишется что-то не то, или в нем самом портится..., т.е. PC принимает совсем не то что я записываю в UDR.

Если поставить точку останова на UDR1=frame1[0], и потом по шагам, то все отвечает нормально.

 

Исходники прилагаю.

 

Уже мозг сломал. Подскажите кто-нибудь где копать???

m64uart.ZIP

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ждать завершения передачи (или опустошения буфера передачи) кто будет? (флаги TXC или UDRE)

Изменено пользователем Александр Куличок

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А ждать завершения передачи (или опустошения буфера передачи) кто будет? (флаги TXC или UDRE)

 

Думаю что ждать его будет мега. Если помотреть исходники, то видно, что все это в прерывании. Но все равно спасибо за участие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уже мозг сломал. Подскажите кто-нибудь где копать???

В детали Вашей алгоритмизации я вряд ли вникну, но прерывание по передаче мне не нравится. Мне кажется, что должен быть запрет прерывания, если весь буфер передан. Может быть, мега передает больше буфера? (Проверить можно осциллографом или терминалкой)

Причин не очень то много может быть - или память затирается (проверить, поставив останов в конце передачи), или индекс и длина массива портится во время передачи (проверить аналогично).

Памяти свободной ведь много, можно организовать буфер для отладки и писать туда все, что ушло в UDR1.

 

void Uart1TXint(void) /**/
{
static unsigned char byteoutcnt1=1;

if (OutPacketLength1) 
{
  UDR1=frame1[byteoutcnt1];
  OutPacketLength1--;
  byteoutcnt1++;
} 
else 
{
  SetRE1;
  ResetDE1;
  byteoutcnt1=1;
} 
}

 

У меня так:

#pragma vector=USART_UDRE_vect
__interrupt void USART_transmit(void)
{    
  if ((uart0.tx_status==Uart0Transmitting)&&
      (uart0.tx_tail < uart0.tx_head))

        {   UDR = *uart0.tx_tail;    
            uart0.tx_tail ++;        
        }
  else  UCSRB &= ~(1 << UDRIE);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Думаю что ждать его будет мега. Если помотреть исходники, то видно, что все это в прерывании

Детально не изучал Вашу программу и никогда не работал с модбас, но отмечу следующее:

Мега ждать не будет. У Вас постоянно осуществляется передача по Uart1TXint(). Одновременно с этим после выставлении флага FrameReady1 в Uart1RXint() осуществляется вызов PrepareRespone1(), который тоже что-то пишет в UDR1 (функции readhr1() и sethr1() ).

Изменено пользователем Александр Куличок

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не уверен, но по моему, ожидание отправки байта происходит,

а после окончания отправки группы байт бит TXC вроде-бы остается сброшен.

Да и если бы проблема была в отсутствии ожидания,

то число байт, наверное, отличалось бы от ожидаемого.

 

Хотя я бы для отправки байтов использовал прерывание UDRE,

а TXC для отключения передатчика, но, по моему, должно работать и так.

______________________

 

Я глубоко конечно не разбирался, но первая мысль при чтении

причем эта самая хрень каждый раз разная. хотя запрос один и тот же.

А не результат ли это работы АЦП? Типа какой-нибудь шум, наводки.

 

И еще, а Вы пробовали делать ресет. А потом посылать запросы.

То есть, отличаются ли первые, вторые и тд ответы после сброса,

или только первый от второго, второй от третьего (после сброса)?

_________________________________________

Общий совет - надо упрощать пока не пропадет ошибка.

Если Вы, автор, не разберетесь, то постороннему тем-более трудно.

 

 

============================================================

 

Это не по теме, но может Вам будет интересно.

-----------------------------------------------------------

 

93:        unsigned int tmp=0;
+00000474:   24AA        CLR     R10              Clear Register
+00000475:   24BB        CLR     R11              Clear Register
97:        tmp=ADCL;            //Read 8 low bits first (important)
+00000476:   B0A4        IN      R10,0x04         In from I/O location
+00000477:   24BB        CLR     R11              Clear Register
98:        tmp|=(int)ADCH << 8; //read 2 high bits and shift into top byte
+00000478:   B025        IN      R2,0x05          In from I/O location
+00000479:   2433        CLR     R3               Clear Register
+0000047A:   2C32        MOV     R3,R2            Copy register
+0000047B:   2422        CLR     R2               Clear Register
+0000047C:   28A2        OR      R10,R2           Logical OR
+0000047D:   28B3        OR      R11,R3           Logical OR
100:       sum[adc]=sum[adc]-(sum[adc]>>8)+tmp;

Это, конечно, не ошибка

 

но, по моему, так красивше

93:        unsigned int tmp=0;
+00000474:   24AA        CLR     R10              Clear Register
+00000475:   24BB        CLR     R11              Clear Register
99:        tmp= ADC;/// А нормальный компилятор должен знать порядок чтения байт
+00000476:   B0A4        IN      R10,0x04         In from I/O location
+00000477:   B0B5        IN      R11,0x05         In from I/O location
100:       sum[adc]=sum[adc]-(sum[adc]>>8)+tmp;

============================================================

И еще, в

unsigned int crc16(void *ptr,unsigned int n)

 

 return ((crcl<<8)|crch);

может надо так?

 return ((crch<<8)|crcl);

 

============================================================

Совершенно мне не ясно, что получим в результате

 sum[adc]=sum[adc]-(sum[adc]>>8)+tmp;

но это тоже навряд ли повлияет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем за участие, попробую ответить, может натолкнет на что-то еще.

 

to Dog Pawlowa

 

В детали ... , но прерывание по передаче мне не нравится. Мне кажется, что должен быть запрет прерывания, если весь буфер передан. Может быть, мега передает больше буфера? (Проверить можно осциллографом или терминалкой)

Проверял терминалкой, в порт уходит нужное число байт.

... - или память затирается (проверить, поставив останов в конце передачи), или индекс и длина массива портится во время передачи (проверить аналогично).

Смотрел, все остается как было, ничего не портится.

 

to Александр Куличок

 

У Вас постоянно осуществляется передача по Uart1TXint(). Одновременно с этим после выставлении флага FrameReady1 в Uart1RXint() осуществляется вызов PrepareRespone1(), который тоже что-то пишет в UDR1 (функции readhr1() и sethr1() ).

Передача по TXint (по опустошению ВСЕХ регистров, участвующих в передаче) осуществляется столько раз сколько записано в UDR, т.е. после записи последнего байта, прерывание вызовется последний раз, и поскольку больше обращения к UDR не было, то и прерывание больше не возникнет. В readhr1 и sethr1 осуществляется первая запись в UDR которая и вызывает первое прерывание Uart1TXint().

 

to Laksus

 

Хотя я бы для отправки байтов использовал прерывание UDRE,

а TXC для отключения передатчика, но, по моему, должно работать и так.

Ноги такой работы с уартом растут из моего опыта работы с 51. Хотя изначально в Меге я использовал прерывание по UDRE, мне не понравилось. что надо разрешать/запрещать прерывания и я "ушел" на TXC. Мне лично оно кажется более логичным.

 

А не результат ли это работы АЦП? Типа какой-нибудь шум, наводки.

Пробовал, не помогает.

 

И еще, а Вы пробовали делать ресет. А потом посылать запросы.

То есть, отличаются ли первые, вторые и тд ответы после сброса,

или только первый от второго, второй от третьего (после сброса)?

Мысль интересная,попробую проверить.

 

Общий совет - надо упрощать пока не пропадет ошибка.

Если Вы, автор, не разберетесь, то постороннему тем-более трудно.

В общем то, расчет был на то что кто-нибудь сталкивался с подобным.

 

но, по моему, так красивше...

99: tmp= ADC;/// А нормальный компилятор должен знать порядок чтения байт

Дело в том что ImageCraft трудно отнести к нормальным компиляторам :-), но за неимением гербовой...

А эту структуру они сами настоятельно рекомендуют использовать.

 

И еще, в unsigned int crc16(void *ptr,unsigned int n) return ((crcl<<8)|crch);

может надо так? return ((crch<<8)|crcl);

В модбасе сначала идет младший байт срс, а потом старший.

 

Совершенно мне не ясно, что получим в результате

sum[adc]=sum[adc]-(sum[adc]>>8)+tmp;

но это тоже навряд ли повлияет.

Не помню как это правильно называется, навскидку вспоминается "экспоненциальное слаживание" и "скользящее среднее". В данном случае получается усреднение по 256 выборкам (почти среднее, математики оспорят, но меня устраивает).

 

 

Еще раз хочу обратить внимание, что на все запросы чтения ответ идет правильный, и на отдельные запросы записи тоже. Битые ответы, идут на строго фиксированные запросы, т.е. на 511 - все ок, на 512 - битый. и еще на некоторые другие запросы (78, 1101).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void PrepareRespone0(void){

. . .

addr=(frame0[2]<<8)|frame0[3];

value=(frame0[4]<<8)|frame0[5];

. . .

}

value для функции 16 вообще-то сдвинуто на 3 байта -

[0] - unicast address

[1] - function code

[2][3] - reference

[4][5] - word count,

[6] - byte count,

[7][8] - data

нужно:

value=(frame0[7]<<8)|frame0[8];

 

Ещё открою маленькую тайну;) - вот так:

crc=crc16((unsigned *)frame0,6);

if (crc==((frame0[7]<<8)|frame0[6]))

делать не надо - досчитав в CRC ещё и последние 2 байта, содержащие CRC, Вы получите (при совпадении конечно) красивый ноль. if(!(crc=crc16((unsigned *)frame0,8))){;}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если поставить точку останова на UDR1=frame1[0], и потом по шагам, то все отвечает нормально.

Возможно у вас перетирается буфер.

Насколько это видно из кода программы в тот же буфер frame1 пишутся данные в RX обработчике.

 

Я бы здесь посоветовал завести два непересекающийхся буфера. Один строго на отправку, второй строго на прием.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В модбасе сначала идет младший байт срс, а потом старший.

В AVR компиляторах, в частности в IAR, тоже идет сначала младший, потом старший, в отличии от компилеров семейства 51, в частности Keil.

 

 

У AVR'ов в UARTе есть еще один глюк (не знаю, правда, может его уже втихаря и починили) - это старт условие запуска приема байта генерируется не по перепаду уровня с 1 на 0, а по уровню 0. То есть, если подключить драйвер 485 к порту и отключить подтяжки, то при переключениии на передачу нога RX повиснет в воздухе и если уровень на ней станет низким и если приемник не будет отключен, то он начнет долбить прерывания. Приемник может в этот момент натворить очень много дел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо огромное всем кто откликнулся.

 

Напомнили мне пару вещей, которые надо бы использовать в программах.

 

Я в свою очередь с"катализировал" работу мысли у народа. :)

 

А ларчик открывался просто: глючный (полуубитый) преобразователь 232-485 от ADAM.

 

поставил новый такой же и все стало ОК.

 

Еще раз всем спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...