Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

Закрытая тема
Опции темы
Непрочитано 04.09.2013, 20:00   #51
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от Someone Посмотреть сообщение
И чем не устраивает равенство нулю счётчика байт?
Код:
ISR(USART1_TX_vect)     // прерывание завершения передачи символа
{
 ByteCountUART--;     // уменьшаем счётчик переданных байт
 if(!ByteCountUART)     // если передали все байты
 {
  TransiverOff();     // отключаем передатчик RS485
  return;       // завершаем прерывание
 }
 UDR1 = *PosBuferUART1++;   // если послали не всё, посылаем очередной байт
}
Очевидно же, что если ByteCountUART равен 0, передача была полностью завершена, и можно спать или заниматься чем угодно.
А вот и нет.

ByteCounter = 1
То есть, в буфере есть 1 байт, требующий отправки. Зашли в прерывание. ByteCounter стал 0. И пошла отправка байта. На скорости 115200 она будет идти 87 мкс. Мы вышли из прерывания и вошли в функцию Flush(). Там мы узнали, что ByteCounter равен нулю, и соответственно, вышли из неё. И всё. Засыпаем. А в это время ещё идёт передача последнего байта.

Сообщение от av0000 Посмотреть сообщение
Someone, в итоге примерно так и вышло.
Оговорка: декремент счётчика без проверки может вызвать переполнение, потому, уменьшаем только если не ноль
Но после уменьшения делать ещё одну проверку (как у вас) не надо.
Реклама:
Godzilla82 вне форума  
Непрочитано 05.09.2013, 00:03   #52
Someone
Гражданин KAZUS.RU
 
Регистрация: 16.06.2005
Сообщений: 944
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
Someone на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от av0000 Посмотреть сообщение
не требуется дублировать код отправки первого байта в uart_putch().
Гм... не понял, о чём это? Зачем что-то дублировать? Первый байт пакета из буфера посылается обычным образом:
Код:
 PosBuferUART1 = &buferUART1[0];   // задаём адрес начала кадра
 ByteCountUART = 5;    // длина кадра
 TransiverOn();        // включаем передатчик RS485
 UDR1 = *PosBuferUART1++;     // посылаем 1й байт ответа
И всё, дальше весь пакет передаётся автоматически, и не требует никакого вмешательства в прцесс передачи. Как только закончится передача 1го байта, сработает прерывание, которое уменьшит счётчик и если он не 0, пхнёт в удр очередной байт. ByteCountUART при входе в прерывание по определению не может быть равным 0, т.к. длину пакета задаём (если только не забыть задать длину пакета перед записью в удр первого байта пакета, что сразу будет заметно), потому-то проверка перед декрементом счётчика не нужна. Зато равенство этого счётчика 0 однозначно укажет что передача пакета завершилась.
Someone вне форума  
Непрочитано 05.09.2013, 00:32   #53
Someone
Гражданин KAZUS.RU
 
Регистрация: 16.06.2005
Сообщений: 944
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
Someone на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от Godzilla82 Посмотреть сообщение
А вот и нет.
А вот и да.

Сообщение от Godzilla82 Посмотреть сообщение
ByteCounter = 1
Т.е. надо передать 1 байт, ну скажем 0х55 например

ByteCountUART = 1; // длина кадра
UDR1 = 0х55;

Байт попадёт в удр, перепишется в сдвиговый регистр, установится флаг удре (что правильно, т.к. байт ушел из буфера, и буфер пуст, но нам на этот флаг плевать, нет у нас такого прерывания, не используем мы его), начнётся передача байта в линию связи, и когда он передастся, установится флаг тхс, и мы попадаем в прерывание, где счётчик, равный пока 1, декрементируется (мы ведь и в самом деле закончили передачу 1го байта), становится равным 0, что означает что ничего более передавать не надо, и прерывание завершается, не записав в удр ничего более. И соответственно более не возникнет, пока пользователь не запишет в удр новый байт, и пока не завершится передача этого байта в линию.


Сообщение от Godzilla82 Посмотреть сообщение
Мы вышли из прерывания и вошли в функцию Flush().
Какую флуш? Зачем она нам? Если есть желание ждать конца передачи, то

while(ByteCountUART);
sleep();

или если охота 87 мкс заниматься чем-либо второстепенным, через

if(!ByteCountUART) sleep();

и всё. И стек лишний раз не дёргается (вызов, сохранение регистров, восстановление регистров, возврат), и код меньше (call, ret).

Сообщение от Godzilla82 Посмотреть сообщение
А в это время ещё идёт передача последнего байта.
Это с чего бы? Прерывание TXC возникает после завершения передачи байта. В том-то вся прелесть и заключается, что войдя в этот обработчик прерывания мы знаем, что символ уже передался.

Последний раз редактировалось Someone; 05.09.2013 в 00:46.
Someone вне форума  
Непрочитано 05.09.2013, 01:50   #54
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Ну да, в голове, что ByteCounter одновременно является индексом элемента массива, из которого идёт передача... А так да, всё верно.
Godzilla82 вне форума  
Непрочитано 05.09.2013, 09:40   #55
av0000
Частый гость
 
Регистрация: 27.08.2008
Адрес: Москва
Сообщений: 29
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
av0000 на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от Someone Посмотреть сообщение
И всё, дальше весь пакет передаётся автоматически,
Про первый байт и шла речь. Таки да, там не весь код получился, а только лишняя проверка (приведённый пример её не учитывает) - в UDR пишем только _первый_ байт, т.е. если буфер пуст. Но это не сравнимая "цена" с кучей push/pop в дополнительном обработчике прерываний

PHP код:
putch(c) {
///
    
if (_tx.cnt) {
        
_tx.buf[_tx.in] = data;
        
_tx.in = (_tx.in 1) & UART_TX_BUF_MASK;
    } else {
        
UDR data;
    }
    
_tx.cnt++;
///

PHP код:
ISR(USART0_TXC_vect) {
    
_tx.cnt--;
    if (
_tx.cnt) {
        
UDR _tx.buf[_tx.out];
        
_tx.out = (_tx.out 1) & UART_TX_BUF_MASK;
    } else {
#ifdef RS485PIN
    
RS485PORT &= ~(1‹‹RS485PIN);
#endif
    
;
    }

ну и flush в таком варианте, действительно, вырождается в `while(_tx.cnt) ;`
(полный код всего этого безобразия )
av0000 вне форума  
Непрочитано 05.09.2013, 20:27   #56
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Подолью ещё маслица в огонь.

Буфер устроен коряво. Проще было бы кольцевой буфер. И к тому же произвольного размера.
Godzilla82 вне форума  
Непрочитано 05.09.2013, 20:33   #57
_Артём_
Гражданин KAZUS.RU
 
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
_Артём_ на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от Godzilla82 Посмотреть сообщение
Буфер устроен коряво. Проще было бы кольцевой буфер.
Он и так кольцевой.

Сообщение от Godzilla82 Посмотреть сообщение
И к тому же произвольного размера.
Произвольного - это как?
_Артём_ вне форума  
Непрочитано 05.09.2013, 21:06   #58
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от _Артём_ Посмотреть сообщение
Он и так кольцевой.
Хотя да, он кольцевой. Всё думаю о том, что в прикреплённом файле из первых постов.
А тут уже всё поменялось.

Сообщение от _Артём_ Посмотреть сообщение
Произвольного - это как?
Не кратного степеням двойки. Хотя это и не принципиально.

Что-то типа этого
PHP код:
 
#define TX_BUFFER_SIZE    50

unsigned char tx[TX_BUFFER_SIZE];

unsigned char tx_read    0;
unsigned char tx_write   0;

ISR(USART0_TXC_vect)
{
tx_read++;
if(
tx_read ›= TX_BUFFER_SIZEtx_read 0;
if(
tx_read != tx_write)    UDR tx[tx_read];
}

void usart_putchar(unsigned char c);
{
cli();
tx[tx_write] = c;
if(
tx_write == tx_read)    UDR c;
tx_write++;
if(
tx_write ›= TX_BUFFER_SIZEtx_write 0;
sei();


Последний раз редактировалось Godzilla82; 05.09.2013 в 21:09.
Godzilla82 вне форума  
Непрочитано 06.09.2013, 09:33   #59
Someone
Гражданин KAZUS.RU
 
Регистрация: 16.06.2005
Сообщений: 944
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
Someone на пути к лучшему
По умолчанию Re: Глюк с UART при засыпании

Сообщение от Godzilla82 Посмотреть сообщение
индексом элемента массива
Вообще массивы штука вредная:
1) Необходимость индексной переменной, с которой требуется работать (инициализация, инкремент/декремент, проверка границ и т.п.)
2) В большинстве случаев (на программах более примерно 20-30% объёма контроллера) компиляторы при обращении к массиву каждый раз пересчитывают адрес (т.е. берут адрес начала, к нему прибавляют смещение, а ведь адрес 16 разрядов). И всегда, если работают с данными помеченными как волатиле. Понятное дело, что это и лишнее время, и относительно немалый объём кода.
3) Программисты почему-то в большинстве случаев помимо индекса используют и длину. В этом случае индекс увеличивается вверх, а счётчик вниз. Влечёт за собой дополнительный код и время для работы с ещё одной переменной.

С указателями код и компактней и быстрее.


Сообщение от av0000 Посмотреть сообщение
полный код всего этого
1) в функциях uart_putch, uart_getch есть запрет прерываний. А вот разрешения их я там не увидел. Зачем оно вообще там? Не, я конечно могу подумать про атомарность, но мало ли...
2) Зачем сохранять и восстанавливать SREG?
3) Работа с указателями есть. Но почему-то для работы с уарт используются массивы...
4) uart_tx_flush(void). Ну если так хочется писать void uart_tx_flush, то зачем в виде функции? Лишний код и время его выполнения. Может быть стоит оформить в виде макроса?
Someone вне форума  
Непрочитано 06.09.2013, 12:47   #60
Godzilla82
Почётный гражданин KAZUS.RU
 
Регистрация: 29.10.2006
Сообщений: 1,443
Сказал спасибо: 99
Сказали Спасибо 315 раз(а) в 231 сообщении(ях)
Godzilla82 на пути к лучшему
Сообщение Re: Глюк с UART при засыпании

Сообщение от Someone Посмотреть сообщение
Вообще массивы штука вредная:
...
С указателями код и компактней и быстрее.
Вредная, но удобная. Не вникал в подробности, но всегда думал, что компиляторы (тем более с оптимизацией) делают вполне адекватнй код.

На CV код такой:

PHP код:
_usart_tx_isr:
    
ST   -Y,R30
    ST   
-Y,R31
    IN   R30
,SREG
    ST   
-Y,R30
tx_read++;
    
INC  R5
; if(tx_read ›= TX_BUFFER_SIZEtx_read 0;
    
LDI  R30,LOW(50)
    
CP   R5,R30
    BRLO _0x3
    CLR  R5
; if(tx_read != tx_write)    UDR tx[tx_read];
_0x3:
    
CP   R4,R5
    BREQ _0x4
    MOV  R30
,R5
    LDI  R31
,0
    SUBI R30
,LOW(-_tx)
    
SBCI R31,HIGH(-_tx)
    
LD   R30,Z
    OUT  0xC
,R30
_0x4
:
    
LD   R30,Y+
    
OUT  SREG,R30
    LD   R31
,Y+
    
LD   R30,Y+
    
RETI 
PHP код:

_usart_putchar
:
    
ST   -Y,R26
;    -› Y+0
    cli
tx[tx_write] = c;
    
MOV  R30,R4
    LDI  R31
,0
    SUBI R30
,LOW(-_tx)
    
SBCI R31,HIGH(-_tx)
    
LD   R26,Y
    STD  Z
+0,R26
; if(tx_write == tx_read)    UDR c;
    
CP   R5,R4
    BRNE _0x5
    LD   R30
,Y
    OUT  0xC
,R30
tx_write++;
_0x5:
    
INC  R4
; if(tx_write ›= TX_BUFFER_SIZEtx_write 0;
    
LDI  R30,LOW(50)
    
CP   R4,R30
    BRLO _0x6
    CLR  R4
#asm("sei");
_0x6:
    
sei
    ADIW R28
,1
    RET 
С указателями стараюсь не работать, как будет выглядеть через указатели?

Последний раз редактировалось Godzilla82; 06.09.2013 в 13:01.
Godzilla82 вне форума  
Закрытая тема

Закладки

Метки
avr, sleep, usart

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Омывание стирального бака СМА при полоскании Слесарь Делимся опытом 33 29.05.2013 00:03
Проблемы с передачей по UART, нужна помощь sansan25 Микроконтроллеры, АЦП, память и т.д 3 28.01.2012 13:19
Водка и как с ней бороться SerjT Отвлекитесь, эмбеддеры! 108 29.09.2009 21:25
Проблема с электропитанием квартиры tourent Источники питания и свет 85 16.09.2009 07:51
[Решено] Сборник перлов любителей кабельщины mikesmith Отвлекитесь, эмбеддеры! 135 14.08.2007 15:49


Часовой пояс GMT +4, время: 01:23.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot