Daria 0 5 октября, 2008 Опубликовано 5 октября, 2008 · Жалоба Опять я :) теперь нужен еще буфер - для АЦП. посмотрите, пожалуйста, нормально ли написана функция чтения? :) Та же структура typedef struct CharBuffer { unsigned char* Data; int NData; int cData; int pWrite; int pRead; } CharBuffer; #define sizeADCBufR 100 struct CharBuffer stADCBufR; unsigned char ADCBufR[sizeADCBufR]; stADCBufR.NData = sizeADCBufR; stADCBufR.Data = ADCBufR; BufferReset(&stADCBufR); Функция записи - записывает по байтам два int числа, функции записи и чтения байта описаны выше int WriteADCbuf(CharBuffer* pBuffer, int* data, int size) { if((pBuffer->NData-pBuffer->cData)<2*size+1)return 1; for( int j = 0; j < size; j++) { BufferWrite(pBuffer, (data[j]&0xFF)); BufferWrite(pBuffer, (data[j]>>8)); } return 0; } Чтение в две переменных void ReadADCbuf(CharBuffer* pBuffer, int* data0, int* data1) { unsigned char Dat[4]; BufferRead(pBuffer, &Dat[0]); BufferRead(pBuffer, &Dat[1]); *data0=((Dat[0]&0x00FF)|((Dat[1]<<8)&0xFF00)); BufferRead(pBuffer, &Dat[2]); BufferRead(pBuffer, &Dat[3]); *data1=((Dat[2]&0x00FF)|((Dat[3]<<8)&0xFF00)); } Вызов ReadADCbuf(&stADCBufR, &Vr0, &Vr1) Правильно ли склеиваю? И вообще - что-то с ней, по-моему, не то :) Еще вопрос - как правильно работать с WDT? Я просто останавливаю его при начальной инициализации, и все. Но говорят, что это не правильно, нужно постоянно обращаться к нему, чтобы избежать зависания процессора. Как это делать - обращаться постоянно в цикле for(;;)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 5 октября, 2008 Опубликовано 5 октября, 2008 · Жалоба И еще :) Мне нужно обмениваться с двумя устройствами. Что лучше - использовать второй модуль USART1 или можно просто многопроцессорный формат в USART0? Нужно уже рисовать схему Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 6 октября, 2008 Опубликовано 6 октября, 2008 · Жалоба И еще :) Мне нужно обмениваться с двумя устройствами. Обычно при обмене кто-то главный (master), а кто-то подчиненный (slave). Как старшинство распределено среди этого трио? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 6 октября, 2008 Опубликовано 6 октября, 2008 · Жалоба Обычно при обмене кто-то главный (master), а кто-то подчиненный (slave). Как старшинство распределено среди этого трио? одно устройство принимает команды с компьютера(от оператора) и на основании их руководит вторым устройством(передает команды и принимает ответные данные). :) Как-то так Вопрос про функцию снимается, а вот про WDT? Что, если перезапускать его в прерываниях таймера через каждые сколько-то мс? Как вообще обычно им пользуются? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 6 октября, 2008 Опубликовано 6 октября, 2008 · Жалоба одно устройство принимает команды с компьютера(от оператора) и на основании их руководит вторым устройством(передает команды и принимает ответные данные). :) Как-то такРаз есть второй аппаратный UART, то грешнО его не использовать. а вот про WDT? Что, если перезапускать его в прерываниях таймера через каждые сколько-то мс? Как вообще обычно им пользуются?Лично я его обычно использую как таймер системных тиков, т.к. у него приоритет прерывания один из самых высоких :) Если же вас интересует теория, то где бы вы не сбрасывали WatchDog он должен сбрасываться только после анализа нескольких флагов, которые устанавливаются в разных ответственных местах программы. Вы можете сбрасывать WDT в прерывании таймера, но не просто по факту попадания в это прерывания, а только если выполняются все условия "попадания" в различные другие части программы. В те, куда программный код обязательно должен привести в промежутках между сбросом WDT. Кстати, от "защелкивания" или экстремальных случаев воздействия статики на MSP430 внутренний WatchDog не спасает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Лично я его обычно использую как таймер системных тиков, т.к. у него приоритет прерывания один из самых высоких :) Если же вас интересует теория, то где бы вы не сбрасывали WatchDog он должен сбрасываться только после анализа нескольких флагов, которые устанавливаются в разных ответственных местах программы. Вы можете сбрасывать WDT в прерывании таймера, но не просто по факту попадания в это прерывания, а только если выполняются все условия "попадания" в различные другие части программы. В те, куда программный код обязательно должен привести в промежутках между сбросом WDT. Кстати, от "защелкивания" или экстремальных случаев воздействия статики на MSP430 внутренний WatchDog не спасает. Ага, а я вот как раз хотела сначала настроить в сторожевом режиме, а потом просто сбрасывать WDTCNTCL в прерываниях таймера :) Не все так просто... То есть, вы не используете WDT в сторожевом режиме, и ничего страшного не случается? :) И вот еще более важные вопросы - У меня куча массивов, если объявлять их в main, они начинают забивать стек, если как глобальные - то ведь память, отведенная под глобальные константы ограничена. Как быть? Можно ли как-то программно увеличить размер стека? Нужно либо увеличивать стек, либо как-то хитро объявлять все эти массивы... подскажите. и не ругайтесь, если опять сморозила глупость :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Ага, а я вот как раз хотела сначала настроить в сторожевом режиме, а потом просто сбрасывать WDTCNTCL в прерываниях таймера :) Не все так просто... То есть, вы не используете WDT в сторожевом режиме, и ничего страшного не случается? :) А что там должно "страшного" случиться? :cranky: Режим интервального таймера для WDT является штатным и документированным. Если вы сомневаетесь в помехоустойчивости, то вообще-то помехоустойчивость устройства в бОльшей степени определяется конструктивными и схемотехническими (трассировка платы, расположение и подключение внешних и внутренних цепей и т.п.) особенностями устройства, а не использованием WatchDog ;) И вот еще более важные вопросы - У меня куча массивов, если объявлять их в main, они начинают забивать стек, если как глобальные - то ведь память, отведенная под глобальные константы ограничена. Как быть? Можно ли как-то программно увеличить размер стека? Нужно либо увеличивать стек, либо как-то хитро объявлять все эти массивы... подскажите. и не ругайтесь, если опять сморозила глупость :) В Plain C и ANSI C используются четыре типа переменных: 1. register (регистровые), размещаются в регистрах (хотя компиляторы чаще всего плюют на это указание). Область "видимости" текущая функция/контейнер. При выходе из функции/контейнера не сохраняются. 2. auto (автоматические или локальные), размещаются на стеке (или в регистрах, опять же по прихоти компилятора). Область "видимости" текущая функция, контейнер. При выходе из функции/контейнера не сохраняются. 3. global (глобальные), размещаются на постоянной основе в ОЗУ, в области данных. Область видимости весь текущий модуль. А объявленные с квалификатором extern могут быть "видны" в любом другом модуле проекта. 4. static (статические), размещаются на постоянной основе в ОЗУ, в области данных. Область "видимости" текущая функция (если объявление внутри функции) или текущий модуль (если объявление как глобальной снаружи какой-либо функции). При выходе из функции сохраняются. Но статические переменные не могут быть использованы в других модулях проекта и квалификатор extern к ним неприменим. В IAR для MSP430 принято, что область данных (глобальных и статических переменных) располагается "снизу" ОЗУ, а стек "сверху" и "растет" ей навстречу. Для того, чтобы хоть как-то контролировать стек в Plain C, вы можете сами организовать "кучу" (HEAP). Для этого создайте большой глобальный массив и располагайте свои временные "массивчики" внутри его. Но для этого нужно будет научиться (если еще не научились) пользоваться указателями, обязательно контролируя выходы их (указателей) за границы выделенных "массивчиков" и глобального массива кучи. А вообще в map-файле, который можно генерировать с помощью конфигурирования опций IAR, указан размер стека при использовании каждой функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 7 октября, 2008 Опубликовано 7 октября, 2008 (изменено) · Жалоба В IAR для MSP430 принято, что область данных (глобальных и статических переменных) располагается "снизу" ОЗУ, а стек "сверху" и "растет" ей навстречу. Для того, чтобы хоть как-то контролировать стек в Plain C, вы можете сами организовать "кучу" (HEAP). Для этого создайте большой глобальный массив и располагайте свои временные "массивчики" внутри его. Но для этого нужно будет научиться (если еще не научились) пользоваться указателями, обязательно контролируя выходы их (указателей) за границы выделенных "массивчиков" и глобального массива кучи. А вообще в map-файле, который можно генерировать с помощью конфигурирования опций IAR, указан размер стека при использовании каждой функции. Все же пока не ясно :05: Есть массивы, которые объявлены в main, они висят в стеке, потом при вызове какой-нибудь функции, создаются еще локальные - и забивают в этот момент стек. я вижу размер стека, вижу, что заполнен, но как же быть, если массив нужен? Объявить большой глобальный - да, но если не хватит памяти, отведенной под глобальные переменные? Кстати, в руководстве, которое вы часто поминаете, сказано, что при начальной инициализации, нужно инициализировать указатель стека(указав вершину ОЗУ). Как записывается инициализация SP? :) Изменено 7 октября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Все же пока не ясно :05: Есть массивы, которые объявлены в main, они висят в стеке, потом при вызове какой-нибудь функции, создаются еще локальные - и забивают в этот момент стек.Пример из программы можете привести, где по-вашему создаются локальные копии массивов локальных переменных? я вижу размер стека, вижу, что заполнен, но как же быть, если массив нужен? Объявить большой глобальный - да, но если не хватит памяти, отведенной под глобальные переменные?Либо вы не совсем аккуратно программируете, либо выбранный кристалл (размер имеющегося у него ОЗУ) не соответствует вашей задаче. Кстати, в руководстве, которое вы часто поминаете, сказано, что при начальной инициализации, нужно инициализировать указатель стека(указав вершину ОЗУ). Как записывается инициализация SP? :)Поскольку вы программируете на Си, а не на ассемблере, то задачей инициализации указателя стека и очисткой/инициализацией глобальных и статических переменных, находящихся в сегменте DATA_Z, занимается сам компилятор. Все это делается в процедуре StartUp, которая выполняется ДО вызова функции main. Надеюсь вы в курсе, что main это тоже функция и у нее есть пролог и эпилог, как и у подавляющего большинства других функций? Вот если бы вы писали программу полностью на ASM, то инициализацию указателя стека и инициализацию/очистку глобальных переменных пришлось бы писать тоже вам. Вручную ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 10 октября, 2008 Опубликовано 10 октября, 2008 · Жалоба Либо вы не совсем аккуратно программируете, либо выбранный кристалл (размер имеющегося у него ОЗУ) не соответствует вашей задаче. Однозначно, первое :) ОЗУ = 2 КВ. Но я поняла, в чем дело - это не стек забивался, а размер stack heap был по умолчанию задан 50 байт. :) Я не тормоз, я медленный газ Но теперь все вроде в порядке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 14 октября, 2008 Опубликовано 14 октября, 2008 (изменено) · Жалоба Опять я :) Такой вопрос - такое впечатление, что мне может не хватить размера ОЗУ - вычислений оказывается надо делать много, куча массивов данных. Как быть - возможен ли такой вариант - писать что-то (например, массивы ко-тов фильтров) во flash, чтобы они не висели в стеке? Еще про WDT :) Что, если в программе будет какой-то невыявленный при испытаниях глюк, который выявится уже в процессе использования? Проц зависнет где-нибудь в прерывании... и будет висеть. А WDT это дело предотвратит. Так или не так? :) Изменено 14 октября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 14 октября, 2008 Опубликовано 14 октября, 2008 · Жалоба Как быть - возможен ли такой вариант - писать что-то (например, массивы ко-тов фильтров) во flash, чтобы они не висели в стеке?Возможен. Объявляйте их с квалификатором const. Но при этом они становятся неизменяемыми. Еще про WDT :) Что, если в программе будет какой-то невыявленный при испытаниях глюк, который выявится уже в процессе использования? Проц зависнет где-нибудь в прерывании... и будет висеть. А WDT это дело предотвратит. Так или не так? :)Так. Именно для этого его и придумали. Надо лишь Придумать алгоритм его периодического сбрасывания, чтобы он не сбросил вашу штатно работающую программу и чтобы при подвисании одной части он не продолжал успешно сбрасываться в другой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 18 октября, 2008 Опубликовано 18 октября, 2008 (изменено) · Жалоба Такой вопрос. Почему-то не получается объявить фукнцию, работающую с двумерным массивом, размер которого можно бы было передавать как формальный параметр. На function(float а[][]) ругается, а если писать function (float** a), а потом передавать конкретный массив float m[5][5] как function(m), то функция вообще не выполняется, хотя никаких ошибок не пишет : :07: Как это вообще делается? :05: И еще - есть уравнение четвертой степени ax^4+bx^3+cx^2+dx+e=0 Как бы можно было реализовать его решение, если коэффициенты a,b,c,d,e будут вычислены по данным АЦП? Это вообще возможно на таком кристалле? Ну, есть методы решения уравнений в общем виде - метод деления отрезка пополам, например. Но во-первых, нужно знать область, на которой функция меняет знак, во-вторых искать пределы последовательностей :07: Если вдруг кто-нибудь когда-нибудь делал, подскажите. А про массив - обязательно подскажите! Изменено 18 октября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 18 октября, 2008 Опубликовано 18 октября, 2008 · Жалоба Такой вопрос. Почему-то не получается объявить фукнцию, работающую с двумерным массивом, размер которого можно бы было передавать как формальный параметр. На function(float а[][]) ругается, а если писать function (float** a), а потом передавать конкретный массив float m[5][5] как function(m), то функция вообще не выполняется, хотя никаких ошибок не пишет : :07: Как это вообще делается? :05:Вы поймите, что многомерные массивы это лишь такая человеческая абстракция. В памяти МК многомерные массивы все равно представляются в виде одномерных участков оперативной памяти. У вас многомерный массив переменных типа float. Единичным элементом массива является переменная типа float. Так вот и передавайте в функцию указатель на переменную типа float. Объявление функции void func (float *ptr); Вызов функции func(&a[0][0]); либо float *ptr=&a[0][0]; func(ptr); Если же вы хотите, чтобы в результате выполнения функции передаваемый указатель тоже изменился, только тогда нужно передавать указатель на указатель. void func (float **pFptr) { float *ptr=pFptr; ... *pFptr=ptr; } вызов функции float *ptr=&a[0][0]; func(&ptr); Насчет второй части вопроса, увы! не могу подсказать :( Не настолько я силен в математике :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 6 19 октября, 2008 Опубликовано 19 октября, 2008 · Жалоба Начиная с 99 года в С стало возможно описывать массивы с переменной длинной, IAR этот стандарт поддерживает. Кстати, в Фортране подобное было с самого начала, не прошло и полвека. :) Ниже примеры из текста стандарта ISO/IEC 9899:1999 EXAMPLE 3 The following declarations demonstrate the compatibility rules for variably modified types. extern int n; extern int m; void fcompat(void) { int a[n][6][m]; int (*p)[4][n+1]; int c[n][n][6][m]; int (*r)[n][n][n+1]; p = a; // invalid: not compatible because 4 != 6 r = c; // compatible, but defined behavior only if // n == 6 and m == n+1 } EXAMPLE 4 All declarations of variably modified (VM) types have to be at either block scope or function prototype scope. Array objects declared with the static or extern storage-class specifier cannot have a variable length array (VLA) type. However, an object declared with the static storageclass specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with a VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions. extern int n; int A[n]; // invalid: file scope VLA extern int (*p2)[n]; // invalid: file scope VM int B[100]; // valid: file scope but not VM void fvla(int m, int C[m][m]); // valid: VLA with prototype scope void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA { typedef int VLA[m][m]; // valid: block scope typedef VLA struct tag { int (*y)[n]; // invalid: y not ordinary identifier int z[n]; // invalid: z not ordinary identifier }; int D[m]; // valid: auto VLA static int E[m]; // invalid: static block scope VLA extern int F[m]; // invalid: F has linkage and is VLA int (*s)[m]; // valid: auto pointer to VLA extern int (*r)[m]; // invalid: r has linkage and points to VLA static int (*q)[m] = &B; // valid: q is a static block pointer to VLA } Примерно так должно работать (не проверял): float func( int i; int j; float a[i][j] ) { float s = 0.0; for( int ii = 0; ii < i; ii++) for( int jj = 0; jj < j; jj++) s += a[ii][jj]; return s; } float m[5][5]; float mm[25][3]; func( 5, 5, m ); func( sizeof(mm)/sizeof(mm[0]), sizeof(mm[0])/sizeof(mm[0][0]), mm ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться