при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
В том что программа написана в стиле КА, вот я и хочу отслеживать КА дошёл по последнего состояния или нет. Ну и смотреть как будет осуществляться доступ из нескольких КА к одному ресурсу.ARV писал(а):что мешает сделать ОДИН выход из функции, как того требует модульный стиль программирования?
Код: Выделить всё
switch(state){
case STATE_1:
state = STATE_5;
break;
case STATE_2:
state = STATE_1;
break;
...
default:
state = STATE_0;
}
debug_output(state);
Код: Выделить всё
unsigned char* Mas_PORTx[MAX_PWM]={&PORTB,&PORTB,&PORTD,&PORTC};
unsigned char* Mas_DDRx[MAX_PWM]={&DDRB,&DDRB,&DDRD,&DDRC};
unsigned char Mas_Pin[MAX_PWM]={0,1,2,3};
for(i=0;i<MAX_PWM;i++){
ClearBit(*Mas_PORTx[i],Mas_Pin[i]);
SetBit(*Mas_DDRx[i],Mas_Pin[i]);
}
Код: Выделить всё
//настройки
#define F_CPU 1000000
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
uint16_t AdcGet (void); //объявление
uint16_t AdcBuf [16]; //буфер накопитель
//Главный файл
int main (void)
{
//инит ADC
ADMUX = (0<<REFS1)| (1<<REFS0)| //в кач-ве ИОН питание контроллера
(0<<MUX3)| (0<<MUX2)| (0<<MUX1)| (0<<MUX0)| //канал ADC0
(0<<ADLAR); //выровнять вправо
ADCSRA = (1<<ADEN)| //вкл АЦП
(1<<ADFR)| //FREE RUNNING
(1<<ADIE)| //прерывание по завершению преобразования
(1<<ADPS2)| (1<<ADPS1)| (1<<ADPS0); //предделитель
ADCSR |= (1<<ADSC); //запустить преобразование
//настройка светика
DDRB |= (1<<6);
//главный цикл
sei ();
while(1){
uint16_t Adc = AdcGet();
//_delay_us (1);
if (Adc < 224){
PORTB |= (1<<6); //если ниже порога - включаем светик
while (1){
Adc = AdcGet();
//_delay_us (1);
if (Adc > 224) break;
}
PORTB &= ~(1<<6); //если выше порога - выключаем светик
}
}
}
//функция чтения усредненных данных ADC
uint16_t AdcGet (void)
{
uint16_t data = 0;
for (uint8_t i=0; i<16; i++)
data += AdcBuf [i];
return (data / 16);
}
//функция циклического опроса ADC
ISR (ADC_vect)
{
sei ();
static uint8_t counter;
AdcBuf [counter] = ADC;
if (++counter >= 16)
counter = 0;
}Кажется вы правы ))))))))))))Аlex писал(а):Первым, что бросается в глаза - отсутствие атомарного доступа к данным буфера.
Видимо, с задержками, как то подгоняется к нормальному доступу.
Код: Выделить всё
//функция чтения усредненных данных ADC
uint16_t AdcGet (void)
{
uint16_t data = 0;
for (uint8_t i=0; i<16; i++){
cli ();
data += AdcBuf [i];
sei ();
}
return (data / 16);
}
маловероятно (хотя и не исключено полностью), что подсчет суммы буфера потребует времени больше, чем проходит между двумя циклическими преобразованиями АЦП, ведь АЦП обычно работает на довольно низкой скорости.Аlex писал(а):Лучше применить атомарный доступ ко всему буферу целиком, а не только отдельно к байтам в слове. Т.к. любая ячейка, как и байт в слове, может измениться в любой момент в прерывании, что может привести к неправильным расчётам.
Вообще-то, буфер - кольцевой, то есть, может наступить себе на радиоя*ца только в результате алгоритмической ошибки.ARV писал(а):за время суммирования в буфере может обновиться максимум 1 ячейка, что не приведет к погрешности при принятом способе усреднения, ...
Код: Выделить всё
typedef struct _tag_Node
{
long int nodeId;
Node *next;
Node *prev;
void *ptr;
}Node, *pNode;
Код: Выделить всё
////////////////////////////////////////////////////////////////////////////
QLIST::~QLIST()
{ // Удаление всех записей по уничтожению объекта (деструктор класса QLIST)
NdPoint = NdFirst; // Присваиваем рабочему указателю адрес первого элемента
while(NdPoint != 0) // Цикл не выполнит ни одну итерацию, если список был пустым и прервется по удалению последнего элемента
{
NdFirst = NdPoint->next; // Присваиваем в качестве первого элемента следующий.
//Если там NULL, то он далее скопируется NdPoint и цикл завершится.
delete NdPoint; // Удаляем текущий
NdPoint = NdFirst; // Присваиваем первый элемент в качестве текущего.
}
}
Код: Выделить всё
delete childList;
Код: Выделить всё
Widget::~Widget()
{
Widget *pC = 0;
childsList.pointer_begin();
while(childsList.get_data_next((void**)&pC) == true)
{
delete pC;
}
}
Конструктор не обязателен - но инициализация лишней не бывает - а то позабытый случайно на стеке объект бабахнет на мусорном адресе при неявной деструкции.DX168B писал(а):Код: Выделить всё
typedef struct _tag_Node { _tag_Node() : nodeId(-1), next(NULL), prev(NULL), ptr(NULL) { } ~_tag_Node() { delete ptr; } long int nodeId; Node *next; Node *prev; void *ptr; } Node, *pNode;
Заведите базовый объект для всех используемых типов - а потом вдарьте по ним полиморфизмом!DX168B писал(а):Проблема в том, что под void указателем может скрываться что угодно.
Либо взять уже готовый стандартный std::list либо изобрести такой-же my_list вручную.DX168B писал(а):Только с условием: один список - один тип данных для всех нодов данного списка.
Я бы сказал деструктор объекта childList вызывается неявно [как и для всех не-динамических полей класса] в ходе исполнения деструктора самого класса. И да, никакой неправильности в его не-динамичности нет - место будет выделено в области данных самого объекта класса - т.е. вместо двух объектов в куче (класс и список) вы поимеете один объект. Когда жизнь заставит разобираться с операторами присвоения объектов класса - динамические поля тоже потребуют к себе несколько завышенного внимания, чтобы впредь стараться обходиться без них.DX168B писал(а):После выхода из деструктора виджета вызывается деструктор объекта childList автоматически.
Хотя наверное это неправильно и в конструкторе класса Widget надо бы создать объект childList оператором new.
Я в курсе. Поля структуры у меня все равно заполняются сразу же после создания.Конструктор не обязателен - но инициализация лишней не бывает - а то позабытый случайно на стеке объект бабахнет на мусорном адресе при неявной деструкции.
Код: Выделить всё
//////////////////////////////////////////////////////////////////
// GUI wiget base class (inherited from GuiObject)
Widget::Widget()
{
drawContext.xPos = 0;
drawContext.yPos = 0;
drawContext.zPos = 0;
drawContext.xSize = 0;
drawContext.ySize = 0;
drawContext.zSize = 0;
drawContext.objectID = 0;
drawContext.extContext = 0;
drawContext.extContextType = DRAW_EXTENDED_CONTEXT_TYPE_NONE;
enableFlag = true;
focusFlag = true;
renderFunc = 0;
eventCallBack = 0;
}
Подумываю над этим. Что-то придется переделать.Заведите базовый объект для всех используемых типов - а потом вдарьте по ним полиморфизмом!
Ну, свой лист я создавал не просто так. Дело в том, что по этому списку производится рендеринг, по нему же идет переборЛибо взять уже готовый стандартный std::list либо изобрести такой-же my_list вручную.
Да уж стараюсь поменьше плодить динамических сущностей. Ибо это бьет как по надежности, так и по производительности.Я бы сказал деструктор объекта childList вызывается неявно [как и для всех не-динамических полей класса] в ходе исполнения деструктора самого класса. И да, никакой неправильности в его не-динамичности нет - место будет выделено в области данных самого объекта класса - т.е. вместо двух объектов в куче (класс и список) вы поимеете один объект. Когда жизнь заставит разобираться с операторами присвоения объектов класса - динамические поля тоже потребуют к себе несколько завышенного внимания, чтобы впредь стараться обходиться без них.
Код: Выделить всё
~_tag_Node() { delete ptr; } Ну т.е. он ещё и сортируется время от времени? В STL, кстати, алгоритмы есть разные - в т.ч. с заданием критериев обработки. Пока непонятно в чем преимущество самопального списка.DX168B писал(а):Рендеринг объектов должен производиться в особом порядке из-за особенностей OpenGL.
И этот порядок динамически изменяется под действием кучи параметров.
Вызов деструктора для не-динамических объектов - обязанность компилятора, либо по выходу из блока в котором он был объявлен, либо по уничтожению объекта-владельца как в описываемом случае.DX168B писал(а):Просто небыло понятно про неявный вызов деструктора childList. Это типа стандарт, или особенность одного компилятора?
Просто сейчас это пишется в Visual Studio 2010, потом будет переезжать на GCC, когда будет портироваться под Linux.
В данном случае никакой информации об объекте нету - и даже если скомпилирует без предупреждений-ошибок - всё, скорее всего сведётся к вызову free для освобождения указуемого блока памяти. Если же указывается объект - то будет исполнен его деструктор - даже если тип этого указателя - абстрактный базовый. Для удаления массивов выделенных посредством new[] хорошо не забывать использовать delete[] - ибо деструкторы всех элементов жаждут исполнения. А для строк есть std::string.DX168B писал(а):А корректно ли поведет себя оператор delete в этом случае?Код: Выделить всё
~_tag_Node() { delete ptr; }
Просто удаление объектов происходит одним способом, а удаление, допустим, строк (массивов) другим способом.
Минимализм. Пробовал различные варианты. При большом количестве объектов жутко проседает FPS.Пока непонятно в чем преимущество самопального списка.![]()
Про использование иерархии классов для хранения разных наборов данных уже говорили выше, а чтобы корректно отрабатывал delete, нужно объявить деструктор базового класса виртуальным. В этом случае деструктор базового класса автоматически вызывается после деструктора производного класса.DX168B писал(а):А корректно ли поведет себя оператор delete в этом случае?