roboforum.ru

Технический форум по робототехнике.

Динамически изменяемый размер переменной

Динамически изменяемый размер переменной

NEOSoftWare » 15 авг 2012, 13:34

Подскажите пожалуйста как на atmega8a можно изменить размер переменной.
например для временно хранения uart данных. они могут быть как 20 байт так и 2 кб.

Re: Динамически изменяемый размер переменной

legion » 15 авг 2012, 13:41

Нужно больше золота данных. Почему не выделить сразу большой объем ОЗУ под эти данные?

Re: Динамически изменяемый размер переменной

NEOSoftWare » 15 авг 2012, 13:53

ну применяться будет не совсем для озу, а для рам. а создавать сразу переменную которая бы заняла бы весь объем - для меня не вариант. несколько переменных с разным объемом (от 1 до 50 байт например). то есть суть такая если переменные маленькие то можно записать большее количество блоков если данные большие то всего несколько, после какого то времени их удалить и по новой выделить для них место в рам.

Re: Динамически изменяемый размер переменной

=DeaD= » 15 авг 2012, 14:02

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

Re: Динамически изменяемый размер переменной

Romikgy » 15 авг 2012, 14:12

имхо решение одно , на лету дешифровать то, что нужно

Re: Динамически изменяемый размер переменной

NEOSoftWare » 15 авг 2012, 14:24

с++ в частности codeavr :) дешевровать на лету не самый удачный вариант, т.к. на придумывание, анализ и отладку у меня уйдет много времени. думал есть что то уже готовое как например для делфей
Код: Выделить всёРазвернуть
var
data: array of array of byte;
...
begin
setlength(data,2);

setlength(data[0],4);
setlength(data[1],10);
setlength(data[2],7);
....

setlength(data,0); // очищаем
// и т.д.

Re: Динамически изменяемый размер переменной

=DeaD= » 15 авг 2012, 14:40

Заведите массив и работайте с указателями в нём :)

Re: Динамически изменяемый размер переменной

NEOSoftWare » 15 авг 2012, 14:46

=DeaD= писал(а):Заведите массив и работайте с указателями в нём :)

а по подробнее? если можно пример :)

Re: Динамически изменяемый размер переменной

Romikgy » 15 авг 2012, 15:08

к МК не совсем корректно применять динамические массивы.... в первую очередь из-за ограниченного объема самой памяти !

Re: Динамически изменяемый размер переменной

Angel71 » 15 авг 2012, 18:48

небольшой объём внутренней памяти при необходимости скрашивается возможностью подключения внешней.
хз, что за зверь такой этот codeavr, есть ли там всякие malloc, free, realoc и прочие. нужна 1 переменная для хранения размерности массива и собственно сам одномерный массив максимальной длины для хранения данных. максимальной - это или необходимый максимум для хранения этих данных, если заранее известно или максимум, что есть в меге с учётом стека и минимизации всяких финтов с рекурсией и прочим. изначально размерность 0. создаём первый элемент, переменной +1. нужно допцустим 5 байт, вот в первую ячейку заносите 5, следующие 5 ячеек собственно данные (можно и инициализировать нулями при желании). теперь допустим нужно создать размеров в 10 байт. создаём второй элемент, опять добавляя +1 к переменной. в 7ю ячейку заносите 10, сл. 10 ячеек будут данные.
n = 2
m содержит такую последовательность байт (на всякий, в скобках адрес) [0]5 [1]0[2]0[3]0[4]0[5]0 [6]10[7]0[8]0[9]0[10]0[11]0[12]0[13]0[14]0[15]0[16]0
надо вам с чем-то произвести какие-то операции, пробежались по массиву и получили два адреса (адреса в памяти или индексы массива), затем работаете с этими данными по указателям или индексам массива. если вы создаёте размерности только один раз в самом начале это одно. но если во время работы захотите уменьшить или увеличить размер любого из елементов, придётся дописать ещё пару простенький ф-ий. переменную с инфой о размере массива можете не делать, эту инфу можно хранить в первой ячейке. как вам удобней.
вариант дубовый, но рабочий. без понимания какая у вас задача в общем и без знания с какими объёмами данных будете работать другое сами придумывайте. и +1, контроллер это не настольный комп, даже если докинуть внешней памяти. как минимум это трата тактов на работу с ней.

Re: Динамически изменяемый размер переменной

NEOSoftWare » 15 авг 2012, 21:23

Angel71 писал(а):небольшой объём внутренней памяти при необходимости скрашивается возможностью подключения внешней.
хз, что за зверь такой этот codeavr, есть ли там всякие malloc, free, realoc и прочие. нужна 1 переменная для хранения размерности массива и собственно сам одномерный массив максимальной длины для хранения данных. максимальной - это или необходимый максимум для хранения этих данных, если заранее известно или максимум, что есть в меге с учётом стека и минимизации всяких финтов с рекурсией и прочим. изначально размерность 0. создаём первый элемент, переменной +1. нужно допцустим 5 байт, вот в первую ячейку заносите 5, следующие 5 ячеек собственно данные (можно и инициализировать нулями при желании). теперь допустим нужно создать размеров в 10 байт. создаём второй элемент, опять добавляя +1 к переменной. в 7ю ячейку заносите 10, сл. 10 ячеек будут данные.
n = 2
m содержит такую последовательность байт (на всякий, в скобках адрес) [0]5 [1]0[2]0[3]0[4]0[5]0 [6]10[7]0[8]0[9]0[10]0[11]0[12]0[13]0[14]0[15]0[16]0
надо вам с чем-то произвести какие-то операции, пробежались по массиву и получили два адреса (адреса в памяти или индексы массива), затем работаете с этими данными по указателям или индексам массива. если вы создаёте размерности только один раз в самом начале это одно. но если во время работы захотите уменьшить или увеличить размер любого из елементов, придётся дописать ещё пару простенький ф-ий. переменную с инфой о размере массива можете не делать, эту инфу можно хранить в первой ячейке. как вам удобней.
вариант дубовый, но рабочий. без понимания какая у вас задача в общем и без знания с какими объёмами данных будете работать другое сами придумывайте. и +1, контроллер это не настольный комп, даже если докинуть внешней памяти. как минимум это трата тактов на работу с ней.
у меня в голове такая идея и крутиться, одно но, надо за ранее занять все место под это дело при условии что я не знаю сколько оно будет занимать. в CodeVisionAVR есть либка с функциями malloc, free, realoc, но как с ними работать вообще понять не могу, много теории на http://avr-libc.narod.ru/malloc.html
еще такой вопрос если сделать так:
Код: Выделить всёРазвернуть
eeprom unsigned char i;
unsigned char tmp;
...

void main(void){
...
tmp =30;
while(1){
  i= tmp;
}

...


ячейка памяти под которую выделана переменная i сдохнит? или есть какая то оптимизация у мк на наличие уже записанного такого же значения? (т.е. обязательно использовать if (i != tmp){i=tmp;} перед записью ??)

Re: Динамически изменяемый размер переменной

Angel71 » 15 авг 2012, 22:39

в дубовом примере выше заранее созданый массив легко заменяется на динамический и при необходимости реализуется дефрагментация и изменение размеров каждого элемента. но пардон, лучше забрасывайте этот проект и учите азы. хорошенько разбравшись как работать с памятью и указателями возвращаетесь к проекту. иначе с уровнем дайте мне волшебную ф-ю аля array.resize или setlength вы быстрее лоб расшибёте или в коде накосячите с утечками или фрагментацией памяти, записями в уже где-то зарезервированную память, невозможностью корректного вызова ф-ий, работы прерываний, использования рекурсий и прочего.

Re: Динамически изменяемый размер переменной

ALS » 16 авг 2012, 00:04

Я бы подключил внешнюю 23K256, нарезал на куски по 2к и забивал бы ее и в хвост и в гриву, а не себе голову...

ЗЫ.
А что за данные ? Потому что если писать в лог, напр., температуру, или кол-во посетителей, или любые другие данные с ограниченным диапазоном, то задача-то имеет простейшее решение.

Re: Динамически изменяемый размер переменной

Angel71 » 16 авг 2012, 02:38

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

Re: Динамически изменяемый размер переменной

yozik0ff » 20 авг 2012, 12:04

На avr-ках лучше не использовать динамическую память.
Тоесть, втопку всякие newи delete
Если хотите, то можете их применить, перед этим объявив какнибудь вот так:
Код: Выделить всёРазвернуть
#include <stdlib.h>
void * operator new(size_t size);
void operator delete(void * ptr);


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

Вопрос задан неверно. Размер переменной изменить нельзя. Можно делать массивы разной размерностью. С использованием указателей на эти массивы.
Чтобы решить вашу задачу с буферизацией UART нужно использовать кольцевой список.
Вот примерный код:
Заголовочный файл.
Код: Выделить всёРазвернуть
#pragma once
#include "../devSettings.h"
//---------------------------------------------------------------------------------------




//---------------------------------------------------------------------------------------
#define MAX_CIRCULAR_BUFFER      0x20   //максимальный кольцевой буфер для протокола
//---------------------------------------------------------------------------------------







/* //===================================================================================*
* //                                                                                    *
* // Реализация кольцевого буфера                                          *
* //------------------------------------------------------------------------------------*
*///
class
   AFIFO
{
   public:
      AFIFO();


      bool push_back(const BYTE data);//Запихнем данные в конец очереди
      BYTE pop_front();//Вытащим данные из начала очереди

      void clear();//очистить очередь   
      int count()const; //количество элементов в буфере
      
   private:
   
      BYTE   m_buffer[MAX_CIRCULAR_BUFFER];
      int      m_indexBegin;//указатель на начало очереди
      int      m_indexEnd;//указатель на конец очереди
      int      m_count;//количество элементов

};


Реализация
Код: Выделить всёРазвернуть
#include "devFIFO.h"
//---------------------------------------------------------------------------------------



//---------------------------------------------------------------------------------------







/* //===================================================================================*
* //                                                                                    *
* // Constructor                                                      *
* //------------------------------------------------------------------------------------*
*///
AFIFO :: AFIFO()
   :
   m_indexBegin(0),
   m_indexEnd(0),
   m_count(0)
{
   
}
//---------------------------------------------------------------------------------------









/* //===================================================================================*
* //                                                                                    *
* // очистить очередь                                                   *
* //------------------------------------------------------------------------------------*
*///
void AFIFO :: clear()
{
   m_indexBegin = 0;
   m_indexEnd = 0;
   m_count = 0;
}
//---------------------------------------------------------------------------------------






/* //===================================================================================*
* //                                                                                    *
* // Запихнем данные в конец очереди                                       *
* //------------------------------------------------------------------------------------*
*///
bool AFIFO :: push_back(const BYTE data)
{
   if (m_count < MAX_CIRCULAR_BUFFER)
   {
      m_buffer[m_indexEnd] = data;
      m_indexEnd++;
      m_count++;
      if (m_indexEnd == MAX_CIRCULAR_BUFFER)
      {
         m_indexEnd = 0;
      }
      return true;
   }      
   return false;
}
//---------------------------------------------------------------------------------------




   
   
   
   
/* //===================================================================================*
* //                                                                                    *
* // Вытащим данные из начала очереди                                       *
* //------------------------------------------------------------------------------------*
*///
BYTE AFIFO :: pop_front()
{
   if (m_count > 0)
   {
      BYTE data = m_buffer[m_indexBegin];
      m_buffer[m_indexBegin] = 0;
      m_indexBegin++;
      m_count--;
   
      if (m_indexBegin == MAX_CIRCULAR_BUFFER)
      {
         //вышли за пределы буфера
         m_indexBegin = 0;
      }
      return data;
   }
   //ошибка, нет данных для чтения
   return 0;      
}
//---------------------------------------------------------------------------------------





/* //===================================================================================*
* //                                                                                    *
* // Количество элементов в буфере                                          *
* //------------------------------------------------------------------------------------*
*///
int AFIFO :: count() const
{
   return m_count;
}
//---------------------------------------------------------------------------------------



Использовать можно вот так
Код: Выделить всёРазвернуть
main()
{
    AFIFO bufRead;
    /* заносим данные в обработчке прерывания на приход новых данных
    */
    bufRead.push_back(34);
    bufRead.push_back(12);
    bufRead.push_back(0xFF);
    ////


    /* в галвном цикле/потоке вытаскиваем неспешно пришедшие данные
    */
    int data = bufRead.pop_front();

}


Также, можно объявить две переменные AFIFO, одну для чтения, вторую для записи в UART.


Rambler\'s Top100 Mail.ru counter