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

Циклический буфер на AVR

Ну Вы прям как Бил Гейтс и Ко :)

 

ИМХО разарботчик обязан сделать так, чтобы его программа не вешалась от добавления пары строк кода где угодно и когда угодна. А взять глубину буфера какую вздумается можно на пне4 и ижесними

Ну и каким местом ваш поток сознания к теме? А уж, тем более, к цытируемому?

Где я написал "взять глубину буфера какую вздумается". Здесь, что-ли "...обязан оценить эту загрузку и взять глубину буфера, чтобы...". Т.е. оценить и ПОСЧИТАТЬ, это "какое вздумается"? Толково!

...обязан сделать так, чтобы его программа не вешалась от добавления пары строк...
Ага, обязан сказать:" по счучьему велению, не вешайся, программа, от добавления пары строк!"

Добавил пару строк - посчитай, добавь глубины, если надо. Потому как за твоих "пару строк" вполне может из линии насыпаться в два раза больше байтиков, чем без них.

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


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

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

 

Спасибо за поправку. Вроде бы теперь правильно.

 

;------------------------------------------------
read_buf:
;------------------------------------------------
; возвращает байт в r16
; используются регисты r16, r17, r26, r27, r28, r29

; в Y адрес структуры, задающей буфер    
    ldi    YL, LOW(buf)
    ldi    YH, HIGH(buf)

    mov    XL, YL
    mov    XL, YL
        
    clr      r17
    ld     r16, Y+1
    add    XL, r16
    adc    XH, r17

; c = buf[rindex]
    ldd    r16, X

    cli

; count--
    ld    r17, Y
    dec    r17
    st    Y, r17
    
; rindex = (rindex + 1) & BUF_SIZE - 1
    ldd    r17, Y+1
    dec    r17
    andi    r17, BUF_SIZE-1
    std    Y+1, r16
    sei
    ret

Изменено пользователем alcosar

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


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

To alcosar

 

1) Здесь: std Y+1,r16 у вас ошибка, надо было r17 написать.

2) Счётчик занятых ячеек вполне может заменить статус буфера: 0-пустой, BUF_SIZE-полный.

3) Недостаток, что очень много регистров используется, аж 6 штук. Уже показывал более простое решение (см. пост #14). Вот адаптированная под ваш вариант программа. В три раза короче и в три раза быстрее. Использует три регистра.

 

;чтение байта из циклического буфера buffer в регистр data

rdbyte: lds   xl,tail        ;указатель 
        ldi   xh,high(buffer);на чтение
        ld    data,x+        ;прочитаем байт
        andi  xl,bufsize-1   ;держим указатель
        sts   tail,xl        ;в рамках 
        ret

3) Кстати, что будет выдавать ваша программа, если буфер пуст? Предыдущие значения, поскольку count пойдёт в минус(:-)? Как сказал =mse=, и он 100% прав, пустой буфер-нередкая штатная ситуация.

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


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

В полезности циклических буферов я нисколько не сомневаюсь :) и сам оччень часто их применяю. НО, очень мало, это сколько? :) допустим применительно к АВР и его USART. Просто не вижу большого смысла тщательно рассказывать, как забивать гвозди...

Для реализации достаточно самого буфера + два указателя.

1. Размер буфера оцениваю исходя из из того что быстрее работает. Например IBM накачивает быстрее чем AVR разгребает. В этом случае размер приёмного буфера для AVR при 485 интерфейсе составляет два размера пакета + 5-6 байт. Для 232 интерфейса приблизительно 1к. Дальнейшее увеличение размера буфера даёт незначительный рост производительности.

2. Размер указателей зависит от размера буфера. Если буфер менее 256 байт, то указатели - байтовые, если больше то 2.

3. Если использую пакетную передачу, то, как я и описывал вводится ещё один указатель (недостоверных данных)

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

Почему нет ни единого примера на Си?

А когда хвост догнал голову, а он важнее (ибо прерывание) получается баальшой булик :lol:

Честно говоря не понял шутки. Если буфер обнулён, то просто прекращается передача. Если заполнен ПОЧТИ полностью, то выполняется приостановка канала любым способом "управления потоком" - либо установкой сигнала CTS (HARD) либо передачей символа XOFF(SOFT). Буфер должен быть расчитан на приём 16 байт с момента выдачи остановки приёма. При работе с 485, очевидно, что вы сами должны следить за заполнением буфера. Но при чём здесь кольцевой буфер??? Если вы не справляетесь с приёмом, то управление потоком должно быть реализовано в любом случае.

Кроме анальгина

Вы просто не работали с большими потоками данных например в четыре стороны. Иначе, простите за эмоции, вы бы бред не писали.

 

Кольцевой буфер это один из очень красивых алгоритмов. И, при правильной реализации, даёт разработчику возможность скрыть все тонкости приёма/передачи внутри драйвера. Поэтому, возможно, мало примеров. Так как придётся вычищать некоторые мелкие моменты.

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


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

2. Размер указателей зависит от размера буфера. Если буфер менее 256 байт, то указатели - байтовые, если больше то 2.

Простите, но непонятно, как Вы меняете размер указателя или что подразумеваете под "размер указателя"

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


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

Простите, но непонятно, как Вы меняете размер указателя или что подразумеваете под "размер указателя"

Естественно на стадии написания программы. Просто prottoss спрашивал размер потребляемой памяти, вот я и написал.

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


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

Естественно на стадии написания программы

Рация на танке(С)

Указатели обычно имеют размерность шины адреса;) или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR.

Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения.

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


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

Указатели обычно имеют размерность шины адреса;) или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR.

Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения.

Именно указатели, хотя памяти в АВРках - кот наплакал 0.5-1.0-2.0 Кбайта, редко больше. Но тем не менее, указатель 16-битный и занимает парные регистры x, y или z. В части приведённых программ старшая часть адреса присутствует как бы за кадром, поскольку она не меняется, установили её один раз в программе и забыли.

 

Обратите внимание на завершенную подпрограмму чтения байта из кольцевого буфера в посте #33. В паре регистров (xh,xl) находится честный 16-битный указатель на чтение, младшая часть которого хранится в ячейке tail.

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


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

Рация на танке(С)

Указатели обычно имеют размерность шины адреса;) или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR.

Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения.

Имелись в виду указатели. Что вас смущает. Хранятся младшие байты указателей. Старшие - фиксированы. Где танк?

Посмотрите топик 6. В условиях экономии памяти вполне применимо.

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


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

To alcosar

 

1) Здесь: std Y+1,r16 у вас ошибка, надо было r17 написать.

2) Счётчик занятых ячеек вполне может заменить статус буфера: 0-пустой, BUF_SIZE-полный.

3) Недостаток, что очень много регистров используется, аж 6 штук. Уже показывал более простое решение (см. пост #14). Вот адаптированная под ваш вариант программа. В три раза короче и в три раза быстрее. Использует три регистра.

 

;чтение байта из циклического буфера buffer в регистр data

rdbyte: lds   xl,tail    ;указатель 
        ldi   xh,high(buffer);на чтение
        ld    data,x+    ;прочитаем байт
        andi  xl,bufsize-1  ;держим указатель
        sts   tail,xl    ;в рамках 
        ret

 

3) Кстати, что будет выдавать ваша программа, если буфер пуст? Предыдущие значения, поскольку count пойдёт в минус(:-)? Как сказал =mse=, и он 100% прав, пустой буфер-нередкая штатная ситуация.

1. Эх. Разгилдяй я.

2. Полный еще не значит переполненный.

3. Перед обращением к чтению нужно смотреть сколько байт в буфере.

rdbyte: lds   xl,tail    ;указатель 
        ldi   xh,high(buffer);на чтение

здесь мне непонятно как сформирован указатель чтения.

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


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

Что вас смущает.

2. Размер указателей зависит от размера буфера.

Ну и? Вы о чём-то думаете, а пишете вещи, которые по меньшей мере вызывают вопросы (а не глупость ли это написана?) из-за отсутствия логической связи с конкретными постами. Для меня указатель есть принаддлежность языка Си, соответственно вольное обращение с предметом режет слух. Попробуйте прочитать сами место, где оно появилось http://electronix.ru/forum/index.php?showt...amp;st=33

Суть, о чём говорили, теперь понятна.

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


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

2. Полный еще не значит переполненный.

3. Перед обращением к чтению нужно смотреть сколько байт в буфере.

rdbyte: lds   xl,tail        ;указатель 
        ldi   xh,high(buffer);на чтение

здесь мне непонятно как сформирован указатель чтения.

Ну как же, в переменной tail хранится младшая часть указателя, она загружается в xl. Для буфера объёмом меньшего или равного 256 байт, старшая часть указателя неизменна, это просто старшая часть начального адреса буфера, поэтому нет смысла её хранить, поэтому просто загружается константа в xh.

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


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

Ну и? Вы о чём-то думаете, а пишете вещи, которые по меньшей мере вызывают вопросы (а не глупость ли это написана?) из-за отсутствия логической связи с конкретными постами. Для меня указатель есть принаддлежность языка Си, соответственно вольное обращение с предметом режет слух.

:)

Я говорил в общепринятых терминах в привязке к теме вопроса "кольцевой буфер". Про Си не думал, а думал про "указатель на голову" и "указатель на хвост", как обычно пишут. Реализация, естественно, может быть разной. Если исходить из начальных постов данной темы, где приводилось упрощённое использование коротких указателей (***) с маскированием и привязкой буферов к началу сегмента (в Си не требуется), то при реализации на Си более правильно назвать это индексом. По типу:

  UDR0 = OutBuf[HeadOutBuf++];                            // Передаём    символ ответа
  HeadOutBuf &=0xf;                                        // Переход по кольцу

 

Если ввёл кого в заблуждение - прошу прощения. :)

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


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

Если ввёл кого в заблуждение

Да всё путём. Просто "в наше время нельзя доверять никому"(С);)))

 

Кстати, вопрос общего плана - а как можно использовать количество данных в буфере (типа семафор или как) при приёме? Не могу найти практического применения;)

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


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

Люди, а как Вы синхронизируете скорости заполнения буфера и отправки от него?

Может что такое новое придумали? :)

 

Поясняю. У меня циклический буфер для мониторинга процессов в терминале или PDA.

Есть моменты, когда буфер переполняется, так как идет интенсивная отправка данных. Буфер размером около 80 символов, больше выделить не могу. Я тупо ставлю Delay() после посылки каждой строки, чтобы в этих местах буфер не переполнился. Висеть в ожидании, пока там не освободится места, мне запрещает какая-то религия, не пойму какая :07:

 

Вы то как делаете?

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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