реклама на сайте
подробности

 
 
> Циклический буфер на AVR, (Примеры применения)
=GM=
сообщение Aug 24 2007, 15:16
Сообщение #1


Ambidexter
*****

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



Тема открыта по горячим следам недавней острой дискуссии.

В ней одним из участников (defunct) была приведена программа, в которой использовался циклический буфер для работы с последовательным портом МК AT90S2313. На взгляд автора программа написана достаточно грамотно, но как-то слишком размашисто, без учёта мизерности ресурсов данного МК. Предлагаю участникам поделиться примерами и приёмами использования циклического буфера в программных разработках.

Для затравки предлагаю следующие фрагменты.

А. Запись байта из регистра AL в циклический буфер
Код
      mov     xl,qhead    ;указатель на запись
      st      x+,al       ;запишем байт
      cp      xl,qend     ;конец буфера?
      brne    .+2         ;нет, обходим
      ldi     xl,buffer   ;да, установим начало

Б. Чтение байта из циклического буфера в регистр AL
Код
      mov     xl,qtail    ;указатель на чтение
      ld      al,x+       ;прочитаем байт
      cp      xl,qend     ;конец буфера?
      brne    .+2         ;нет, обходим
      ldi     xl,buffer   ;да, установим начало

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

В. Запись байта из регистра AL в циклический буфер длиной 32
Код
      mov     xl,qhead    ;указатель на запись
      st      x+,al       ;запишем байт
      cbr     xl,0xE0     ;держим указатель в предписанных рамках

Г. Чтение байта из циклического буфера длиной 32 в регистр AL
Код
      mov     xl,qtail    ;указатель на чтение
      ld      al,x+       ;прочитаем байт
      cbr     xl,0xE0     ;держим указатель в предписанных рамках

Здесь qhead, qtail, qend – регистровые переменные, содержащие адреса-указатели ячеек в озу для записи, чтения и конца буфера соответственно.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
alcosar
сообщение Aug 31 2007, 12:37
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 30-03-06
Пользователь №: 15 598



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

Внимание! Программа не тестировалась в реальной работе. Если есть косяки, буду признателен за поправки. Опыт работы с AVR очень маленький.
Код
.dseg

.equ    BUF_SIZE = 64    ; размер буфера, может быть n^2 <= 256


buf:    .byte    3 + BUF_SIZE; счетчик занятых ячеек, индекс чтения, состояние буфера, буфер

.cseg


;------------------------------------------------
init_buf:
;------------------------------------------------
; инициализация буфера
; используются r16, r28, r29

; в Y адрес структуры, задающей буфер    
    mov    YL, LOW(buf)
    mov    YH, HIGH(buf)
    clr    r16
    std    Y, r16
    std    Y+1, r16
    std    Y+2, r16
    ret


;------------------------------------------------
write_buf:
;------------------------------------------------
; в r16 байт для записи
; используются регисты r17, r18, r28, r29

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

; если буфер полный не записывать, установить флаг переполнения
    ld    r17, Y
    cpi    r17, BUF_SIZE - 1
    brcs    L1
    ldi    r17, 1
    std    Y+2, r17
    ret
L1:    
; определить индекс для записи
; i = (rindex + count) & (BUF_SIZE - 1)
    ld    r18, Y + 1
    add    r18, r17
    andi    r18, BUF_SIZE-1
    
; увеличить счетчик занятых ячеек в буфере
; count++
    inc    r17
    st    Y, r17

; buf[i] = data;
    clr    r17
    add    YL, r18
    adc    YH, r17
    std    Y+3, r16
    ret

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

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

; c = buf[rindex]
    ldd    r16, Y+3

    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 - Aug 31 2007, 12:40
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 31 2007, 15:12
Сообщение #3


Ambidexter
*****

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



Цитата(alcosar @ Aug 31 2007, 11:37) *
Код
; в Y адрес структуры, задающей буфер    
    mov    YL, LOW(buf)
    mov    YH, HIGH(buf)
; c = buf[rindex]
    ldd    r16, Y+3

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

Для загрузки непосредственных данных в регистр применяется команда ldi, а не mov.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
prottoss
сообщение Aug 31 2007, 16:53
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(=GM= @ Aug 31 2007, 23:12) *


Пара вопросов:

1.Сколько памяти программ и памяти данных занимает код с циклическими буферами для USART?

2.Почему во всех приведенных кодах процедуры чтения-записи из-в буферЫ нет команд запрета прерываний от обработчиков приема-окончания-передачи USART?


--------------------
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Aug 31 2007, 18:37
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(prottoss @ Aug 31 2007, 19:53) *
Пара вопросов:

1.Сколько памяти программ и памяти данных занимает код с циклическими буферами для USART?

2.Почему во всех приведенных кодах процедуры чтения-записи из-в буферЫ нет команд запрета прерываний от обработчиков приема-окончания-передачи USART?


1. Вы же видите - очень мало. Но не это главное. Циклический буфер позволяет работать с максимальной производительностью и абсолютно отделяет работу с внешним устройством от интерфейса. Это можно использовать в любом месте. Например в последней теме у меня два таких буфера. 1-UART, 2-EEPROM.

2. В этом есть особый смысл. smile.gif Классическая структура буфера - сам буфер+2переменных. Указатель на голову и указатель на хвост. Представим себе приём. В прерывании используется только хвост(добавляются символы), а в main только голова буфера (забираются данные).

Есть ещё один приятный момент. Если работаешь с подтверждениями (например CRC), то тоже имеется огромный плюс. Представьте кольцевой буфер и три указателя. Первых два я описал, а третий - указатель на недостоверные данные. Таким образом всё работает тем же способом, а по принятию решения (сравнение CRC) указатель на хвост присваивается либо указателю на принятые недостоверные данные (данные верны) либо наоборот указателю на недостоверные данные присваивается указатель на хвост (данные неверны и пакет требуется повторить). Никаких дополнительных средств и инструментов не требуется.

2 GM сенькую именно такую книгу искал (в смысле задача стоит именно как вы и написали). Сейчас буду искать саму книгу. smile.gif
Go to the top of the page
 
+Quote Post
prottoss
сообщение Aug 31 2007, 18:57
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(SasaVitebsk @ Sep 1 2007, 02:37) *
1. Вы же видите - очень мало. Но не это главное. Циклический буфер позволяет работать с максимальной производительностью и абсолютно отделяет работу с внешним устройством от интерфейса. Это можно использовать в любом месте. Например в последней теме у меня два таких буфера. 1-UART, 2-EEPROM.
В полезности циклических буферов я нисколько не сомневаюсь smile.gif и сам оччень часто их применяю. НО, очень мало, это сколько? smile.gif допустим применительно к АВР и его USART. Просто не вижу большого смысла тщательно рассказывать, как забивать гвозди...

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



Цитата(SasaVitebsk @ Sep 1 2007, 02:37) *
2. В этом есть особый смысл. smile.gif Классическая структура буфера - сам буфер+2переменных. Указатель на голову и указатель на хвост. Представим себе приём. В прерывании используется только хвост(добавляются символы), а в main только голова буфера (забираются данные).
А когда хвост догнал голову, а он важнее (ибо прерывание) получается баальшой булик lol.gif

Цитата(SasaVitebsk @ Sep 1 2007, 02:37) *
Есть ещё один приятный момент.

..................Никаких дополнительных средств и инструментов не требуется.
Кроме анальгина


--------------------
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 3 2007, 14:31
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(prottoss @ Aug 31 2007, 21:57) *
В полезности циклических буферов я нисколько не сомневаюсь smile.gif и сам оччень часто их применяю. НО, очень мало, это сколько? smile.gif допустим применительно к АВР и его USART. Просто не вижу большого смысла тщательно рассказывать, как забивать гвозди...

Для реализации достаточно самого буфера + два указателя.
1. Размер буфера оцениваю исходя из из того что быстрее работает. Например IBM накачивает быстрее чем AVR разгребает. В этом случае размер приёмного буфера для AVR при 485 интерфейсе составляет два размера пакета + 5-6 байт. Для 232 интерфейса приблизительно 1к. Дальнейшее увеличение размера буфера даёт незначительный рост производительности.
2. Размер указателей зависит от размера буфера. Если буфер менее 256 байт, то указатели - байтовые, если больше то 2.
3. Если использую пакетную передачу, то, как я и описывал вводится ещё один указатель (недостоверных данных)
4. Если используется конвертер из одного интерфейса в другой, то некоторые указатели совмещаются размер буфера увеличивается.
Цитата
Почему нет ни единого примера на Си?
А когда хвост догнал голову, а он важнее (ибо прерывание) получается баальшой булик lol.gif

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

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

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

Сообщений в этой теме
- =GM=   Циклический буфер на AVR   Aug 24 2007, 15:16
- - defunct   Цитата(=GM= @ Aug 24 2007, 18:16) Если ис...   Aug 24 2007, 22:12
- - =AVR=   Такой метод (посредством урезания операцией ...   Aug 25 2007, 05:42
|- - SasaVitebsk   Цитата(=AVR= @ Aug 25 2007, 08:42) Такой ...   Aug 26 2007, 10:50
|- - =GM=   Привет всем! Отъезжал ненадолго, тут праздник ...   Aug 28 2007, 16:02
|- - WHALE   Цитата(=GM= @ Aug 28 2007, 20:02) Привет ...   Aug 28 2007, 18:33
||- - =GM=   Цитата(WHALE @ Aug 28 2007, 18:33) Господ...   Aug 28 2007, 22:33
|- - SasaVitebsk   Цитата(=GM= @ Aug 28 2007, 19:02) 1) To S...   Aug 28 2007, 19:20
|- - =AVR=   Аппаратные буфера отличаются от address mode тем ж...   Aug 28 2007, 20:21
- - sensor_ua   IMHO, обсуждение циклических буферов в привязке к ...   Aug 25 2007, 07:11
- - mse   Цитата(=GM= @ Aug 24 2007, 19:16) Код m...   Aug 25 2007, 07:48
- - adnega   Доброго дня! Мне вот очень интересно применен...   Aug 27 2007, 06:45
- - zltigo   Moderator: Так, оба двое и присоединившийся к ним ...   Aug 28 2007, 22:41
|- - =GM=   Цитата(zltigo @ Aug 28 2007, 22:41) Если ...   Aug 29 2007, 00:07
- - SasaVitebsk   2 AVR спасибо. До вашего варианта не додумался. Пр...   Aug 29 2007, 11:05
|- - =GM=   Цитата(SasaVitebsk @ Aug 29 2007, 10:05) ...   Aug 29 2007, 12:13
|- - alcosar   [quote name='=GM=' date='Aug 31 2007, ...   Sep 2 2007, 18:55
- - sensor_ua   ЦитатаЦиклический буфер позволяет работать с макси...   Aug 31 2007, 19:56
|- - mse   Цитата(sensor_ua @ Aug 31 2007, 23:56) Вс...   Sep 1 2007, 07:03
|- - prottoss   Цитата(mse @ Sep 1 2007, 15:03) Практика ...   Sep 1 2007, 07:15
|- - mse   Цитата(prottoss @ Sep 1 2007, 11:15) Прак...   Sep 1 2007, 08:57
|- - prottoss   Цитата(mse @ Sep 1 2007, 16:57) Если загр...   Sep 1 2007, 09:02
|- - mse   Цитата(prottoss @ Sep 1 2007, 13:02) Ну В...   Sep 1 2007, 09:23
|- - =GM=   To alcosar 1) Здесь: std Y+1,r16 у вас ошибка, на...   Sep 3 2007, 11:54
|- - alcosar   Цитата(=GM= @ Sep 3 2007, 14:54) To alcos...   Sep 3 2007, 19:33
|- - =GM=   Цитата(alcosar @ Sep 3 2007, 19:33) 2. По...   Sep 3 2007, 20:45
- - sensor_ua   ЦитатаПочему нет ни единого примера на Си? Файл пр...   Sep 1 2007, 07:45
|- - zltigo   Цитата(sensor_ua @ Sep 1 2007, 10:45) Код...   Sep 1 2007, 08:36
- - prottoss   Выложу и я свое здесь, хоть уже и выкладывал в тем...   Sep 1 2007, 08:43
- - sensor_ua   ЦитатаНу хоть тэгами пользуйтесь для выделения исх...   Sep 1 2007, 09:03
- - sensor_ua   Цитата2. Размер указателей зависит от размера буфе...   Sep 3 2007, 15:03
|- - SasaVitebsk   Цитата(sensor_ua @ Sep 3 2007, 18:03) Про...   Sep 3 2007, 15:14
- - sensor_ua   ЦитатаЕстественно на стадии написания программы Ра...   Sep 3 2007, 17:51
|- - =GM=   Цитата(sensor_ua @ Sep 3 2007, 17:51) Ука...   Sep 3 2007, 19:25
|- - SasaVitebsk   Цитата(sensor_ua @ Sep 3 2007, 20:51) Рац...   Sep 3 2007, 19:33
- - sensor_ua   ЦитатаЧто вас смущает. Цитата2. Размер указателей ...   Sep 3 2007, 19:50
|- - SasaVitebsk   Цитата(sensor_ua @ Sep 3 2007, 22:50) Ну ...   Sep 4 2007, 17:07
- - sensor_ua   ЦитатаЕсли ввёл кого в заблуждение Да всё путём. П...   Sep 4 2007, 17:46
|- - Dog Pawlowa   Люди, а как Вы синхронизируете скорости заполнения...   Sep 4 2007, 18:06
|- - mse   Цитата(Dog Pawlowa @ Sep 4 2007, 22:06) Л...   Sep 4 2007, 18:39
|- - bodja74   Цитата(Dog Pawlowa @ Sep 4 2007, 21:06) Л...   Sep 4 2007, 20:46
|- - defunct   Цитата(Dog Pawlowa @ Sep 4 2007, 21:06) Л...   Sep 8 2007, 22:21
- - sensor_ua   ЦитатаВисеть в ожидании, пока там не освободится м...   Sep 4 2007, 18:44
- - Dog Pawlowa   Цитата(sensor_ua @ Sep 4 2007, 21:44) Дык...   Sep 5 2007, 05:03
- - sensor_ua   Цитата(Dog Pawlowa @ Sep 5 2007, 08:03) У...   Sep 5 2007, 06:33
- - Dog Pawlowa   Цитата(sensor_ua @ Sep 5 2007, 09:33) Исп...   Sep 5 2007, 07:19


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 9th August 2025 - 05:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016