|
|
  |
Циклический буфер на AVR, (Примеры применения) |
|
|
|
Sep 1 2007, 09:23
|
Знающий
   
Группа: Свой
Сообщений: 709
Регистрация: 3-05-05
Пользователь №: 4 693

|
Цитата(prottoss @ Sep 1 2007, 13:02)  Ну Вы прям как Бил Гейтс и Ко ИМХО разарботчик обязан сделать так, чтобы его программа не вешалась от добавления пары строк кода где угодно и когда угодна. А взять глубину буфера какую вздумается можно на пне4 и ижесними Ну и каким местом ваш поток сознания к теме? А уж, тем более, к цытируемому? Где я написал "взять глубину буфера какую вздумается". Здесь, что-ли "...обязан оценить эту загрузку и взять глубину буфера, чтобы...". Т.е. оценить и ПОСЧИТАТЬ, это "какое вздумается"? Толково! Цитата ...обязан сделать так, чтобы его программа не вешалась от добавления пары строк... Ага, обязан сказать:" по счучьему велению, не вешайся, программа, от добавления пары строк!" Добавил пару строк - посчитай, добавь глубины, если надо. Потому как за твоих "пару строк" вполне может из линии насыпаться в два раза больше байтиков, чем без них.
|
|
|
|
|
Sep 2 2007, 18:55
|
Участник

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

|
[quote name='=GM=' date='Aug 31 2007, 18:12' post='289675'] Здесь логическая ошибка, вы всё время читаете из одной и той же ячейки памяти. Идея сделать отдельный счётчик на заполнение буфера мне кажется здравой, надо обдумать на досуге. [quote] Спасибо за поправку. Вроде бы теперь правильно. Код ;------------------------------------------------ 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 - Sep 2 2007, 19:17
|
|
|
|
|
Sep 3 2007, 11:54
|

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

|
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% прав, пустой буфер-нередкая штатная ситуация.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 3 2007, 14:31
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(prottoss @ Aug 31 2007, 21:57)  В полезности циклических буферов я нисколько не сомневаюсь  и сам оччень часто их применяю. НО, очень мало, это сколько?  допустим применительно к АВР и его USART. Просто не вижу большого смысла тщательно рассказывать, как забивать гвозди... Для реализации достаточно самого буфера + два указателя. 1. Размер буфера оцениваю исходя из из того что быстрее работает. Например IBM накачивает быстрее чем AVR разгребает. В этом случае размер приёмного буфера для AVR при 485 интерфейсе составляет два размера пакета + 5-6 байт. Для 232 интерфейса приблизительно 1к. Дальнейшее увеличение размера буфера даёт незначительный рост производительности. 2. Размер указателей зависит от размера буфера. Если буфер менее 256 байт, то указатели - байтовые, если больше то 2. 3. Если использую пакетную передачу, то, как я и описывал вводится ещё один указатель (недостоверных данных) 4. Если используется конвертер из одного интерфейса в другой, то некоторые указатели совмещаются размер буфера увеличивается. Цитата Почему нет ни единого примера на Си? А когда хвост догнал голову, а он важнее (ибо прерывание) получается баальшой булик  Честно говоря не понял шутки. Если буфер обнулён, то просто прекращается передача. Если заполнен ПОЧТИ полностью, то выполняется приостановка канала любым способом "управления потоком" - либо установкой сигнала CTS (HARD) либо передачей символа XOFF(SOFT). Буфер должен быть расчитан на приём 16 байт с момента выдачи остановки приёма. При работе с 485, очевидно, что вы сами должны следить за заполнением буфера. Но при чём здесь кольцевой буфер??? Если вы не справляетесь с приёмом, то управление потоком должно быть реализовано в любом случае. Цитата Кроме анальгина Вы просто не работали с большими потоками данных например в четыре стороны. Иначе, простите за эмоции, вы бы бред не писали. Кольцевой буфер это один из очень красивых алгоритмов. И, при правильной реализации, даёт разработчику возможность скрыть все тонкости приёма/передачи внутри драйвера. Поэтому, возможно, мало примеров. Так как придётся вычищать некоторые мелкие моменты.
|
|
|
|
|
Sep 3 2007, 15:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата 2. Размер указателей зависит от размера буфера. Если буфер менее 256 байт, то указатели - байтовые, если больше то 2. Простите, но непонятно, как Вы меняете размер указателя или что подразумеваете под "размер указателя"
--------------------
aka Vit
|
|
|
|
|
Sep 3 2007, 17:51
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Естественно на стадии написания программы Рация на танке(С) Указатели обычно имеют размерность шины адреса  или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR. Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения.
--------------------
aka Vit
|
|
|
|
|
Sep 3 2007, 19:25
|

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

|
Цитата(sensor_ua @ Sep 3 2007, 17:51)  Указатели обычно имеют размерность шины адреса  или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR. Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения. Именно указатели, хотя памяти в АВРках - кот наплакал 0.5-1.0-2.0 Кбайта, редко больше. Но тем не менее, указатель 16-битный и занимает парные регистры x, y или z. В части приведённых программ старшая часть адреса присутствует как бы за кадром, поскольку она не меняется, установили её один раз в программе и забыли. Обратите внимание на завершенную подпрограмму чтения байта из кольцевого буфера в посте #33. В паре регистров (xh,xl) находится честный 16-битный указатель на чтение, младшая часть которого хранится в ячейке tail.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 3 2007, 19:33
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(sensor_ua @ Sep 3 2007, 20:51)  Рация на танке(С) Указатели обычно имеют размерность шины адреса  или чуть более - для AVR это 16 бит и несколько больше в случае использования __generic в компиляторе IAR. Похоже имелись в виду не указатели, а индексы. Тогда оптимально будет короткие (до 256 байт) буферы размещать по адресам, кратным 256 (о примерно таком говорил =GM= в начале топика), тогда можно получить выигрыш и в объёме кода, и в скорости выполнения. Имелись в виду указатели. Что вас смущает. Хранятся младшие байты указателей. Старшие - фиксированы. Где танк? Посмотрите топик 6. В условиях экономии памяти вполне применимо.
|
|
|
|
|
Sep 3 2007, 19:33
|
Участник

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

|
Цитата(=GM= @ Sep 3 2007, 14:54)  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);на чтение здесь мне непонятно как сформирован указатель чтения.
|
|
|
|
|
Sep 3 2007, 19:50
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Что вас смущает. Цитата 2. Размер указателей зависит от размера буфера. Ну и? Вы о чём-то думаете, а пишете вещи, которые по меньшей мере вызывают вопросы (а не глупость ли это написана?) из-за отсутствия логической связи с конкретными постами. Для меня указатель есть принаддлежность языка Си, соответственно вольное обращение с предметом режет слух. Попробуйте прочитать сами место, где оно появилось http://electronix.ru/forum/index.php?showt...amp;st=33&#Суть, о чём говорили, теперь понятна.
--------------------
aka Vit
|
|
|
|
|
Sep 3 2007, 20:45
|

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

|
Цитата(alcosar @ Sep 3 2007, 19:33)  2. Полный еще не значит переполненный. 3. Перед обращением к чтению нужно смотреть сколько байт в буфере. Код rdbyte: lds xl,tail ;указатель ldi xh,high(buffer);на чтение здесь мне непонятно как сформирован указатель чтения. Ну как же, в переменной tail хранится младшая часть указателя, она загружается в xl. Для буфера объёмом меньшего или равного 256 байт, старшая часть указателя неизменна, это просто старшая часть начального адреса буфера, поэтому нет смысла её хранить, поэтому просто загружается константа в xh.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 4 2007, 17:07
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(sensor_ua @ Sep 3 2007, 22:50)  Ну и? Вы о чём-то думаете, а пишете вещи, которые по меньшей мере вызывают вопросы (а не глупость ли это написана?) из-за отсутствия логической связи с конкретными постами. Для меня указатель есть принаддлежность языка Си, соответственно вольное обращение с предметом режет слух. Я говорил в общепринятых терминах в привязке к теме вопроса "кольцевой буфер". Про Си не думал, а думал про "указатель на голову" и "указатель на хвост", как обычно пишут. Реализация, естественно, может быть разной. Если исходить из начальных постов данной темы, где приводилось упрощённое использование коротких указателей (***) с маскированием и привязкой буферов к началу сегмента (в Си не требуется), то при реализации на Си более правильно назвать это индексом. По типу: Код UDR0 = OutBuf[HeadOutBuf++]; // Передаём символ ответа HeadOutBuf &=0xf; // Переход по кольцу Если ввёл кого в заблуждение - прошу прощения.
|
|
|
|
|
Sep 4 2007, 17:46
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Если ввёл кого в заблуждение Да всё путём. Просто "в наше время нельзя доверять никому"(С)  )) Кстати, вопрос общего плана - а как можно использовать количество данных в буфере (типа семафор или как) при приёме? Не могу найти практического применения
--------------------
aka Vit
|
|
|
|
|
Sep 4 2007, 18:06
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Люди, а как Вы синхронизируете скорости заполнения буфера и отправки от него? Может что такое новое придумали? Поясняю. У меня циклический буфер для мониторинга процессов в терминале или PDA. Есть моменты, когда буфер переполняется, так как идет интенсивная отправка данных. Буфер размером около 80 символов, больше выделить не могу. Я тупо ставлю Delay() после посылки каждой строки, чтобы в этих местах буфер не переполнился. Висеть в ожидании, пока там не освободится места, мне запрещает какая-то религия, не пойму какая Вы то как делаете?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|