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

 
 
17 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> MSP430 - снова вопросы от чайника, Вопросы от чайника про MSP и магнитный компас
Daria
сообщение Jul 23 2008, 19:17
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



smile.gif Здравствуйте. Кто читал предыдущую мою тему "MSP430 - вопросы от чайника", тот поймет - это снова я biggrin.gif Тему закрыли, слишком долго висела. А вопрсов все больше. smile.gif
Если кому-то вдруг окажется не влом разбираться, то
Вот кусок проги:
int flag;//глобальные переменные
int cindex;
испульзуемые функции(write_flash - пишет число во flash, read_flash - считывает)
void write_flash(float* value, float *addr)
{ while(FCTL1 & BUSY);
_BIC_SR(GIE);
FCTL1 = FWKEY + ERASE;
FCTL3 = FWKEY;
*addr = 0;

while(FCTL1 & BUSY);
FCTL1 = FWKEY + WRT; for (int i=0;i<=3;i++)
{ *addr = value[i];
addr++;
}

_BIS_SR(GIE);
while(FCTL1 & BUSY);
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
}

void read_flash(float* addr, float* pfO)
{
for (int i=0;i<=3;i++)
{ pfO[i]=*addr;
addr++;
}
}
Чего хочу сделать - Если присылаю 0, то должны считаться два показания с выводов P6.3 и P6.4, присылается 0хАА - т.е. "считалось", записываются первые элементы двух массивоы данных.
Когда набирается по четыре элемента, индекс сбрасывается
Если присылаю 0xFF, то должна выполнится функция calibrovka_hmc, если она выполняется неверно, то присылается 0хСС, иначе из flash считывается и присылается вычисленная с помощью этой функции константа.
Внутри функции main
ADC12CTL0 = ADC12ON + REFON + SHT0_8; //настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;

float temp[4];
flag=0;
cindex=0;
for(;;)
{
for(delay = 0; delay <20000; delay++);
if( flag==0 )
{send_int(0x0);
}
if( flag==1 )
{

if (calibrovka_hmc(CVx, CVy, temp)==0)//calibrovka_hmc - имеет параметрами два массива и вычисляет четыре константы(нужные для калибровки устройства)

{
send_int(0xCC);
flag=0;
}
else
{
float pfO[4];
read_flash((float*)0x1000,pfO);
r=(int)(pfO[0]+0.5);
send_int®;
flag=0;
}

flag=4;
}

if (flag==2)
{
ADC12CTL0 |=ADC12SC + ENC; CVx[cindex] = ADC12MEM3; CVy[cindex] = ADC12MEM4;
ADC12CTL0 &= ENC;
cindex++;
send_int(0xAA);
flag=0;
}

if (cindex>3)
cindex=0;
}
}
#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx ( void)
{
if( RXBUF0==0xFF)
flag = 1;
if (RXBUF0==0x0)
flag = 2;
}
В ЧЕМ ПРОБЛЕМА:
Перед выполнением калибровки присылаю элементы массива, полученного при считывании показаний с выводов, - оказывается, что в массив записываются по два-три раза одно значение, хотя этого не может быть. Соответственно, из-за этого не работает и все остальное crying.gif
Может, неправильно настроен АЦП? Или в чем может быть дело?
И, если кому-то вдруг не влом разбираться - функции записи во flash и чтения flash - можно ли сделать как-то поумнее?
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 23 2008, 22:03
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Некоторое (продолжительное) время не заглядывал в форум, а когда заглянул оказалось, что вашу тему прикрыли. cranky.gif
По поводу Flash.
Проверять готовность к записи во Flash (бит BUSY) при выполнении программы записи прямо из Flash нет необходимости. Вот такая вот продвинутая технология у MSP430 smile.gif Почему так, объяснять еще раз не буду. Читайте внимательно User's Manual. Проверка готовности нужна только в том случае, если ваша функция записи исполняется из ОЗУ (SRAM), а не из Flash.
Запись во внутреннюю Flash MSP430 может производится 16-и разрядными словами и/или байтами. float имеет размерность 32 бита, т.е. 2 слова/4 байта. Так что, для записи переменной float нужно как минимум две команды записи 16-и битных слов или четыре команды записи байта. У вас указатели value и addr указывают на тип float. Поэтому команды типа addr++; увеличивают значение такого указателя на 4 байта и во Flash пишется какая-то фигня. Пишите тогда уж пословно, делая явное приведение типа к 16-и битному целому.
Код
for (int i=0; i<(4*2); i++) // здесь я явно выделил удвоение числа элементов записи
((unsigned short *)addr)[i] = ((unsigned short *)value)[i];

Назначение функции чтения из Flash я вообще не очень понимаю. У MSP430 фон-Неймановская архитектура с общим адресным пространством для команд и данных. Встроенного EEPROM тоже нет. Так что выделять копирование в отдельную функцию (если только она не вызывается несколько раз) я не вижу смысла. Да и ее тоже можно оптимизировать на одну команду (выкинув addr++; ), если в теле цикла писать
Код
pfO[i]=addr[i];

Насчет всего остального.
Может у меня сложилось неверное впечатление, но похоже вы не осознаете, что такое синхронные и асинхронные события. Просто не владеете таким уровнем абстракций. Попробую объяснить на бытовом примере.
Вы когда-нибудь видели как подъемный кран работает? Внизу на земле стоит стропальщик, который крепит к крюку крана груз, а наверху в кабине крана сидит крановщик, который управляет движением крюка, стрелы и платформы крана. Причем крановщик не сам-по-себе управляет, а подчиняется управляющим командам стропальщика. Только после того как груз
- прицеплен,
- надежность крепления проверена,
- стропальщик подал команду "вира!"
крановщик включает двигатель, приводящий к движению крюка и стрелы крана. До подачи команды "вира!" крановщик просто ждет готовности груза.
У вас в системе присутствуют асинхронные процессы (измерение АЦП, прием/передача UART), а вы работаете с ними как Бог на душу положит. sad.gif Стропальщик убил бы просто такого крановщика, если бы остался жив после его несанкционированных действий. wink.gif
Эта иллюстрация синхронных действий. Для иллюстрации же асинхронных процессов к картине работы башенного крана нужно добавить несколько КАМАЗов с кирпичем, которые приезжают на стройку асинхронно работе крана, когда у них получится, и сваливают кирпич в общую кучу. Которую потом стропальщик с крановщиком общими синхронными действиями перемещают на строящийся уровень дома smile.gif
Эта моя пространная тирада относится в частности к строке
Цитата
ADC12CTL0 |=ADC12SC + ENC; CVx[cindex] = ADC12MEM3; CVy[cindex] = ADC12MEM4;

Где вы запускаете преобразование АЦП и тут же, не дожидаясь окончания выполнения преобразования, считываете результаты оцифровки непонятно чего. Раз вы не используете прерывание от АЦП, ну подождите для приличия установки флага готовности что ли laughing.gif
Код
ADC12CTL0 |=ADC12SC|ENC;
while ((ADC12IFG&(1<<3))!=0);
CVx[cindex]=ADCMEM3;
while ((ADC12IFG&(1<<4))!=0);
CVy[cindex] = ADC12MEM4;

То же самое относится к модификации флага в прерывании UART. Если вы посылаете последовательности из двух команд 0xFF и 0x00, и снова 0xFF и 0x00, но не успели считать значение какого-то флага, то его значение потеряется и вы получите дублирование команды 0xFF или 0x00. Потому, что прием через UART асинхронен выполнению основного тела программы, где эти флаги анализируются. Для того чтобы команды, принятые через UART не терялись, их нужно буферизировать, т.е. складывать в некий массив из которого в основном теле программы они будут извлекаться.
Буферы бывают линейные (типа FIFO) и циклические. По-моему для вашего случая больше подходит циклический буфер. Пример.
Код
#define UART_MAXBUFSIZE 8  //здесь задается размер выделяемого UART буфера
struct cbuf
{ unsigned char *pBuf;  //указатель на начало буфера
  unsigned int rIdx;   //индекс для чтения элемента из буфера
  unsigned int wIdx;  //индекс для записи элемента в буфер
  unsigned int cntr;  //счетчик общего количества элементов в буфере, чтобы знать о его заполнении
} cbuf;
unsigned char uartBuf[UART_MAXBUFSIZE]; // собственно сам буфер UART


где-то в начале программы нужно инициализировать структуру этого буфера
Код
...
cbuf.pBuf=&uartBuf[0];
cbuf.rIdx=0;
cbuf.wIdx=0;
cbuf.cntr=0;
...

В прерывании от приемника UART запись в буфер
Код
#pragma vector=UART0RX_VECTOR
__interrupt void usart0_rx ( void)
{ if (cbuf.cntr<UART_MAXBUFSIZE)
  { cbuf.pBuf[cbuf.wIdx]=U0RXBUF;
    if (cbuf.wIdx<(UART_MAXBUFSIZE-1))
      cbuf.wIdx++;
    else
      cbuf.wIdx=0;
    cbuf.cntr++;
  }
}

В теле программы считывание из буфера. Для атомарности доступа к буферу на время доступа к нему временно запрещаем прерывание от приемника UART
Код
...
if (cbuf.cntr>0)
{ IE1&=~URXIE0;
  uCmd=cbuf.pBuf[cbuf.rIdx];
  cBuf.cntr--;
  IE1|=URXIE0;
  if (cbuf.rIdx<(UART_MAXBUFSIZE-1))
    cbuf.rIdx++;
  else
    cbuf.rIdx=0;
}
// дальше значение переменной uCmd можно использовать как текущую команду, полученную через UART
...
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 24 2008, 19:29
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Ага, все же заглянули smile.gif спасибо за комментарии и критику, все подробно и пространно. smile.gif
По поводу АЦП я уже сама доперла, установку флагов жду, режим использую последовательный, и бит MSC ставлю biggrin.gif Теперь работает. По поводу read_flash - ну да, но это так, для понта отдельная функция smile.gif
А по поводу write_flash - хм. но она работает. я проверяла, во flash пишется не фигня smile.gif может это мне просто везет? biggrin.gif
Про буфер - спасибо, попробую.
Вообще спасибо, что не забыли smile.gif
Go to the top of the page
 
+Quote Post
=DS=
сообщение Jul 25 2008, 03:03
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 54
Регистрация: 25-09-07
Пользователь №: 30 836



Цитата(Daria @ Jul 24 2008, 23:29) *
А по поводу write_flash - хм. но она работает. я проверяла, во flash пишется не фигня smile.gif может это мне просто везет?


Пока везет. В данном случае строка:

*addr = value[i];
скорее всего, транслируется компилятором как

MOV.W @R12+, 0(R13)
MOV.W @R12+, 2(R13)


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

*addr = 0;

транслируется в

MOV.W #0x0, 0(R13)
MOV.W #0x0, 2(R13)


что два раза подряд вызовет стирание сегмента, причем без пауз между ними. В лучшем случае это вызовет удвоенный износ флешки, в худшем - неизвестно (поскольку до подобных действий наверняка еще никто не додумался smile.gif )
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 25 2008, 18:27
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(=DS= @ Jul 25 2008, 07:03) *
*addr = 0;

транслируется в

MOV.W #0x0, 0(R13)
MOV.W #0x0, 2(R13)


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

sad.gif а как тогда написать? Такая строка была в примере, который я скачала с ИАРовского сайта, - "фиктивная запись". Как тогда написать фиктивную запись ?smile.gif
И вот еще ВОПРОС- понимаю, что, наверное, глупый, но -
Когда гружу прогу с помощью IAR Kickstart - работает нормально, считает четко все - я проверяла. Но так как код уже превышает 4кБ, гружу с помощью полной версии - на COM приходит полная ересь. С чем это может быть связано? Код такой же - один в один.
Я думала, может дело в доступе к библиотекам, но не ругается же на код, на #include <math.h>, работает, считает, пишет... только фигню 05.gif
Вот. Не ругайтесь! - уж такая я глупая biggrin.gif
Вот сама функция, она принимает два массива и на их основании вычисляет и пишет во flash 4 четыре константы
int calibrovka_hmc( float* V1, float* V2, float* calibr)
{

float x[4], a[3][3],d[4];
float Ox,k,Oy,kx,ky;
for (int i=0;i<4;i++)
{ a[i][0]=2*(V1[i]-V1[i+1]);
a[i][1]=2*(V2[i]-V2[i+1]);
a[i][2]= -((V2[i])*(V2[i])-(V2[i+1])*(V2[i+1]));
a[i][3]= ((V1[i])*(V1[i])-(V1[i+1])*(V1[i+1]));
d[i]=((V1[i])*(V1[i])-(V1[i+1])*(V1[i+1]));
}

if (gauss(x,a,d,3)==0) return 0;
else
{
Ox=x[0];
k=x[2];
if (x[2]!=0) Oy=x[1]/x[2];
else Oy=0;
}
kx=sqrt((V1[3]-Ox)*(V1[3]-Ox)+k*(V2[3]-Oy)*(V2[3]-Oy));
ky=sqrt((kx)*(kx)/k);
calibr[0]=Ox;
calibr[1]=Oy;
calibr[2]=kx;
calibr[3]=ky;
write_flash( calibr, (float*) 0x1080);
return 1;
}

gauss( ) - решение системы методом Гаусса, она точно работает, не буду приводить - к тому же вряд ли кому-то будет охота в ней разбираться smile.gif
Такие вопросы laughing.gif

Сообщение отредактировал Daria - Jul 25 2008, 18:31
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 25 2008, 19:47
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jul 26 2008, 00:27) *
sad.gif а как тогда написать? Такая строка была в примере, который я скачала с ИАРовского сайта, - "фиктивная запись". Как тогда написать фиктивную запись ?smile.gif
Конечно фиктивная запись, вот только в примере скорее всего был указатель другого типа (unsigned int или unsigned char). Как поступить в данной ситуации я вам уже выше подсказал - используйте явное приведение типа. Раз у вас указатель на float, то при фиктивной записи преобразуйте его к указателю на unsigned int.
Код
*((unsigned int *)addr)=0;

Цитата(Daria @ Jul 26 2008, 00:27) *
И вот еще ВОПРОС- понимаю, что, наверное, глупый, но -
Когда гружу прогу с помощью IAR Kickstart - работает нормально, считает четко все - я проверяла. Но так как код уже превышает 4кБ, гружу с помощью полной версии - на COM приходит полная ересь. С чем это может быть связано? Код такой же - один в один.
Версии IAR одинаковы? Настройки проекта одинаковы? И вообще, спрашивается зачем использовать KickStart при наличии полной версии? 07.gif Если вы не пользуетесь дебаггером, то для загрузки прошивки в кристалл использовать IAR вообще не обязательно. Пользуйтесь специальными программами. MSPFET Programmer от Kurt-а или FET-Pro430 Lite от Elprotronic или вот тут же в форуме zltigo свою утилиту AT430 предлагает.
А вообще правильность работы алгоритма программы можно проверить в симуляторе. Тем более, если у вас есть в наличии результаты работы алгоритма по известным данным.
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 25 2008, 21:05
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



И версии, и настройки. А кикстарт - потому что сначала был только он smile.gif
FET-Pro430 Lite у меня есть. но не очень-то удобно компилироваться, а потом грузить через нее - проще и быстрее же все делать в ИАРе smile.gif
Дебаггером, кстати, пользуюсь, но проверить алгоритм не получается - он не показывает текущие значения моих переменных, только регистры контроллера 05.gif - то же касается симулятора

Кстати, если настройка АЦП
ADC12CTL0 = ADC12ON +REFON + SHT0_8+MSC;
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+SHP;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
а потом
ADC12CTL0 |=ADC12SC;
ADC12CTL0 |=ENC;
while(ADC12IFG & BIT3);
CVx[cindex] = ADC12MEM3;
while(ADC12IFG & BIT4);
CVy[cindex] = ADC12MEM4;
ADC12CTL0 &= ENC;
так нормально? Или опять грузовики с кирпичами понаехали? biggrin.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 25 2008, 21:38
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jul 26 2008, 03:05) *
И версии, и настройки. А кикстарт - потому что сначала был только он smile.gif
FET-Pro430 Lite у меня есть. но не очень-то удобно компилироваться, а потом грузить через нее - проще и быстрее же все делать в ИАРе smile.gif
Не проще. C-Cpy грузит "дебажную" версию прошивки, а в реальное устройство вы будете компилировать другую версию, без дебаговских примочек. Не нравится FET-Pro430, используйте программатор Курта. Её (программу) кстати можно интегрировать в IAR, т.к. в ней имеется поддержка командной строки. Tools->Configure Tools->New обзываете ее и заполняете необходимые поля параметрами запуска программы MSPFET Programmer. Только для нее нужно использовать Release-ную настройку с форматом выходного файла TI-TXT или HEX.
Цитата(Daria @ Jul 26 2008, 03:05) *
Дебаггером, кстати, пользуюсь, но проверить алгоритм не получается - он не показывает текущие значения моих переменных, только регистры контроллера 05.gif - то же касается симулятора
Ну здрасте! А ручками в окно View->Watch имя интересуемых переменных или структур забить лень что ли? Или окно View->Locals открыть и наблюдать за автоматическими переменными.
Цитата(Daria @ Jul 26 2008, 03:05) *
Кстати, если настройка АЦП
ADC12CTL0 = ADC12ON +REFON + SHT0_8+MSC;
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+SHP;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
а потом
ADC12CTL0 |=ADC12SC;
ADC12CTL0 |=ENC;
while(ADC12IFG & BIT3);
CVx[cindex] = ADC12MEM3;
while(ADC12IFG & BIT4);
CVy[cindex] = ADC12MEM4;
ADC12CTL0 &= ENC;
так нормально? Или опять грузовики с кирпичами понаехали? biggrin.gif
А зачем вы включаете опору, если ее не использует е при измерении? А так... сойдет smile.gif Только я бы перед запуском преобразования флаги ADC12IFG почистил бы на всякий пожарный.
Опс! Тока сейчас заметил, неверно все-таки. Нужно так.
while((ADC12IFG & BIT3)==0);
Пока флаг не установлен, нужно ждать. А у вас инверсное условие. В моем примере выше я тоже ошибся, но поправить уже не могу. sad.gif
Go to the top of the page
 
+Quote Post
=DS=
сообщение Jul 25 2008, 21:40
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 54
Регистрация: 25-09-07
Пользователь №: 30 836



Цитата(Daria @ Jul 26 2008, 01:05) *
Дебаггером, кстати, пользуюсь, но проверить алгоритм не получается - он не показывает текущие значения моих переменных, только регистры контроллера 05.gif - то же касается симулятора

Галочка в project->options->linker->output "debug information for C-Spy" стоит?
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 26 2008, 12:38
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Jul 26 2008, 01:38) *
Ну здрасте! А ручками в окно View->Watch имя интересуемых переменных или структур забить лень что ли? Или окно View->Locals открыть и наблюдать за автоматическими переменными.

rezident, ну вы меня уж за совсем-пресовсем тупую держите! 05.gif smile.gif Конечно, не лень! Но состояние переменных почему-то не отображается, вместо этого error стоит. Только состояние регистров. Я думала, это так всегда biggrin.gif

Цитата(rezident @ Jul 26 2008, 01:38) *
Опс! Тока сейчас заметил, неверно все-таки. Нужно так.
while((ADC12IFG & BIT3)==0);
Пока флаг не установлен, нужно ждать. А у вас инверсное условие. В моем примере выше я тоже ошибся, но поправить уже не могу. sad.gif

не, это я тоже ошиблась, когда вам писала - на самом деле я, конечно, while(!(ADC12IFG & BIT3)) пишу. Ага? Тож на тож ведь. или все же не очень корректно? smile.gif



Цитата(=DS= @ Jul 26 2008, 01:40) *
Галочка в project->options->linker->output "debug information for C-Spy" стоит?

А вот не знаю. Посмотрю, спасибо smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 26 2008, 12:58
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jul 26 2008, 18:38) *
rezident, ну вы меня уж за совсем-пресовсем тупую держите! 05.gif smile.gif
Ну зачем же сразу такие эпитеты? Я просто делаю скидку на женскую альтернативную логику. Извините, если обидел.
Цитата(Daria @ Jul 26 2008, 18:38) *
Но состояние переменных почему-то не отображается, вместо этого error стоит. Только состояние регистров. Я думала, это так всегда biggrin.gif
=DS=, указал вероятную причину.
Цитата(Daria @ Jul 26 2008, 18:38) *
не, это я тоже ошиблась, когда вам писала - на самом деле я, конечно, while(!(ADC12IFG & BIT3)) пишу. Ага? Тож на тож ведь. или все же не очень корректно? smile.gif
Да пишите себе на здоровье, раз вам такой стиль нравится! Просто я лично при проверке условий предпочитаю явное сравнение с нулем. Для меня так нагляднее и понятнее. Но в свою "религию" я никого насильно не обращаю biggrin.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 28 2008, 20:14
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Так вот. Галочка стоит. А состояние переменных все равно error 05.gif
По поводу ошибок в программе - у меня, кстати, все-таки разные версии, Kickstart 5.0, a Evolution 4.0. smile.gif Но разве это может повлиять.? Ведь не ругается, все считает... Что-то не так с #include <math.h>? А, еще - они стоят вместе. Могут, перепуться библиотеки?
Теперь такие вопросы:
rezident, вы вот давно обещали помочь разобраться с таймером wink.gif Так, как я это делаю(по переключению флага ) - не пойдет biggrin.gif "Камазы с кирпичами", да и только biggrin.gif При большой скорости пересчета, в принципе, можно забить на некоторые неточности, но, когда нужно выполнять что-то четко по команде...
Вы говорили, что можно использовать выход таймера. Как? smile.gif Ведь мне не нужно постоянно переключать вывод, нужно долго держать его в единице, а потом короткое время в ноле.
Еще- если я запущу еще и таймер В - это не будет излишней перегрузкой программы? Дело в том, что мне надо постоянно фиксировать состояние переменной azimut и где-то раз в секунду смотреть, не изменилась ли она, если изменилась - отсылать команду на COM. Что, если делать это по таймеру В?
Короче - помогите, спасите smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 28 2008, 23:05
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jul 29 2008, 02:14) *
Так вот. Галочка стоит. А состояние переменных все равно error 05.gif
Ну я не знаю. laughing.gif Попробовал я в своем текущем проекте убирать "птички" в опциях проекта везде, где только встретил "Generate debug ...". В режиме отладки пропала возможность "шагать" по Сишному исходнику. Только по ASM-овому тексту теперь шагает. Но значения глобальных переменных в окне Watch и локальных переменных в окне Locals все равно показывает. Может вы пытаетесь в окне Watch значение локальной переменной посмотреть? Тогда понятно почему ошибку выдает.
Цитата(Daria @ Jul 29 2008, 02:14) *
По поводу ошибок в программе - у меня, кстати, все-таки разные версии, Kickstart 5.0, a Evolution 4.0. smile.gif Но разве это может повлиять.? Ведь не ругается, все считает... Что-то не так с #include <math.h>? А, еще - они стоят вместе. Могут, перепуться библиотеки?
В один каталог крайне не рекомендуется устанавливать разные версии одного продукта. Если только с одинаковой версией IDE, но для разных целевых платформ (например, EWAVR и EW430). Устанавливайте версии KickStart и Evalution в разные каталоги, тогда путаницы не будет.
Цитата(Daria @ Jul 29 2008, 02:14) *
rezident, вы вот давно обещали помочь разобраться с таймером wink.gif Так, как я это делаю(по переключению флага ) - не пойдет biggrin.gif "Камазы с кирпичами", да и только biggrin.gif При большой скорости пересчета, в принципе, можно забить на некоторые неточности, но, когда нужно выполнять что-то четко по команде...
Вы говорили, что можно использовать выход таймера. Как? smile.gif Ведь мне не нужно постоянно переключать вывод, нужно долго держать его в единице, а потом короткое время в ноле.
У таймеров MSP430 имеется режим compare (сравнения), в котором содержимое регистра TAR/TBR (которое постоянно инкрементируется по тактовым импульсам TACLK/TBCLK) сравнивается с capture-регистрами CCRx. При совпадении CCRx и TAR/TBR происходит установка флага CCIFG в соответствующем регистре CCTLx, а если разрешено прерывание для этого регистра (установлен бит CCIE), то еще и генерируется вызов прерывания по соответствующему вектору. Векторов для каждого таймера по две штуки. Один для CCR0, второй вектор расшарен для всех остальных CCRx. Манипулируя содержимым CCRx, вы можете генерировать прерывания для разных отметок времени. Кроме этого, для каждого блока compare имеется выходной модуль, который по возникающим событиям таймера может управлять состоянием бита OUT в CCTLx и ассоциированного с ним пина (или пинов, т.к. для TimerA эта функция выведена на несколько пинов) TAx/TBx. По событию совпадения TAR/TBR и CCRx бит OUT может быть сброшен, установлен, проинвертирован. Совпадение TAR/TBR и CCR0 действует на состояния всех битов OUT во всех выходных модулях таймера. По этому событию (от CCR0) бит OUT также может быть сброшен, установлен, проинвертирован. Таким образом можно генерировать ШИМ. Например, если для TA1 выбрать режим выходного модуля "сброс/установка", то по совпадению TAR и CCR1 вывод TA1 сброситься в лог.0, а по совпадению TAR и CCR0 установиться в лог.1. Режим выходного блока задается для каждого регистра индивидуально. Исключение составляет только CCR0, т.к. он действует сам на себя дважды за период, если выбран режим счета CountUp или Up/Down в которых период счета определяется содержимым этого CCR0.
Я предлагал вам использовать TimerA в режим счета Continious (с переполением). Выходной модуль TA0 или TA1 использовать для генерации выходного управляющего импульса, который одновременно запускает преобразование АЦП в непрерывном режиме последовательности каналов. Вам нужно только в прерывании от CCR0 или CCR1 вести счетчик и при достижении предпоследнего интервала отсчета импульса перепрограммировать режимы выходного блока и вовремя остановить АЦП для нового запуска по другому фронту TA0 или TA1.
Вот. Утомился я что-то "на пальцах" пересказывать содержимое User's Manual. smile.gif Если еще непонятно, то пояснения будут уже завтра.
Кстати, не помню, давал ли я ссылку на русскоязычный переводной вариант User's Manual? На всякий случай продублирую ссылку на Компэловскую библиотеку.
Цитата(Daria @ Jul 29 2008, 02:14) *
Еще- если я запущу еще и таймер В - это не будет излишней перегрузкой программы? Дело в том, что мне надо постоянно фиксировать состояние переменной azimut и где-то раз в секунду смотреть, не изменилась ли она, если изменилась - отсылать команду на COM. Что, если делать это по таймеру В?
Нет особой разницы на какой таймере вести счет временных отметок (пауз). Если вам так удобно, то задействуйте TimerB. Хотя необходимости в этом я не вижу. У вас уже имеется счетчик на TimerA. Просто добавьте в процедуру прерывания еще один счетчик с удобным весовым коэффициентом. Я предпочитаю вести счет времени в миллисекундах. Например, используя WDTimer и ACLK от часового таймера.
Код
#define SYSTIME_TICKPERIOD_MS  16 //весовой коэффициент системных тиков

volatile unsigned int TMTick;

//================================================//
// Инициализация таймера системных тиков          //
//------------------------------------------------//
//аргументы :нет                                  //
//возвращает:нет                                  //
//================================================//
void initSysTickTimer(void)
{ TMTick=0;
  WDTCTL=WDT_ADLY_16;                             //интервальный таймер тиков, тик=15,625мс
  IFG1&=~WDTIFG;                                  //сбросим флаг
  IE1|=WDTIE;                                     //разр. прерывание
}

const unsigned int SysTickCorrTbl[8]={0,0,1,0,0,1,0,1};  //корректировочная таблица

//================================================//
// Обработчик прерываний системного таймера       //
//------------------------------------------------//
//аргументы :нет                                  //
//возвращает:нет                                  //
//================================================//
#pragma vector=WDT_VECTOR
#pragma type_attribute=__interrupt
void SysTickTimer_ISR(void)
{ static unsigned int sysCntr=0;                     //вспомогательная переменная сист.тиков
//--- системные тики [мс] ---
  if (sysCntr<7)
    sysCntr++;
  else
    sysCntr=0;
  TMTick+=SYSTIME_TICKPERIOD_MS-SysTickCorrTbl[sysCntr];//инкремент сист. тиков (мс)
}

В основном теле программы я беру абсолютную разницу (беззнаковую разность) между двумя считанными значениями переменной TMTick и получаю прошедший интервал времени. Учитывая необходимость атомарности доступа к переменной системных тиков, выбираю ее тип unsigned int. Этот тип позволяет определять интервал времени до 65,5 секунд (период переполнения переменной). Если нужны бОльшие интервалы времени, то нужно брать 32-х битную переменную, но тогда придется запретом/разрешением прерывания или другими способами обеспечить атомарность доступа к ней.
Еще замечание насчет примененной корректировочной таблицы. Поскольку период частоты, полученной от деления частоты часового кварца (32768Гц) на делитель WDTimer (512), не является целой величиной миллисекунд (15,625мс), то я корректирую точность системных тиков с помощью таблицы. И на периоде 250мс получаю целое число миллисекунд.
Go to the top of the page
 
+Quote Post
Daria
сообщение Jul 30 2008, 19:31
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Jul 29 2008, 03:05) *
Ну я не знаю. laughing.gif Попробовал я в своем текущем проекте убирать "птички" в опциях проекта везде, где только встретил "Generate debug ...". В режиме отладки пропала возможность "шагать" по Сишному исходнику. Только по ASM-овому тексту теперь шагает. Но значения глобальных переменных в окне Watch и локальных переменных в окне Locals все равно показывает. Может вы пытаетесь в окне Watch значение локальной переменной посмотреть? Тогда понятно почему ошибку выдает.

Ничего подобного smile.gif Все же не совсем, не совсем я даунито, я уже говорила. Локальные переменные смотрю, где надо smile.gif
Об остальном - rezident, какой же вы все-таки хороший! biggrin.gif Так все подробно и хорошо. Та функция, которую хотела сделать, вроде работает, а про таймеры... В принципе я пыталась сделать нечто подобное, но возникли проблемы smile.gif Какие именно, напишу чуть позже, когда еще раз попробую переделать, руководствуясь вашими комментариями smile.gif Спасибо, конечно, огромное. буду разбираться smile.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 7 2008, 20:43
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте, снова я smile.gif
Цитата(rezident @ Jul 29 2008, 03:05) *
Например, если для TA1 выбрать режим выходного модуля "сброс/установка", то по совпадению TAR и CCR1 вывод TA1 сброситься в лог.0, а по совпадению TAR и CCR0 установиться в лог.1.
...Я предлагал вам использовать TimerA в режим счета Continious (с переполением). Выходной модуль TA0 или TA1 использовать для генерации выходного управляющего импульса, который одновременно запускает преобразование АЦП в непрерывном режиме последовательности каналов. Вам нужно только в прерывании от CCR0 или CCR1 вести счетчик и при достижении предпоследнего интервала отсчета импульса перепрограммировать режимы выходного блока и вовремя остановить АЦП для нового запуска по другому фронту TA0 или TA1.

Все же я какая-то непонятливая sad.gif допустим, режим Continious и режим "сброс/установка", по совпадению TAR и CCR1 вывод TA1 сброситься в лог.0, а по совпадению TAR и CCR0 установиться в лог.1. Но максимальное число. которое я могу записать в CCR0 - FFFF. А мне нужно держать лог. 1 долго. Как быть? Может, установить сначала режим "установка", в прерываниях от CCR0 вести счетчик, а в последнем переключить режим на "сброс". В следующем за ним прерывании опять "установка". Можно так сделать? Вы об этом говорите? smile.gif
Да, а по поводу версий IAR - дело было просто в глючности самой ломаной версии 3.2 smile.gif
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 06:17
Рейтинг@Mail.ru


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