CrazyAlex 0 4 июня, 2007 Опубликовано 4 июня, 2007 · Жалоба не могу понять в чем дело: устройство: Мега->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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kool 0 4 июня, 2007 Опубликовано 4 июня, 2007 (изменено) · Жалоба А ждать завершения передачи (или опустошения буфера передачи) кто будет? (флаги TXC или UDRE) Изменено 4 июня, 2007 пользователем Александр Куличок Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrazyAlex 0 5 июня, 2007 Опубликовано 5 июня, 2007 · Жалоба А ждать завершения передачи (или опустошения буфера передачи) кто будет? (флаги TXC или UDRE) Думаю что ждать его будет мега. Если помотреть исходники, то видно, что все это в прерывании. Но все равно спасибо за участие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 5 июня, 2007 Опубликовано 5 июня, 2007 · Жалоба Уже мозг сломал. Подскажите кто-нибудь где копать??? В детали Вашей алгоритмизации я вряд ли вникну, но прерывание по передаче мне не нравится. Мне кажется, что должен быть запрет прерывания, если весь буфер передан. Может быть, мега передает больше буфера? (Проверить можно осциллографом или терминалкой) Причин не очень то много может быть - или память затирается (проверить, поставив останов в конце передачи), или индекс и длина массива портится во время передачи (проверить аналогично). Памяти свободной ведь много, можно организовать буфер для отладки и писать туда все, что ушло в 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); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kool 0 5 июня, 2007 Опубликовано 5 июня, 2007 (изменено) · Жалоба Думаю что ждать его будет мега. Если помотреть исходники, то видно, что все это в прерывании Детально не изучал Вашу программу и никогда не работал с модбас, но отмечу следующее: Мега ждать не будет. У Вас постоянно осуществляется передача по Uart1TXint(). Одновременно с этим после выставлении флага FrameReady1 в Uart1RXint() осуществляется вызов PrepareRespone1(), который тоже что-то пишет в UDR1 (функции readhr1() и sethr1() ). Изменено 5 июня, 2007 пользователем Александр Куличок Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Laksus 0 6 июня, 2007 Опубликовано 6 июня, 2007 · Жалоба Я не уверен, но по моему, ожидание отправки байта происходит, а после окончания отправки группы байт бит 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; но это тоже навряд ли повлияет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrazyAlex 0 6 июня, 2007 Опубликовано 6 июня, 2007 · Жалоба Спасибо всем за участие, попробую ответить, может натолкнет на что-то еще. 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). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sensor_ua 0 6 июня, 2007 Опубликовано 6 июня, 2007 · Жалоба 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))){;} Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 6 июня, 2007 Опубликовано 6 июня, 2007 · Жалоба Если поставить точку останова на UDR1=frame1[0], и потом по шагам, то все отвечает нормально. Возможно у вас перетирается буфер. Насколько это видно из кода программы в тот же буфер frame1 пишутся данные в RX обработчике. Я бы здесь посоветовал завести два непересекающийхся буфера. Один строго на отправку, второй строго на прием. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 7 июня, 2007 Опубликовано 7 июня, 2007 · Жалоба В модбасе сначала идет младший байт срс, а потом старший. В AVR компиляторах, в частности в IAR, тоже идет сначала младший, потом старший, в отличии от компилеров семейства 51, в частности Keil. У AVR'ов в UARTе есть еще один глюк (не знаю, правда, может его уже втихаря и починили) - это старт условие запуска приема байта генерируется не по перепаду уровня с 1 на 0, а по уровню 0. То есть, если подключить драйвер 485 к порту и отключить подтяжки, то при переключениии на передачу нога RX повиснет в воздухе и если уровень на ней станет низким и если приемник не будет отключен, то он начнет долбить прерывания. Приемник может в этот момент натворить очень много дел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrazyAlex 0 18 июня, 2007 Опубликовано 18 июня, 2007 · Жалоба Спасибо огромное всем кто откликнулся. Напомнили мне пару вещей, которые надо бы использовать в программах. Я в свою очередь с"катализировал" работу мысли у народа. :) А ларчик открывался просто: глючный (полуубитый) преобразователь 232-485 от ADAM. поставил новый такой же и все стало ОК. Еще раз всем спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться