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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Циклический буфер на AVR, (Примеры применения)
=GM=
сообщение Aug 29 2007, 12:13
Сообщение #16


Ambidexter
*****

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



Цитата(SasaVitebsk @ Aug 29 2007, 10:05) *
Я вот всё больше и больше склоняюсь к мысли что необходимо унифицировать некоторые узлы и блоки, процедуры процессоронезависимые и даже переменные и структуры.

Прошу прощения за отход от темы может кто посоветует хорошую книгу в данной области. То есть что-то по типу визуализации/структурирования. Даже не знаю как назвать эту область. Короче выработки единого подхода к написанию прог на Си.

Попробуйте вот эту книжку: Ван Тассел Д. Стиль, разработка, эффективность, отладка и испытание программ: Пер. с англ. , 1981. Много ценных мыслей, в своё время очень мне помогла систематизировать программирование, как вид деятельности.


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


Участник
*

Группа: Участник
Сообщений: 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
Сообщение #18


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
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 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
sensor_ua
сообщение Aug 31 2007, 19:56
Сообщение #22


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



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

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


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
mse
сообщение Sep 1 2007, 07:03
Сообщение #23


Знающий
****

Группа: Свой
Сообщений: 709
Регистрация: 3-05-05
Пользователь №: 4 693



Цитата(sensor_ua @ Aug 31 2007, 23:56) *
Всё-таки накладные нужно отметить - это удвоенное время пересылки байтов - в буфер и из него.
...

Для УАРТовых времян это слёзы.
Цитата
А когда хвост догнал голову, а он важнее (ибо прерывание) получается баальшой булик

Практика такова, что это хвост постоянно сидит на хвосте у головы ;О) Даже если УАРТ работает на мегабоде, то между двумя байтами 160 тактов. За это время фон успеет прожевать не один байт. Конечно, если его тормознут на 100мкС, тогда приёмник ему накидает. Но всё равно, потом фон огуляет принятое гораздо быстрее. ;О)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Sep 1 2007, 07:15
Сообщение #24


Гуру
******

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



Цитата(mse @ Sep 1 2007, 15:03) *
Практика такова, что это хвост постоянно сидит на хвосте у головы ;О) Даже если УАРТ работает на мегабоде, то между двумя байтами 160 тактов. За это время фон успеет прожевать не один байт. Конечно, если его тормознут на 100мкС, тогда приёмник ему накидает. Но всё равно, потом фон огуляет принятое гораздо быстрее. ;О)
Практика Ваша? Или мировая? Или кЫтайская? 160 тактов, как сказал один чел выше - это очень мало smile.gif Если за это время основной поток не заберет из головы данные, то хвост накидает голове байтов по самые уши - будет потеря данных

Опять же сказанное мной выше то - что показывает практика


--------------------
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Sep 1 2007, 07:45
Сообщение #25


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



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

Файл прицепить не получилось, так что как есть... (Рулёжка по типам камешков была, так её вырезал. Вроде корректно)

Код
#include "uart.h"

unsigned char U0_RxBufGetIndex = 0;
unsigned char U0_RxBufPutIndex = 0;
unsigned char U0_RxBufSize = BUF0RXSIZE;
unsigned int U0_RxBuffer[BUF0RXSIZE] = {0};

void USART0_Ring_Flush(void){
  U0_RxBufGetIndex = U0_RxBufPutIndex;
  return;
}

int UART0_getc (void){
  int proxy = 0;
  if(U0_RxBufPutIndex != U0_RxBufGetIndex){
    //proxy = U0_RxBuffer[U0_RxBufGetIndex] & (~(((!!PARITY)<<RXB80)<<8));
    proxy = U0_RxBuffer[U0_RxBufGetIndex];
    U0_RxBufGetIndex = (U0_RxBufGetIndex+1)&(U0_RxBufSize-1);  
    // modulo UART0_RxBufSize
    return (proxy);    
  }
  return (EOF);
}

#ifdef __ICCAVR__
#pragma vector = USART_RX_vect
__interrupt void USART_RX_Handler(void){
#else
ISR(USART_RX_vect){
#endif

  unsigned char status;
//  unsigned char resh;
  status = UCSR0A;
  //resh = UCSR0B;
  
  // Read flags
  U0_RxBuffer[U0_RxBufPutIndex] = (status & ((1<<FE0)|(1<<DOR0)|(1<<UPE0))) << 8;
  
  // Filter the 9th bit, then return
  //U0_RxBuffer[U0_RxBufPutIndex] |= _BLV(resh, RXB80) << 8; //(resh >> 1) & 0x01;

  U0_RxBuffer[U0_RxBufPutIndex] |= UDR0;
  // normal ready, save into the Data Ring Buffer

  U0_RxBufPutIndex=(U0_RxBufPutIndex+1)&(U0_RxBufSize-1);
  // PutIndex modulo BufferSize

  if(U0_RxBufPutIndex == U0_RxBufGetIndex) {
    U0_RxBufPutIndex--;
    U0_RxBufPutIndex &= U0_RxBufSize-1;
    // PutIndex modulo BufferSize
  }
  return;
}


то:sensor_ua
Ну хоть тэгами пользуйтесь для выделения исходников

Сообщение отредактировал zltigo - Sep 1 2007, 08:24


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 1 2007, 08:36
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sensor_ua @ Sep 1 2007, 10:45) *
Код
  U0_RxBuffer[U0_RxBufPutIndex] |= UDR0;
  // normal ready, save into the Data Ring Buffer

  U0_RxBufPutIndex=(U0_RxBufPutIndex+1)&(U0_RxBufSize-1);
  // PutIndex modulo BufferSize

А так:
Код
  U0_RxBuffer[(U0_RxBufPutIndex++)&(U0_RxBufSize-1)] |= UDR0;

При этом Вы имеете всегда полный индекс равный счетчику помещенных извлеченных байтов и одним простым арифметическим действием (в пределах размерности счетчиков, естественно ) можете узнать количество байтов в буфере.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
prottoss
сообщение Sep 1 2007, 08:43
Сообщение #27


Гуру
******

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



Выложу и я свое здесь, хоть уже и выкладывал в теме про исходники - http://electronix.ru/forum/index.php?showtopic=10934
Прикрепленные файлы
Прикрепленный файл  usart.driver.rar ( 4.47 килобайт ) Кол-во скачиваний: 366
 


--------------------
Go to the top of the page
 
+Quote Post
mse
сообщение Sep 1 2007, 08:57
Сообщение #28


Знающий
****

Группа: Свой
Сообщений: 709
Регистрация: 3-05-05
Пользователь №: 4 693



Цитата(prottoss @ Sep 1 2007, 11:15) *
Практика Ваша? Или мировая? Или кЫтайская? 160 тактов, как сказал один чел выше - это очень мало smile.gif Если за это время основной поток не заберет из головы данные, то хвост накидает голове байтов по самые уши - будет потеря данных

Опять же сказанное мной выше то - что показывает практика

Практичная практика. Проистекает от навыков владения калькулятором и головным мосхом:
Если загрузка фона сильная, то разработчик обязан оценить эту загрузку и взять глубину буфера, чтобы голова не топталась по хвосту, пока фон топчется по своим делам. Задача сродни определению требуемой глубины стека. Если таинством арифметики разрабоччик, таки, настойчиво овладел, то 160 тактов ему - выше крыши. А тому одному челу сверху виднее, чего он наворотил, мож ему и мало. А я на 160 тактах зайца в поле загоняю.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Sep 1 2007, 09:02
Сообщение #29


Гуру
******

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



Цитата(mse @ Sep 1 2007, 16:57) *
Если загрузка фона сильная, то разработчик обязан оценить эту загрузку и взять глубину буфера, чтобы голова не топталась по хвосту, пока фон топчется по своим делам.
Ну Вы прям как Бил Гейтс и Ко smile.gif

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


--------------------
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Sep 1 2007, 09:03
Сообщение #30


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Ну хоть тэгами пользуйтесь для выделения исходников

Пробовал pre и code - не получилось
Цитата
А так:

U0_RxBuffer[(U0_RxBufPutIndex++)&(U0_RxBufSize-1)] |= UDR0;

Ничего против. Просто я при переполнении переписываю последний доступный для записи байт буфера принятым символом (это может быть полезным при поиске управляющих символов, но тогда ещё одна пересылка данных и сравнение внизу). Потому "не верю" этому счётчику. И мне вообще-то не приходится в моих последующих процедурах узнавать размер данных попавших в буферwink.gif - может ещё и потому и не пытаюсь семафорить. Кроме того, так (в одну строку) не пишу, потому как иногда пользую буфер размером не кратным 2^N. Тогда (может мне кажется) рихтуется меньше.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 07:25
Рейтинг@Mail.ru


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