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

 
 
> Закольцевать данные, программа на Си
Dubov
сообщение Jun 3 2014, 05:09
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052



Имеется буфер длины N
имеется подпрограмма, принимающая на вход указатель на блок данных длины N.

Буфер заполняется циклически (по заполнении буфера, новый отсчёт поступает в начало буфера).

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

Как закольцевать адресацию массива?

Например, может получится ситуация когда указатель находится в произвольном месте массива:

| (a) ( b ) (PTR) (...) (N) |

тогда подпрограмма должна "знать", что она оперирует с массивом | (PTR) (...) (N) (a) ( b ) |

Сообщение отредактировал Dubov - Jun 3 2014, 05:10
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
mempfis_
сообщение Jun 3 2014, 06:02
Сообщение #2


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(Dubov @ Jun 3 2014, 12:19) *
Имеется буфер длины N
имеется подпрограмма, принимающая на вход указатель на блок данных длины N.
Буфер заполняется циклически (по заполнении буфера, новый отсчёт поступает в начало буфера).
с каждым новым вызовом подпрограммы, получаемый указатель увеличивается на единицу.
Как закольцевать адресацию массива?


Может быть Вам стоит поступить немного иначе - организовать 2 функции putArray(data) и getarray()
putArray(data) закидывает данные в буффер, контролируя при этом переход через границу буффера и смещая позицию head (позицию куда необходимо закидывать следующие данные)
Код
void putarray(short data)
{
buff[head] = data;
head++;
if(head >= BUFF_SIZE) head = 0; //переход через границу буффера
}


Функция getArray() возвращает или-1 если нет данных, или данные
Код
signed int getArray(void)
{
signed int res = -1;
if(head == tail) return res; //нет данных - возвращаем -1
res = buff[tail];
tail++;
if(tail >= BUFF_SIZE) tail = 0;
return res; //возвращаем данные

}


Эти 2 процедуры позволяют организовать FIFO данных без проверки переполнения буффера.
Если Вам критично отслеживать переполнение, то всегда можно ввести переменную status, которой можно присваивать статусы empty/not_empty/full
Также довольно легко вместо данных, возвращать указатели на данные.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Jun 3 2014, 07:30
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(mempfis_ @ Jun 3 2014, 13:12) *
Функция getArray() возвращает или-1 если нет данных, или данные
Код
signed int getArray(void)
{
signed int res = -1;
if(head == tail) return res; //нет данных - возвращаем -1
res = buff[tail];
tail++;
if(tail >= BUFF_SIZE) tail = 0;
return res; //возвращаем данные
}

Только в этой функции, я думаю , не увеличение tail а набоборот:
Код
signed int getArray(void)
{
signed int res = -1;
if(head == 0) return res; //нет данных - возвращаем -1
res = buff[tail];
tail--;
return res; //возвращаем данные
}
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 3 2014, 08:13
Сообщение #4


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(MaxiMuz @ Jun 3 2014, 14:40) *
Только в этой функции, я думаю , не увеличение tail а набоборот:
Код
signed int getArray(void)
{
signed int res = -1;
if(head == 0) return res; //нет данных - возвращаем -1
res = buff[tail];
tail++;
return res; //возвращаем данные
}


Исходный код правильный - это кольцевой буффер FIFO.
По позици head ложим данные с инкрементом head.
Забираем данные по позиции tail с инкрементом tail.
При закидывании данных голова убегает от хвоста.
При извлечении - хвост догоняет голову.

Если Т.С. нужен кольцевой буффер с доступом по указателю, то megajohn уже подсказал решение.


Позволю себе также пояснить то, что предложил megajohn

Предположим у Вас есть буффер char-элементов buff расположенный по адресу 0x1000 и размер BUFF_SIZE = 256 байт
Тогда Ваш буффер будет занимать диапазон адресов 0xFF1000 - 0x001000
Маска для этого диапазона адресов ADDR_MSK = 0xFF<<12

Теперь мы хотим считать с любой позиции буффера через указатель 256 байт, но так, чтобы при достижении границы буффера адрес автоматически перешёл в начало
Код
unsigned char* pbuff = &buff[255];
for(unsigned int i=0; i<BUFF_SIZE; i++)
{
*((pbuff+i)&ADDR_MSK);
}


Сначала адрес pbuff+i = 0xff1000+0
Читаем с этого адреса значение из ячейки buff[255]
Далее инкремен i и адрес становится pbuff+i=0xff1000+1=0x1001000
Но мы накладываем маску адресов 0xff<<12 и получаем адрес 0x100010000&(0xff<<12) = 0x001000;
Т.е. новый адрес соответсвует ячейке buff[0];
при i == 1 адрес будет 0x1011000&(0xff<<12) = 0x001000
и так далее.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Jun 5 2014, 08:15
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(mempfis_ @ Jun 3 2014, 15:23) *
Тогда Ваш буффер будет занимать диапазон адресов 0xFF1000 - 0x001000
Маска для этого диапазона адресов ADDR_MSK = 0xFF<<12

Принцип понял, но непонятен механизм.
Цитата(mempfis_ @ Jun 3 2014, 15:23) *
Сначала адрес pbuff+i = 0xff1000+0
Читаем с этого адреса значение из ячейки buff[255]
Далее инкремен i и адрес становится pbuff+i=0xff1000+1=0x1001000
Но мы накладываем маску адресов 0xff<<12 и получаем адрес 0x100010000&(0xff<<12) = 0x001000;
Т.е. новый адрес соответсвует ячейке buff[0];
при i == 1 адрес будет 0x1011000&(0xff<<12) = 0x001000
и так далее.

i=0 ,получаем адрес ((pbuff+i)&ADDR_MSK) = (0х00001000+0)&0x000FF000 = 0х00001000
i=1 : ((pbuff+i)&ADDR_MSK) = (0х00001000+1)&0x000FF000 = 0х00001000
тот же самый адрес, или я чего то не так понял ?
Go to the top of the page
 
+Quote Post
megajohn
сообщение Jun 5 2014, 08:24
Сообщение #6


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(MaxiMuz @ Jun 5 2014, 16:25) *
тот же самый адрес, или я чего то не так понял ?


автар перепутал байт
вместо "Тогда Ваш буффер будет занимать диапазон адресов 0xFF1000 - 0x001000"
читать "Тогда Ваш буффер будет занимать диапазон адресов 0x0010FF - 0x001000"

и далее, сам же запутался (или HumanEndian путает с HardwareEndian ) =)


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Dubov   Закольцевать данные   Jun 3 2014, 05:09
- - menzoda   Вместе с указателем на данные передавать указатель...   Jun 3 2014, 05:59
|- - Dubov   Цитата(menzoda @ Jun 3 2014, 14:09) Вмест...   Jun 3 2014, 06:38
|- - megajohn   Цитата(Dubov @ Jun 3 2014, 14:48) В идеал...   Jun 3 2014, 06:42
||- - Dubov   Цитата(megajohn @ Jun 3 2014, 14:52) ну д...   Jun 3 2014, 06:47
||- - _pv   Цитата(Dubov @ Jun 3 2014, 17:57) прошу п...   Jun 3 2014, 07:43
||- - megajohn   Цитата(Dubov @ Jun 3 2014, 14:57) прошу п...   Jun 3 2014, 07:50
||- - mdmitry   Цитата(Dubov @ Jun 3 2014, 14:57) прошу п...   Jun 3 2014, 08:29
|- - menzoda   Цитата(Dubov @ Jun 3 2014, 14:48) допусти...   Jun 3 2014, 08:18
|- - mempfis_   Цитата(megajohn @ Jun 5 2014, 15:34) авта...   Jun 5 2014, 09:34
|- - menzoda   Цитата(mempfis_ @ Jun 5 2014, 17:44) Тогд...   Jun 5 2014, 15:17
- - Voldemari4   Можно сделать указатель типом BYTE. Если размер ма...   Jun 3 2014, 07:43
- - x893   а может просто код посмотреть ? 1. http://c.learn...   Jun 5 2014, 09:15
- - alexeyv   ЦитатаДа в них и так нет необходимости. Что все пр...   Jun 9 2014, 01:14
|- - Сергей Борщ   Цитата(alexeyv @ Jun 9 2014, 08:24) Видат...   Jun 9 2014, 02:36
- - alexeyv   Цитатано совать его везде "потому что микроко...   Jun 9 2014, 22:27
|- - menzoda   Как раз таки я прекрасно представляю, что будет в ...   Jun 10 2014, 01:47
- - Genadi Zawidowski   ЦитатаТак и обрабатывать. В цикле проверять не дош...   Jun 12 2014, 20:37


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

 


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


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