|
Работа TXC в USART, Не могу разобраться с флагом "окончание передачи", помогите |
|
|
|
 |
Ответов
(1 - 47)
|
Aug 20 2007, 03:06
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Цитата(Т.Достоевский @ Aug 20 2007, 08:46)  Доброго времени суток! Помогите разобраться с работой USART в tiny2313. Немогу понять как работает флаг TXC. В даташите написано что он выставляется по окончании передачи. Но там есть буферизация в 2 байта. Он выставляется если передал 1 байт или если передал всё? Честно говоря никогда не испольвал этот флаг. Использую вместо него UDRE, он выставляется если регистр данных передатчика пуст и готов к отправке следующего байта. Рекомендую воспользоваться этим прерыванием. Цитата(Т.Достоевский @ Aug 20 2007, 08:46)  ЗЫ. В прерывании сбрасывал флаг записью в него 1. При передаче 2х байт запрещал прерывания для неразрывности, всё равно ничего не добился. Смотрел по осцылу время нахождения в режиме передача, но ничего непонял. Сколько реально времени (включая служебные биты 1-четности и 1-стоп 9-ый) будет передавать 2 байта усарт? Флаг в прерывании сбрасывать ненужно. Это происходит автоматически, если прерывание было вызвано. Вообще для отладки всего воспользуйтесь терминальной программой и подключите USART МК через MAX232 к com порту компьютера. Так Вы сумеете устранить все ошибки без особого усилия.
--------------------
Выбор.
|
|
|
|
|
Aug 20 2007, 07:06
|
Тутэйшы
   
Группа: Свой
Сообщений: 708
Регистрация: 30-11-04
Пользователь №: 1 263

|
Для 485 я пользую следующие конструкции: Код //POPTE #define RXD0 0 #define TXD0 1
#define RS485_DDR DDRE #define RS485_PORT PORTE #define RS485_PIN PINE
#define GL_BUS_DIR 2 #define Global_Bus_RS485_Dir_RX() {RS485_PORT &= ~(1<<GL_BUS_DIR);} #define Global_Bus_RS485_Dir_TX() {RS485_PORT |= (1<<GL_BUS_DIR);}
#define LL_BUS_DIR 3 #define Local_Bus_RS485_Dir_RX() {RS485_PORT &= ~(1<<LL_BUS_DIR);} #define Local_Bus_RS485_Dir_TX() {RS485_PORT |= (1<<LL_BUS_DIR);}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::: // Запрет приема //:::::::::::::::::::::::::::::::::::::::::::::::::::::: void USART0_DisableRecive(void) { UCSR0B &= ~(1 << RXEN0); Global_Bus_RS485_Dir_TX(); }
//:::::::::::::::::::::::::::::::::::::::::::::::::::::: // Разрешение приема //:::::::::::::::::::::::::::::::::::::::::::::::::::::: void USART0_EnableRecive(void) { Global_Bus_RS485_Dir_RX(); UCSR0B |= (1 << RXEN0); }
#pragma vector=USART0_TXC_vect __interrupt void USART0_TX_interrupt( void ) { if((usart0.flags & (1<<USART0_FLAG_TX_COMPLETE)) != 0) { usart0.flags &= ~(1<<USART0_FLAG_TX_COMPLETE); usart0.flags |= (1<<USART0_FLAG_SHIFT_REG_EMPTY); USART0_EnableRecive(); } } Перед передачей отключаю приемник и переключаю драйвер. По прерыванию переключаю драйвер и включаю приемник.
Прикрепленные файлы
drv.rar ( 1.88 килобайт )
Кол-во скачиваний: 66
|
|
|
|
|
Aug 20 2007, 10:46
|
Местный
  
Группа: Свой
Сообщений: 263
Регистрация: 22-03-05
Из: г. Харьков, Украина
Пользователь №: 3 598

|
Цитата(Т.Достоевский @ Aug 20 2007, 02:46)  Сколько реально времени (включая служебные биты 1-четности и 1-стоп 9-ый) будет передавать 2 байта усарт? Зависит от скорости передачи Ftx (Бод -> бит в секуду ) Ttx = 1/Ftx - передача одного бита данных в секундах.
|
|
|
|
|
Aug 20 2007, 10:47
|

Местный
  
Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606

|
Цитата(vesago @ Aug 20 2007, 11:06)  Код #pragma vector=USART0_TXC_vect __interrupt void USART0_TX_interrupt( void ) { if((usart0.flags & (1<<USART0_FLAG_TX_COMPLETE)) != 0) ???????????????????? ВОТ ЭТА ?????????? { usart0.flags &= ~(1<<USART0_FLAG_TX_COMPLETE); usart0.flags |= (1<<USART0_FLAG_SHIFT_REG_EMPTY); USART0_EnableRecive(); } } Перед передачей отключаю приемник и переключаю драйвер. По прерыванию переключаю драйвер и включаю приемник. Не совсем понял Ваш код в прерывании. Зачем нужна проверка флага?
Сообщение отредактировал Т.Достоевский - Aug 20 2007, 11:03
|
|
|
|
|
Aug 20 2007, 10:49
|
Местный
  
Группа: Свой
Сообщений: 263
Регистрация: 22-03-05
Из: г. Харьков, Украина
Пользователь №: 3 598

|
Цитата(Т.Достоевский @ Aug 20 2007, 13:44)  Тоесть флаг TXC выставляется только по окончании передачи ВСЕГО? Но у меня почемуто не работает! Вечером заменю камень и перепроверю. ВСЕГО байта, который был отправлен в буфер, т.е. после передачи стопового бита!!!
|
|
|
|
|
Aug 20 2007, 11:02
|

Местный
  
Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606

|
Цитата(IEC @ Aug 20 2007, 14:49)  ВСЕГО байта, который был отправлен в буфер, т.е. после передачи стопового бита!!! Тоесть если Я отослал в буфер 2 байта то и прерываний будет 2? Цитата(IEC @ Aug 20 2007, 14:46)  Зависит от скорости передачи Ftx (Бод -> бит в секуду ) Ttx = 1/Ftx - передача одного бита данных в секундах. Спасибо! Незнал длинну битов "старт" и "стоп". По привычке считал её отличающейся от длинны обычных бит.
|
|
|
|
|
Aug 20 2007, 14:56
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Т.Достоевский @ Aug 20 2007, 14:02)  Тоесть если Я отослал в буфер 2 байта то и прерываний будет 2? Спасибо! Незнал длинну битов "старт" и "стоп". По привычке считал её отличающейся от длинны обычных бит. Длина старт бита "по привычке" всегда была один бит. А длина стопа может быть 1-1.5-2 бита и задаётся вами же при инициализации УСАРТА. Смотрите внимательнее описалово. Если вы отослали 2 байта, то вы получите 2 прерывания: сначала UDRE потом TXC. Если передадите по первому UDRE третий байт, то получите 2 UDRE и один TXC. Цитата(haker_fox @ Aug 20 2007, 14:02)  Честно говоря никогда не испольвал этот флаг. Использую вместо него UDRE, он выставляется если регистр данных передатчика пуст и готов к отправке следующего байта. Рекомендую воспользоваться этим прерыванием. .... Прошу прощения, не учел особенностей RS485 01.gif Если хотите получить максимальную скорость обмена, то правильно будет использовать оба флага и при работе с RS232. По-моему это очевидно.
|
|
|
|
|
Aug 20 2007, 15:46
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата Работает только если после передачи первого байта проверять флаг вручную и передавать второй байт после его установки. Соответственно так же переключаю на приём. Не надо ничего проверять. Сделайте очередь. В прерывании TXC посылайте следующий байт - если нечего слать - то переключайте линию на прием. PS: вы на чем пишете программу? asm/c? Цитата Честно говоря никогда не испольвал этот флаг. Использую вместо него UDRE, он выставляется если регистр данных передатчика пуст честно говоря никогда не использовал UDRE. Т.к. по TXC все что связано с 485-м реализуется гораздо удобнее, как бонус даже межсимвольный интервал непроизвольно получается.
|
|
|
|
|
Aug 20 2007, 20:11
|

Местный
  
Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606

|
Цитата(defunct @ Aug 20 2007, 19:46)  Не надо ничего проверять. Сделайте очередь. В прерывании TXC посылайте следующий байт - если нечего слать - то переключайте линию на прием.
PS: вы на чем пишете программу? asm/c? честно говоря никогда не использовал UDRE. Т.к. по TXC все что связано с 485-м реализуется гораздо удобнее, как бонус даже межсимвольный интервал непроизвольно получается. Пишу на асме. Вот и Я этот бонус захотел. Всётаки наверное камень глючит. Походу 2 прерывания даёт. Посылаю сразу 2 байта. И получаю 2 прерывания по TXC! К сожалению новый будет только в четверг!
Сообщение отредактировал Т.Достоевский - Aug 20 2007, 20:13
|
|
|
|
|
Aug 21 2007, 00:41
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Т.Достоевский @ Aug 20 2007, 23:11)  Пишу на асме. Вот и Я этот бонус захотел. Всётаки наверное камень глючит. Походу 2 прерывания даёт. Посылаю сразу 2 байта. И получаю 2 прерывания по TXC! К сожалению новый будет только в четверг! Я где-то приводил пример работы с UART на asm'e.. Искать долго, поэтому просто прикляю его еще раз. смотрите в атаче. Пример написан под AT90S2313, чтобы переделать под Tiny2313 надо будет поменять таблицу векторов и возможно пару штрихов с настройкой UART'a. Так же надо будет выставить константы Fosc и BaudRate согласно вашим потребностям. константа .equ PD7 = 7 ; // объявим константу которая не прописана в .inc файле используется как флажек (прием/передачи) поменяйте ее на Pin которым у вас меняется направление (прием/передача) 485-го. Цитата у меня фраза "камень глючит" или "винда не так села" вызывает .... Согласен. Камень тут не причем. 2 TXC на 2 переданных байта - абсолютно нормальное поведение чипа.
|
|
|
|
|
Aug 21 2007, 02:06
|

Местный
  
Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606

|
Цитата(defunct @ Aug 21 2007, 04:41)  2 TXC на 2 переданных байта - абсолютно нормальное поведение чипа. Вот именно такой прямой ответ я и хотел получить! Огромное спасибо! Ибо "Атмеловский английский" неразумею. Им наверное построчно плотют. Ка-кто смутно и коротко у них там описана работа буферизации USART. Было бы логично если бы флаг TXC устанавливался по ОПУСТОШЕНИЮ буфера. Но похоже он устанавливается по окончанию передачи одного байта из двух что в буфере. Соответственно возникают 2 прерывания вместо ожидаемого 1го. То-есть не получится сделать совсем красиво. Досадно. Спасибо за исходники. Цитата(SasaVitebsk @ Aug 21 2007, 02:56)  Простите пожалуйста, но лично у меня фраза "камень глючит" или "винда не так села" вызывает пену у рта и лёгкое подколбашивание. Кто-то на форуме собирал камни которые "глючат" как редкую реликвию. И, наверное перекупили бы у вас такой камень. К сожалению, скорее всего "глючит" другой прибор не техногенного происхождения. Во всяком случае с очень большой долей вероятности. Впоне возможно что глючу Я. А камень продам по сходящей тк. он уже в 2 раза питался 12 вольтами. Что вы понимаете под словом "отладчик"?
|
|
|
|
|
Aug 21 2007, 04:53
|

Профессионал
    
Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371

|
Почему получается 2 прерывания по TXC при передачи 2-х байт не понял. может я не правильно помню и делаю иначе, но с таким не встречался. На память TXC возникает при пустом буфере и выдачи стопового бита. На я передачу делал так. 2 байта в буфер; включить UDRE по UDRE подкачивать данные если новых двнных нет, то выключить UDRE и включить TXC если TXC, то все переданно, переключиться на прием. и таких вещей Цитата как бонус даже межсимвольный интервал непроизвольно получается. у меня не было
--------------------
OrCAD, Altium,IAR, AVR....
|
|
|
|
|
Aug 21 2007, 10:59
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(arttab @ Aug 21 2007, 07:53)  Почему получается 2 прерывания по TXC при передачи 2-х байт не понял. может я не правильно помню и делаю иначе, но с таким не встречался. На память TXC возникает при пустом буфере и выдачи стопового бита. Безусловно. Прямо так и написано: Цитата The Transmit Complete (TXC) flag bit is set one when the entire frame in the Transmit Shift Register has been shifted out and there are no new data currently present in the transmit buffer Цитата На я передачу делал так. 2 байта в буфер; включить UDRE по UDRE подкачивать данные если новых двнных нет, то выключить UDRE и включить TXC если TXC, то все переданно, переключиться на прием.
и таких вещей у меня не было Ну в принципе даже разрешение TXC можно не дергать, если вы можете дать гарантию, что время реакции на UDRE не превысит времени передачи символа. Тогда TXC придет ТОЛЬКО ОДИН в конце пакета. Как раз, чтобы выключить передатчик на ADM485  Вообщем-то все культурно и правильно в камне. Работать в принципе по UDRE и надо, чтобы не было дырок между символами (они только уменьшают общую скорость передачи).
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 21 2007, 11:47
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Rst7 @ Aug 21 2007, 13:59)  Вообщем-то все культурно и правильно в камне. Работать в принципе по UDRE и надо, чтобы не было дырок между символами (они только уменьшают общую скорость передачи). Они (всмысле межсимвольные интервалы) добавляют стабильности передачи. В Modbus - межсимвольный интервал is a MUST. А скорость, кому она нужна в 485? Цитата Почему получается 2 прерывания по TXC при передачи 2-х байт не понял. Потому что отправляется два символа. После отправки каждого генерится TXC, если игнорировать UDRE.
|
|
|
|
|
Aug 21 2007, 11:59
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(defunct @ Aug 21 2007, 14:47)  Они (всмысле межсимвольные интервалы) добавляют стабильности передачи. Обоснуйте? Цитата В Modbus - межсимвольный интервал is a MUST. Межпакетный да, а вот межсимвольный??? Можно цитату? Цитата А скорость, кому она нужна в 485? Ну не скажите... Разные случаи есть..
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 21 2007, 13:42
|
Местный
  
Группа: Свой
Сообщений: 263
Регистрация: 22-03-05
Из: г. Харьков, Украина
Пользователь №: 3 598

|
Цитата(Rst7 @ Aug 21 2007, 13:59)  Работать в принципе по UDRE и надо, чтобы не было дырок между символами (они только уменьшают общую скорость передачи). Оно то может и так, но привычка с 51 осталась. Там аналога UDRE нет. Да и немного неудобно. UDRE устанавливается всегда, когда буфер на передачу пуст (срабатывание по состоянию). А если я не хочу передавать, надо прерывание запрещать. Прерывание ТХС устанавливается по событию, сбросил после передачи последнего байта и свободен до следующей передачи.
|
|
|
|
|
Aug 21 2007, 13:59
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(Т.Достоевский @ Aug 21 2007, 13:44)  А разве там есть окно COM порта? У меня 4,12 с обработкой прерываний там туго.  Чойто туго??! Там можешь руками поднять бит прерывания - и вот оно, появилось. Или маску. Или ещё что, всё работает. Наоборот, оч. хорошо там с прерываниями вручную. Приём только так и отлаживал - включаешь RXC - сразу прерываание, побежал обрабатывать байт... По поводу TXC/UDRE. Пользую их оба, для 485, ага. Чтобы отправить строку байтов, переключаю интерфейс на выход и записываю байт в UDR. Всё! дальше прерывания сами. Тут же байт из UDR проваливается в регистр сдвига и возникает прерывание UDRI. Обработчик смотрит: все байты передал? нет: следующий в UDR; да: ничего. Когда последний байт передан, возникает TXCI. Его обработчик переключает RS485 на приём. Всё.
|
|
|
|
|
Aug 21 2007, 15:48
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Rst7 @ Aug 21 2007, 14:59)  Обоснуйте? Ну например - передатчик работает 8-1-N, а приемник включили 8-2-N. С отправкой "по TXC" с большой долей вероятности ошибок приема не будет. Цитата Межпакетный да, а вот межсимвольный??? Можно цитату? Таки действительно органичение "снизу" только на межпакетный - "Character gap interval". На межсимвольный "silent interval" ограничение "сверху": Цитата The entire message must be transmitted as a continuous stream. If a silent interval of more than 1.5 character times occurs before completion of the frame (not a continuous stream), the receiving device flushes the incomplete message and assumes the next byte will be the address field of a new message. источник: http://www.sena.com/download/tutorial/tech_Modbus_v1r0c0.pdf (150k) cм. секцию 5.2 Цитата Ну не скажите... Разные случаи есть.. Может быть, но мне что-то такие случаи в сетях 485 не подворачивались.
|
|
|
|
|
Aug 22 2007, 05:20
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(defunct @ Aug 21 2007, 18:48)  Ну например - передатчик работает 8-1-N, а приемник включили 8-2-N. С отправкой "по TXC" с большой долей вероятности ошибок приема не будет. Так включите и в передатчике 9 бит с установленным девятым битом... А ручные задержки для добавления бита - это моветон... А задержки, которые еще и неизвестно какой длительности (ну сколько времени там будет от TXC до записи в UDR) - как говорится, это ваще  Цитата Таки действительно органичение "снизу" только на межпакетный - "Character gap interval". На межсимвольный "silent interval" ограничение "сверху": источник: http://www.sena.com/download/tutorial/tech_Modbus_v1r0c0.pdf (150k) cм. секцию 5.2 Посему оптимально будет посылка именно без интервалов. Цитата Может быть, но мне что-то такие случаи в сетях 485 не подворачивались. Ну надо минимизировать время опроса в сети при ограничении битовой скорости. Вот и весь случай.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 22 2007, 06:13
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(WHALE @ Aug 21 2007, 21:45)  Дык у аффтара проблемы с передачей,значит руками флаги дергать ваще не надо.байт в UDR -и смотри чего-там с прерываниями.И скачайте версию 4.13,там атымельцы здорово над переферией поработали. Согласен. Я удивился, как он этих флагов не видел. Или мышой не ткнул? А что нового в периферии в 4.13? У меня только нумерацию битов приходится всё время включать, больше новостей не заметил. Проц М16.
|
|
|
|
|
Aug 22 2007, 06:40
|

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

|
Цитата(Rst7 @ Aug 21 2007, 12:59)  Ну в принципе даже разрешение TXC можно не дергать, если вы можете дать гарантию, что время реакции на UDRE не превысит времени передачи символа. Ещё можно тупо в прерывании UDRE - если производится запись очередного байта в UDR, то не глядя заодно сбрасывать флаг TXC. В суме это даёт меньше кода, чем разрешение/запрещение TXCIE и защищает от задержки отработки UDRE. Так как если были запрещены прерывания и UDRE не отработало своевременно, успел установиться флаг TXC, то при разрешении прерываний (выходе из другого прерывания) первым будет передано управление на UDRE_vect.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Aug 22 2007, 12:55
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 22 2007, 13:09)  Одно место меня озадачило, в теле подпрограммы PutChar вы снова вызываете PutChar. Это что, такая рекурсия заложена, или как? Спасибо что проявили интерес ;> Да - там рекурсия. посылаем строку "hello\n" putchar автоматически добавит возврат каретки и терминал примет "hello\r\n". Цитата Вроде не должно работать. Попробуйте код. ;> Какой резон мне выкладывать что-то нерабочее?
|
|
|
|
|
Aug 23 2007, 09:19
|

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

|
Цитата(defunct @ Aug 22 2007, 11:55)  Да - там рекурсия Посмотрел попристальнее - нет там никакой рекурсии. И вообще, проще было бы вызывать не rcall PutChar, a rcall __skip_add_cr (ну и названьице(:-)). И выполнение было бы быстрее, ведь рутина у вас и в прерывании вызывается... Цитата(defunct @ Aug 22 2007, 11:55)  Попробуйте код А чего его пробовать, и так видно, что тяжеловесно и неоптимально. Например, фрагмент с кольцевым буфером можно написать в два раза короче. А что там за пляски с бубнами в PutChar: in AH,SREG cli + out SREG,AH? Не проще ли обойтись связкой cli/sei. Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 12:49
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 23 2007, 12:19)  Посмотрел попристальнее - нет там никакой рекурсии. Смотрите пристальнее сразу. Ок? Есть там рекурсия, коль скоро функция вызывает сама себя. Цитата проще было бы вызывать не rcall PutChar, a rcall __skip_add_cr (ну и названьице(:-)). Не сомневаюсь что вы именно так и поступаете, у меня же все метки начинающиеся с "__" внутренние и я стараюсь их не вызывать, чтобы было меньше путаницы. Цитата А что там за пляски с бубнами в PutChar: in AH,SREG cli + out SREG,AH? Не проще ли обойтись связкой cli/sei. Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print? Не проще. Потому что вызывается эта функция еще и в прерывании. И вообще прежде чем хаить хамоватым тоном - разберитесь с кодом. Цитата Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print? опечатка.
|
|
|
|
|
Aug 23 2007, 16:14
|

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

|
Цитата(defunct @ Aug 23 2007, 11:49)  Есть там рекурсия, коль скоро функция вызывает сама себя. Ну-ну, tell it your sailors(:-). Рекурсии там нет. Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности. Вот пример классической рекурсии. Код Задача заключается в том, чтобы найти по заданному n число последовательности Фибоначчи Fn. #include <stdio.h> #include <time.h> long F(unsigned int n) { return n <= 1 ? n : F(n-1) + F(n-2); } int main() { time_t begin, end; long res; for(int n = 0; n < 40; n++) { time(&begin); res = F(n); time(&end); printf("%-3i\t%-9li\t%-20.3f\n",n,res,difftime(end,begin)); } return 0; } Кстати, цикл является частным видом рекурсии. У вас ни того, ни другого. Цитата(defunct @ Aug 23 2007, 11:49)  Не сомневаюсь что вы именно так и поступаете, у меня же все метки начинающиеся с "__" внутренние и я стараюсь их не вызывать, чтобы было меньше путаницы. Дорогой мой, зачем метки тогда вообще писать. Я пишу программы так, чтобы они были эффективные и красивые, а не какие-то там крокозябры (это не вам). Цитата(defunct @ Aug 23 2007, 11:49)  Не проще. Потому что вызывается эта функция еще и в прерывании. Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает. Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом. Цитата(defunct @ Aug 23 2007, 11:49)  И вообще прежде чем хаить хамоватым тоном - разберитесь с кодом Прошу прощения, если кого-то обидел, но я никому не хамил и никого не хаял. Была выложена программа, идёт её обсуждение, ничего личного.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 17:54
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 23 2007, 19:14)  Ну-ну, tell it your sailors(:-). Рекурсии там нет. Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности. Вот пример классической рекурсии. Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области. рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи. В программировании рекурсия — вызов функции или процедуры из неё же самой источник: http://ru.wikipedia.org/wiki/РекурсияЦитата Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает.  Цитата Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом. Теоретически возможно. Атомарность Print я не организовывал. Но конструкция реализованная в PutChar не препятствует организации атомарности Print. тем же самым in Rr, SREG - cli - out SREG, Rr Цитата Дорогой мой, зачем метки тогда вообще писать. Во-первых выбирайте выражения. Своему бойфренду можете говорить "дорогой мой". Во-вторых, я не виноват что русский язык порождает неоднозначность ("не вызывать" - имелось в виду "call" не делать. ) в третьих - это такой стиль - для обозначения внутренних меток (локальных для функций) на которые осуществяется условный переход я применю "тэг" - "__".
|
|
|
|
|
Aug 23 2007, 18:42
|

Знающий
   
Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768

|
Цитата Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности А откуда такое определение рекурмии,ссылку можно? Цитата В программировании рекурсия — вызов функции или процедуры из неё же самой Вот с этим не поспоришь. И чего-вы к обозначению внутренних меток прицепились?По моему,нормальная идея визуально разделять локальные и глобальные метки. З.Ы. вы кодер,не знающий ошибок?
--------------------
"Hello, word!" - 17 errors 56 warnings
|
|
|
|
|
Aug 23 2007, 21:29
|

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

|
Цитата(defunct @ Aug 23 2007, 17:54)  Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области. рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи. Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию F на более заметную RECURRENCE). Код long RECURRENCE(unsigned int n) { return n <= 1 ? n : RECURRENCE(n-1) + RECURRENCE(n-2); } Напишите ваш код PutChar на си в таком же виде, тогда и будем говорить, что верно, а что неверно. Интересно, что у вас будет параметром рекурсии? Цитата(defunct @ Aug 23 2007, 17:54)  Теоретически возможно. Атомарность Print я не организовывал. Но конструкция, реализованная в PutChar не препятствует организации атомарности Print. тем же самым in Rr, SREG - cli - out SREG, Rr Так я и сказал. что все эти примочки внутри PutChar не нужны, не решают они задачу до конца, а снаружи атомарность передачи строки вы не обеспечили. И не теоретически, а сугубо практически, поверьте. Цитата(defunct @ Aug 23 2007, 17:54)  Во-первых, выбирайте выражения. Своему бойфренду можете говорить "дорогой мой" Да что ж такое! Такое впечатление, что или у всех мозги такие извращенные, или все свихнулись на этой секссвободе, что ни скажешь, всё переводят в плоскость гениталий. Вы уж, уважаемый, тоже слова выбирайте. Цитата(SasaVitebsk @ Aug 23 2007, 18:16)  =GM=, при всём уважении к Вашим знаниям давайте будем добрее друг к другу. Так вы отобъёте всякое желание выложить свою прогу, чтобы кому-то помочь.  Знаний как раз маловато, спасибо форуму, много даёт в плане самообразования. Да я...белый и пушистый, defunct'а почти люблю (как брата, а то опять поймет не в той плоскости(:-)). Что касается проги, не собирался я её критиковать, с первого взгляда она мне понравилась, посмотрел по диагонали - в подпрограмме вывода символа вроде используется рекурсия, вот думаю, люди рекурсию применяют, а я от неё как чёрт от ладана, ну я и спросил спроста, а потом уж стал смотреть, а он мне отвечает, да, там рекурсия, да какая рекурсия, курам на смехЦитата(SasaVitebsk @ Aug 23 2007, 18:16)  Любая мало-мальски приличная прога содержит ошибки. Иногда их вылавливаешь годами. Плюс различные предпочтения у каждого программиста. Это как аккорды на гитаре. Один пользуется чаще такими, а другой другими. Но если оба музыканта, то музыка всё равно звучит.  Согласен. Ошибок в любой программе полно, у самого так. Смотришь на программу годичной давности, и думаешь, неужели это я написал такое гуано? Ну посмотрел я его программу, ну высказал замечания, будь благодарен, что кто-то потратил своё время, разобрался, принял участие, ответил, что плохого? Почему сразу надо воспринимать как наезд, которого и в помине не было. Дефункту не надо было говорить, чтоб код испытал(:-). Да если б все мои программы так критиковали, это было бы здорово, и программы были бы в стократ лучше...
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 21:57
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 24 2007, 00:29)  Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию F на более заметную RECURRENCE). Взглянул непредвзято.. будем считать, что вы взяли определение рекурсии не из той предметной области. Цитата Напишите ваш код PutChar на си в таком же виде, тогда и будем говорить, что верно, а что неверно. Интересно, что у вас будет параметром рекурсии? отправляемый char, а что еще может быть параметром? функциональный аналог ассемблерной функции: Код void put(U8 ch) { if (ch == 0x0A) // add CR char ahead of LF put(0x0D); { U8 IStatus = ILock() pRing->storage[ pRing->tail ] = ch; pRing->tail = RingNextTail( pRing ); IUnlock( IStatus ); } } Цитата Так я и сказал. что все эти примочки внутри PutChar не нужны, не решают они задачу до конца, Это вам так кажется. Примочки внутри putchar решают свои задачи: - атомарность выгрузки символа в очередь - добавление символа CR Цитата а снаружи атомарность передачи строки вы не обеспечили. И не теоретически, а сугубо практически, поверьте. Господи, да что вы цепляетесь к фантикам от конфет. Чес слово. Уж не пойму или у меня там полный бред в коде или у вас проблемы с прочтением алгоритма из асм программы. поменять Print так: Код /* * Print() * Выводит строки размещенные во флеш памяти через PutChar * ---> Z - указатель на строку оканчиваемую \0 во флеш * <--- ничего не возвращает */ Print: in AH, SREG push AH cli __do_output: lpm; // читаем данные флеш adiw Z, 1 // увеличим указатель на 1 (z++) mov AL, R0 rcall PutChar tst AL brne __do_output pop AH out SREG, AH ret и будет обеспечиваться атомарность. push/pop конечно же можно сократить если использовать какой-либо другой регистр для хранения SREG вместо AH, но поставил специально для наглядности. Цитата да какая рекурсия, курам на смех Маленькая простенькая - но рекурсия, т.к. функция вызывает сама себя. Прочитайте определение рекурсии на wiki. Цитата Ну посмотрел я его программу, ну высказал замечания, будь благодарен, что кто-то потратил своё время, разобрался, принял участие, ответил, что плохого? Я выразил вам благодарность и попытался нормально ответить на ваши вопросы вначале. PS: я и сейчас пытаюсь отвечать на ваши вопросы по-сущесту, с приведением ссылок и примеров. Может вы просто не замечаете?
|
|
|
|
|
Aug 23 2007, 22:22
|

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

|
Цитата(defunct @ Aug 23 2007, 21:57)  Уж не пойму или у меня там полный бред в коде или у вас проблемы с прочтением алгоритма из асм программы. поменять Print так: Код /* * Print() * Выводит строки размещенный во флеш памяти через UART * ---> Z - указатель на строку оканчиваемую \0 во флеш * <--- ничего не возвращает */ Print: in AH, SREG push AH cli __do_output: lpm; // читаем данные флеш adiw Z, 1 // увеличим указатель на 1 (z++) mov AL, R0 rcall PutChar tst AL brne __do_output pop AH out SREG, AH ret и будет обеспечиваться атомарность Ну, это другое дело. Но тогда сохранение/восстановление статус-регистра в PutChar не нужно, о чём я и толкую последние две страницы. Кстати, неплохо бы добавить проверку на переполнение буфера в подпрограмме обработки прерываний по приему. UART_RX_ISR так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 22:41
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 24 2007, 01:22)  Ну, это другое дело. Но тогда сохранение/восстановление статус-регистра в PutChar не нужно, о чём я и толкую последние две страницы. Нужно! Т.к. PutChar автономная функция, и кроме Print может быть использована где угодно. "Лучше перебдеть чем "недобдеть" ;> Цитата Кстати, неплохо бы добавить проверку на переполнение буфера в подпрограмме обработки прерываний по приему. Это так и было задумано.. Практика показывает что для консольных приложений (а пример относился как раз консоли) много лучше допускать опустошение Tx (при переполнении) чем притормаживать CPU ожиданием освобождения места. Цитата UART_RX_ISR так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг. RX_ISR в идеале должен работать со входной очередью. Вывод "Эхо" по скорости заполнения не быстрее TX, переполнений по вине RX потока быть не должно. Ну а в случае когда полный overload, то деваться некуда или сбросить TX очередь или ждать окончания TX. Но мы не можем торчать в прерывании и ждать когда освободится место в очереди..
|
|
|
|
|
Aug 28 2007, 05:16
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата(Т.Достоевский @ Aug 28 2007, 00:29)  С новым камнем всё заработало. Проблема была не с USART а с подпаленными ногами. Да, действительно флаг TXC появляется только по опустошению буфера. А не на каждый байт. В авр студио флаг UDRE появляется если оба байта буфера пусты. В прерывании по UDRE передаю байт и прерывание повторяется ещё раз. Тоесть по флагу UDRE можно передавать сразу 2 байта! Передачу сразу 2х байт по UDRE в железе не проверял(нет времени, чуть позже проверю), всё остальное работает прекрасно! 2 раза сразу только ПЕРВЫЙ раз. UDRE уже выставлен, передачи еще нет. Первый байт сразу влетает в сдвиговый регистр и буфер опустошается, выставляется сразу опять UDRE. А вот следующий будет только тогда, когда вытолкнется самый первый.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 28 2007, 09:24
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(Rst7 @ Aug 28 2007, 09:16)  2 раза сразу только ПЕРВЫЙ раз. UDRE уже выставлен, передачи еще нет. Первый байт сразу влетает в сдвиговый регистр и буфер опустошается, выставляется сразу опять UDRE. А вот следующий будет только тогда, когда вытолкнется самый первый. Именно так! А не "передавать сразу 2 байта"... И АВРстудио честно всё показывает. Не "флаг UDRE появляется если оба байта буфера пусты", а если пуст только UDR. Тщательнее надо, тов. Достоевский!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|