Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MSP430 - вопросы от чайника
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Страницы: 1, 2
Daria
Здравствуйте.
Подскажите пожалуйста, генератор тактовой частоты запускается сразу после подачи питания или его надо сначала сконфигурировать? не могу найти регистр, который бы за это отвечал. Тот же вопрос про генератор опорного напряжения.
Подскажите еще, пожалуйста, как в CCE 2.0 войти в режим симулятора, никак не могу понять. Вроде в свойствах проекта на режим отладки устанавливаю - "simulator", но при запуске debuge ничего не происходит.
rezident
Цитата(Daria @ May 19 2008, 02:05) *
Подскажите пожалуйста, генератор тактовой частоты запускается сразу после подачи питания или его надо сначала сконфигурировать? не могу найти регистр, который бы за это отвечал.
Про какой их двух/трех генераторов вопрос? И про какой кристалл? DCO стартует сразу после подачи питания. LFXT с часовым кварцем тоже сразу, но колебания стабилизируются только через несколько сотен миллисекунд после включения. С высокочастотным кварцем LFXT сразу не стартует, для этого его нужно сконфигурировать. XT2 при подаче питания выключен. Для включения опять же нужно его сконфигурировать. FLL от часового кварца тоже по-моему запускается сразу, но вот тут на 100% не уверен, т.к. с кристаллами в которых есть FLL я не работал.
Цитата(Daria @ May 19 2008, 02:05) *
Тот же вопрос про генератор опорного напряжения.
REF при включении питания выключен. И везде включается только отдельным битом в специальном регистре.
И вообще ответы на ваши вопросы находятся в User's Guide семейства MSP430 и в datasheet конкретного кристалла.
Цитата(Daria @ May 19 2008, 02:05) *
Подскажите еще, пожалуйста, как в CCE 2.0 войти в режим симулятора, никак не могу понять. Вроде в свойствах проекта на режим отладки устанавливаю - "simulator", но при запуске debuge ничего не происходит.
По CCE не подскажу, т.к. не использую эту среду разработки.
Daria
Большое спасибо, вопрос был именно про LFXT smile.gif А в руководстве я этого не нашла.
rezident
Цитата(Daria @ May 19 2008, 23:28) *
А в руководстве я этого не нашла.
Ну если вы соблаговолите указать полное имя кристалла MSP430, то наверное я смогу "ткнуть пальцем" на то место, где об этом явно написано. smile.gif
Daria
Цитата(rezident @ May 19 2008, 21:13) *
Ну если вы соблаговолите указать полное имя кристалла MSP430, то наверное я смогу "ткнуть пальцем" на то место, где об этом явно написано. smile.gif

Большое спасибо, но я уже smile.gif не надо тыкать
Daria
А вот еще вопрос от чайника. Подскажите, если кто наткнется на тему, какую-нибудь отладку, чтобы работала с IARом в режиме эмулятора, и позволяла бы программировать прямо на плате, т.к.. контроллер уже напаян. Вот какие запросы smile.gif
rezident
Вам нужен готовый или схема для самостоятельного изготовления? Готовые - пожалуйста, в большом ассортименте в Терраэлектронике. А если хотите сами делать, то схемы оригинальных MSP-FET430PIF (LPT) и MSP-FET430UIF (USB) имеются в апликухе от производителя - slau138. Прошивку для MSP-FET430UIF где-то тут в форуме выкладывали.
Daria
Цитата(rezident @ May 25 2008, 22:58) *
Вам нужен готовый или схема для самостоятельного изготовления? Готовые - пожалуйста, в большом ассортименте в Терраэлектронике. А если хотите сами делать, то схемы оригинальных MSP-FET430PIF (LPT) и MSP-FET430UIF (USB) имеются в апликухе от производителя - slau138. Прошивку для MSP-FET430UIF где-то тут в форуме выкладывали.

Большое спасибо smile.gif
Daria
Здравствуйте. Такой вопрос - запускаю таймер( в TACCRO записываю 50000), в обработчике прерываний посылаю на COM число 0хАА, передаю и принимаю на скорости 9600, число исправно приходит, но на каждом 30-м и 31-м шаге появлются какие-то лишние биты, получается 0хЕА и 0хСА. Есть варианты, почему это может происходить? Посылаю с вывода P3.4, при начальной конфигурации записываю P3SEL=Bit4, P3OUT=0(на всякий случай). На эмуляторе видно, что таймер работает и в буфере передачи только 0хаа. (Но достаточно долго наблюдать работу не получается, так как происходит переполнение стека - почему, кстати, оно происходит?) Я не считаю модуляцию, U0MCTL оставляю нулевым - может, в этом дело? Но нужно ли считать модуляцию при такой скорости? Частота тактирования 8МГц.
Заранее спасибо, если кто ответит.
rezident
Что-то полная путаница. При чем тут модуль TimerA, если для передачи вы пользуетесь модулем USART0? Вы бы хоть кусок кода привели. Как именно инициализируете модули, а особенно систему тактирования? Как выглядят обработчики прерываний? Что за кристалл вообще вы используете? В сообщениях выше вы "махнули рукой", а теперь снова не уточнив ничего мечетесь с вопросами.
Насчет делителя и модуляции. 8000000/9600=833,3(3). Значение для делителя 0x0341, если представлять его как целое число в HEX формате. Если не использовать модулятор, то получается реальный битрейт 8000000/833=9603,8 и ошибка составляет меньше 0,05%. Для UART такая ошибка сущие мелочи. Так что думаю проблема у вас не там, где в программе приемо-передача, а как это обычно бывает у новичков, там где инициализация источников тактирования.
Переполнения стека бывают чаще всего при использовании функций активно его использующих (типа printf/sprintf) и/или при неконтролируемом использовании вложенных прерываний.
A R T
Цитата(Daria @ Jun 3 2008, 23:24) *
Здравствуйте. Такой вопрос - запускаю таймер( в TACCRO записываю 50000), в обработчике прерываний посылаю на COM число 0хАА, передаю и принимаю на скорости 9600, число исправно приходит, но на каждом 30-м и 31-м шаге появлются какие-то лишние биты, получается 0хЕА и 0хСА. Есть варианты, почему это может происходить? Посылаю с вывода P3.4, при начальной конфигурации записываю P3SEL=Bit4, P3OUT=0(на всякий случай). На эмуляторе видно, что таймер работает и в буфере передачи только 0хаа. (Но достаточно долго наблюдать работу не получается, так как происходит переполнение стека - почему, кстати, оно происходит?) Я не считаю модуляцию, U0MCTL оставляю нулевым - может, в этом дело? Но нужно ли считать модуляцию при такой скорости? Частота тактирования 8МГц.
Заранее спасибо, если кто ответит.

Согласен с rezident. Ошибка UART-a скорее всего никак не связана с таймером. Прпробуйте отладить передатчик отдельно от таймера. От себя хочу посоветовать посмотреть, как происходит контроль бита четности на приемнике и передатчике, т.е. устанавливается ли он (и каким образом) передатчиком и контролируется ли он (и каким образом) приемником...

Механизм переполнения стэка примерно такой: когда вызывается подпрограмма (в т.ч. обработки прерывания) регистр состояния проца, адрес возврата и передаваемые подпрограмме переменные (если они есть) закидываются в стек, после окончания подпрограммы они оттуда удаляются. Если в процессе выполнения подпрограммы снова происходит вызов подпрограммы (более приоритетное прерывание или вложенная подпрограмма), происходит то же самое (регистр состояния и пр. закидывается в стек) и размер стека увеличивается. Если и дальше производить вызовы подпрограмм рано или поздно данные, загружаемы в стек, попадут в облать переменных или "кучи" и будут модифицированы случайными значениями, которые в свою очередь будут испольованы как регистр состояния или адрес возврата при выходе из подпрограммы.
Daria
Спасибо, следуя вашему совету, начинаю разбираться с начала.
Вот текст простенькой программки работы таймера, с которой все начиналось smile.gif
#include <msp430x14x.h>
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

P1DIR = BIT5;
P1OUT = BIT5;

BCSCTL1 |= XTS;
BCSCTL2 |= SELM_3;

TACCTL0 = CCIE;
TACTL = TASSEL_1 + MC_1 + ID_3;
TACCR0 = 5000;

_BIS_SR(GIE);
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
P1OUT ^= 0x01;

}
Источник тактирования - резонатор 8МГц, выбираю режим "вверх"(MC_1), по идее таймер считает вверх до значения в TACCR0 и счетчик сбрасывается. в обработчике прерывания инвертирую выход P1.5.
В чем проблема - когда в TACCR0 записываю значения более 1000 тактов, картинка на осциллографе соответствует ожиданиям. Если же CCR0 меньше 500 тактов, то длительность задаваемых импульсов не соответствует длительности импульсов на экране осциллографа. С чем это может быть связано? Может, в этом режиме существует минимальное значение, которое можно записывать в TACCR0?
Вот пока такой вопрос smile.gif
rezident
А у вас высокочастотный кварц 8Мгц куда подключен? К генератору XT1/LFXT что ли? Что за кристал-то в конце-концов у вас??? Это военная тайна или вы внучка-последовательница Зои Космодемьянской? И не нужно какой-то абстрактный пример приводить, приведите текст реальной программы, которую вы используете! Пускай он выглядит как угодно некузяво. В примере же вами приведенном как минимум имеется один недочет, связанный с алгоритмом инициализации системы тактирования. Но раз вы не желаете диалога, то читайте Chapter 4..2 Basic Clock Module Operation из MSP430x1xx Family User's Guide самостоятельно и с тщательным вниманием.
Daria
Цитата(rezident @ Jun 6 2008, 04:08) *
А у вас высокочастотный кварц 8Мгц куда подключен? К генератору XT1/LFXT что ли? Что за кристал-то в конце-концов у вас??? Это военная тайна или вы внучка-последовательница Зои Космодемьянской? И не нужно какой-то абстрактный пример приводить, приведите текст реальной программы, которую вы используете! Пускай он выглядит как угодно некузяво. В примере же вами приведенном как минимум имеется один недочет, связанный с алгоритмом инициализации системы тактирования. Но раз вы не желаете диалога, то читайте Chapter 4..2 Basic Clock Module Operation из MSP430x1xx Family User's Guide самостоятельно и с тщательным вниманием.

Желаю я диалога, очень желаю! smile.gif Никакая не тайна, просто по рассеянности все время забываю указать кристалл - MSP430F149, кварц подключен к XT1/LFXT, пример вполне конкретный - начиная разбираться, я закомментила все, кроме вот этого текста, который Вам привела. и вот такая ошибка, которую не могу понять. Тактовая частота 8МГц, делю на 8 (ID_3), получается, что один такт - 1 мкс, задаю длительности, и получаю, что при уменьшении с 500 на 400 длительность импульса на осциллографе изменяется совсем чуть-чуть, а при дальнейшем уменьшении - вообще не изменяется. А вот если задать 1000 и больше - то все нормально.
Вы же сами говорили не кидаться кучей вопросов, а разбираться с нуля. ну вот. Не ругайтесь на меня, пожалуйста 05.gif :)USART действительно вполне нормально инициилизирован, я проверяла без таймера, так что наверное все дело в этом. А руководство я читаю, вникаю, пыхчу, но вот никак пока не получается, может - не дано, а, может просто опыта нет - что такое контроллер - узнала только зимой biggrin.gif бывают такие темные личности. smile.gif
А, если Вам, действительно, не лень разбираться в моей проге - то обязательно приведу весь текст. со всей некузявостью, но он и сам пока небольшой smile.gif
rezident
При использовании высокочастотного кварца нужна определенная последовательность действий в процедуре инициализации модуля тактирования. По старту тактирование MCLK и SMCLK от DCO происходит. Нужно дождаться стабилизации колебаний кварцевого генератора и только потом переключить тактирование на него.
Код
BCSCTL2=SELM_0|DIVM_0|DIVS_0;
BCSCTL1=DIVA_3|XTS|XT2OFF;
do
{ IFG1&=~OFIFG;
} while((IFG1&OFIFG)!=0);
BCSCTL2|=SELM_3;

После такой процедуры ACLK=XT1/8=1МГц, SMCLK=DCO≈1МГц, MCLK=XT1=8МГц. Кстати, ошибка из-за которой ваш UART принимает неправильно может быть локализована именно здесь.
Далее. Как именно вы меняете период TimerA при ваших наблюдениях? Изменяете значение TACCR0 в программе, компилируете, загружаете в кристалл и смотрите? Или это опять где-то в недрах вашей таинственной программы делается? Если первый вариант, но никаких чудес быть не должно.
Код
TACTL=TASSEL_1|ID_0|TACLR; //TACLK=ACLK/1=1МГц
TACCTL0=CCIE;
TACCR0=4999; //период перезагрузки (4999+1)/1МГц=5мс
TACTL|=MC_1; //только сейчас можно запускать таймер

Сначала инициализируем все нужные регистры и только потом запускаем таймер. Период перезагрузки таймера и соответственно вызова прерываний по вектору TIMERA0_VECTOR будет 5мс, а период переключения выхода P1.0 соотвественно вдвое больше. Это если использовать указанный в вашем примере способ "ногодрыгания".
Код
#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA_ISR (void)
{ P1OUT^=0x01;
}
Daria
Большое спасибо! Сделаю в точности так, как вы говорите. А изменяю длительность именно так - меняю TACCR0, компилируюсь, загружаю и смотрю smile.gif И никакой таинственной программы пока по сути нет - набрасываю просто куски, учусь smile.gif
Спасибо еще раз
Daria
Здравствуйте, снова я smile.gif Опять проблемы
привожу весь свой маленький текст, чтобы не ругались потом. будто что-то скрываюsmile.gif
#include <msp430x14x.h>

void main(void)
{
int i, Vs, Vr;

WDTCTL = WDTPW + WDTHOLD;

P1SEL |= BIT6;
P3SEL = BIT4 + BIT5;
P6SEL = 0xF8;
P1DIR |= BIT5;
P1OUT = BIT5;

CCTL0 = OUTMOD_4 ;
TACCR0 = 65000;
BCSCTL1 = XTS + XT2OFF;
BCSCTL2 = SELM0;

do
{
IFG1 &= ~OFIFG;
for (i = 0xFF; i > 0; i--);
}
while ((IFG1 & OFIFG));

BCSCTL2 = SELM_3;

TACTL = TASSEL_1 + ID_3;

ADC12CTL0 = SHT0_12 + ADC12ON + REFON;
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1 + CONSEQ_1;
ADC12MCTL3 = INCH_3;

ADC12CTL0 |= ENC;


_BIS_SR(U0CTL & SWRST);

ME1 |= UTXE0 + URXE0;
U0CTL |= CHAR;
U0TCTL = SSEL0;
U0BR0 = 0xA0;
U0BR1 = 0x01;
U0MCTL = 0x00;
U0CTL &= ~SWRST;
IE1 |= URXIE0;
_BIS_SR(GIE);

i = 1;

TACTL |= MC_1 ;

for(;;)
{

if (TACCTL0 & CCIFG)
{
if (P1OUT & BIT5)
{
ADC12CTL0 |= ADC12SC + ENC;
ADC12CTL0 &= ENC;
if (ADC12IFG)
{
Vr = ADC12MEM3;

TXBUF0 = ((Vr-Vs)/2 & 0xFF);



send_int(conv[j]);
}


TACCTL0 &= !CCIFG;
i++;
if (i >= 918 )
{
TACCR0 = 400;
P1OUT = 0;
i = 0;
}
if (i == 1)
{
P1OUT = BIT5;
ADC12CTL0 |= ADC12SC + ENC;
ADC12CTL0 &= ENC;
Vs = ADC12MEM3;


TACCR0 = 65000;

}
}
}
}
Чего, как я думаю, здесь делается - включаю таймер в режим переключения, в TACCR0 - 65000 тактов, вывод держу в единице, пока не поризойдет 918 переключений, затем переписываю счетчик на 400, переключаю вывод в ноль, после следующего переключения, снова в единицу, и снова переписываю счетчик в 65000 тактов. Т.е. хочу минуту держать вывод в единице, затем 400 мкс в нуле, и так все время работы. Вовремя коротких импульсов, считываю уровень с вывода P6.3, записываю как Vs, во время длинных - как Vr, потом считаю (Vr-Vs)/2 и посылаю на COM. То, что буфере один байт, а число получается двухбайтовым, я знаю smile.gif , посылаю пока младший байт, не в этом суть.
В ЧЕМ ПРОБЛЕМА - напряжения на P6.3 только положительные, нужно при преобразовании АЦП получать положительные и отрицательные числа. Формула преобразования АЦП по даташиту - 4095*(Vin - V-)/(V+- V-) Питание - 3,3 В. Опорное напряжение Vref+ = 1.5В. Как мне правильно сконфигурировать АЦП? CONSEQ_1 означает, что V- = 0, V+ = 3.3. Более подходящего варианта не вижу. Но как указать, что ноль переносится в 1,5? Или
каждый раз писать Vr - 4095*1.5/3.3 - извините за глупые вопросы, но вот непонятно 05.gif
И вообще, если кому-то вдруг не лень будет почитать текст - есть ли здесь ошибки при конфигурировании АЦП или USART?
Заранее огромное спасибо
Daria
на строчку send_int не обращайте внимания, она осталась от старой, уже удаленной функции. И, конечно, Vs перед for(;;); определяется как Vs=0; smile.gif
Daria
Нет, тут опять ошибки biggrin.gif Vs вычисляется после P1OUT = 0; и CONSEQ_1 не нужен, в данном случае однократное преобразование.
И вот еще - я записываю функцию, которая передает два байта, так
void send_int(int a)
{
while (!(IFG1 & UTXIFG0));
TXBUF0 = (a & 0x3F);
while (!(IFG1 & UTXIFG0));
TXBUF0 = (a>>6);
while (!(IFG1 & UTXIFG0));
TXBUF0 = 0xFF;
}
0xFF - флаг, АЦП двенадцатиразрядный. Сначала 6 бит, потом еще 6, потом флаг.
Как можно это сделать проще?
Ау, кто-нибудь smile.gif
АДИКМ
Посылать по 6 бит никто не запрещает конечно, но все таки лучше посылать например сначала младший байт, потом старший . а уже в компьютере их склеивать. Тем более, что ничего вы не теряете.


примерно так -
mov &adc12mem0 , r10 - копируем результат измерения
mov.b r10, &TXBUF0 - передаем младший байт
ждем UTXIFG0
swpb r10
mov.b r10, &TXBUF - передаем старший байт
ждем UTXIFG0




я бы порекомендовал вам посмотреть на эту книгу. там очень хорошо описаны многие вопросы, правда на английском
Daria
Цитата(АДИКМ @ Jun 10 2008, 00:24) *
Посылать по 6 бит никто не запрещает конечно, но все таки лучше посылать например сначала младший байт, потом старший . а уже в компьютере их склеивать. Тем более, что ничего вы не теряете.

Проблема в том, как потом записать флаг. Любое число не будет уникальным, если младший байт будет 8-ми битовым. А так получается, что 0xFF никогда не может прийти в младшем байте. Мысль была такая. smile.gif Или я чего-то не понимаю? sad.gif
Книгу обязательно почитаю, спасибо
АДИКМ
Цитата(Daria @ Jun 9 2008, 23:47) *
Проблема в том, как потом записать флаг. Любое число не будет уникальным, если младший байт будет 8-ми битовым. А так получается, что 0xFF никогда не может прийти в младшем байте. Мысль была такая. smile.gif Или я чего-то не понимаю? sad.gif
Книгу обязательно почитаю, спасибо


Расскажите, что это за флаг и почему число должно быть уникальным? Далее, что Вы измеряете и какой амплитуды у Вас сигнал? С какой позиции выбрано опорное 1.5 В, а не 2.5 или 3.3 ?
Если Вы передаете данные в компьютер, то гораздо проще переложить вычисления на него. Ну или расскажите, что Вы задумали сделать.
rezident
Цитата(Daria @ Jun 8 2008, 23:22) *
Здравствуйте, снова я smile.gif Опять проблемы
привожу весь свой маленький текст, чтобы не ругались потом. будто что-то скрываюsmile.gif
Текст программы пока комментировать не буду, лучше после уточнений приведу для сравнения свой вариант. Сделаю лишь несколько замечаний.
1. Не следует надеятся на значения регистров периферии, устанавливаемых состояниями POR/PUC. При инициализации их прописывайте явно значения, а не накладывайте маски.
2. Сначала обычно инициализируются функции всех пинов и система тактирования. Потом инициализируются периферийные модули, разрешается работа этих модулей, при необходимости прерывания. Затем устанавливается глобальный флаг прерываний и запускаются таймеры. Я обычно делаю в такой последовательности.
3. При склеивании отдельных битов в байт/слово, вместо операции + (сложение) следует использовать | (побитовое ИЛИ). Это позволяет избежать недоразумений при случайном дублировании одинаковых бит.
Цитата(Daria @ Jun 8 2008, 23:22) *
Чего, как я думаю, здесь делается - включаю таймер в режим переключения, в TACCR0 - 65000 тактов, вывод держу в единице, пока не поризойдет 918 переключений, затем переписываю счетчик на 400, переключаю вывод в ноль, после следующего переключения, снова в единицу, и снова переписываю счетчик в 65000 тактов. Т.е. хочу минуту держать вывод в единице, затем 400 мкс в нуле, и так все время работы.
Логичнее было бы использовать таймер в режиме переполнения Continious. А интервалы отсчитывать по прерыванию от регистра совпадения CCRx. При тактировании таймера частотой 1МГц для отсчета 60 секунд нужно 915 раз к текущему значению прибавлять максимальное число 65536 или просто 915 раз пропускать это суммирование. На 916-й раз добавить к текущему значению CCRx число 34560 и следующее прерывание от CCRx будет соответствовать 60с интервалу. Тут же в прерывании добавляем к текущему значению CCRx число 400 и опять-таки следующее прерывание будет соответствовать интервалу 400мкс. Затем по-новой игнорируем 915 раз в прерывании суммирование и т.д. А если еще задействовать аппаратное управление выходом TAx, то получиться совсем кошерно и точно. Ваш сигнал что-то реально переключает или используется в качестве индикации состояния? Допустимо ли его "переключательную" функцию переместить на пин, который может выполнять выходную функцию TAx? Например, на P1.1 или P1.2?
Цитата(Daria @ Jun 8 2008, 23:22) *
Вовремя коротких импульсов, считываю уровень с вывода P6.3, записываю как Vs, во время длинных - как Vr, потом считаю (Vr-Vs)/2 и посылаю на COM. То, что буфере один байт, а число получается двухбайтовым, я знаю smile.gif , посылаю пока младший байт, не в этом суть.
Опять-таки лучше было бы посылать не просто код, а преобразовывать его в символьную строку. Тогда результат можно наблюдать даже в виндусовом гипертерминале. А если напряжение вычислять не в абстрактных попугаях, а, например, в миллиВольтах, то для вычислений не понадобится даже плавающая арифметика и результат измерения будет достаточно точным.
Цитата(Daria @ Jun 8 2008, 23:22) *
В ЧЕМ ПРОБЛЕМА - напряжения на P6.3 только положительные, нужно при преобразовании АЦП получать положительные и отрицательные числа. Формула преобразования АЦП по даташиту - 4095*(Vin - V-)/(V+- V-) Питание - 3,3 В. Опорное напряжение Vref+ = 1.5В. Как мне правильно сконфигурировать АЦП? CONSEQ_1 означает, что V- = 0, V+ = 3.3. Более подходящего варианта не вижу. Но как указать, что ноль переносится в 1,5? Или
каждый раз писать Vr - 4095*1.5/3.3 - извините за глупые вопросы, но вот непонятно 05.gif
А вот здесь мне непонятно. Что за двуполярное напряжение? На вход АЦП можно подавать сигнал, который попадает в диапазон от Vref- до Vref+. Если Vref+ равно 1,5В, то входной сигнал не может быть выше 1,5В. Если же в качестве Vref используется питание, то не выше 3,3В. Вы можете сместить входной сигнал на половину питания или относительно любого другого напряжения, но в любом случае промасштабированный размах входного сигнала должен быть не ниже потенциала AGND и не выше потенциала AVCC. Это принципиальное условие для того, чтобы не вывести кристалл из строя.
А для учета смещения нужно ввести коэффициент в конечную формулу преобразования.
Vin=(VREFmax-VREFmin)/(ADCmax-ADCmin)*x+VREFmin-Vbias, где VREFmax - напряжение VREF+/VeREF+, VREFmin - напряжение VREF-/VeREF-, ADCmax - 4095, ADCmin - 0, x - код полученный от АЦП, Vbias - напряжение смещения относительно которого считается нуль. Если у вас Vbias = 1,5В, VREF+ = 3,3В, а VREF- = 0В, то расчетное напряжения Vin в диапазоне от 0В до 1,5В будет иметь отрицательные значения, а от 1,5В до 3,3В положительные значения. Хотя входное измеряемое напряжение будет все равно положительным относительно AGND.
Цитата(Daria @ Jun 8 2008, 23:22) *
И вообще, если кому-то вдруг не лень будет почитать текст - есть ли здесь ошибки при конфигурировании АЦП или USART?
После уточнения параметров задания с вашей стороны приведу свой вариант программы.
Daria
Цитата(АДИКМ @ Jun 10 2008, 01:10) *
Расскажите, что это за флаг и почему число должно быть уникальным? Далее, что Вы измеряете и какой амплитуды у Вас сигнал? С какой позиции выбрано опорное 1.5 В, а не 2.5 или 3.3 ?
Если Вы передаете данные в компьютер, то гораздо проще переложить вычисления на него. Ну или расскажите, что Вы задумали сделать.

Пробовала сначала просто посылать один байт, потом другой. но получалась путаница. Поэтому отправляю байт, означающий конец посылки. С опорным, если честно, не понятно. выбрано потому, что по схеме вроде требуется 1,5 В напряжения для правильного включения усилителя мощности - вот с Vref+ и подается. А что дальше с ним делать не знаю biggrin.gif Темная я, темная smile.gif Что хочу сделать, сейчас расскажу - в ответе rezident Спасибо за участие!

Так. Режим переполнения таймера я пока не разбирала smile.gif Так что сейчас, да еще ночью, если честно не все ясно. Просмотрю внимательно Ваши комментарии утром, спасибо огромное, кстати smile.gif
Чего хочу сделать - вообще когда-нибудь это должно стать программой цифрового компаса biggrin.gif Для правильной работы магнитного датчика необходимо подавать с мк такие импульсы на преобразователь IRF7105, с выводов IRF7105 (транзисторная сборка) импульсы(получаются противоположные по направлению тока) идут на датчик. Короткий импульс приводит датчик в рабочее состояние, вычисляются эти Vs, Vr и по формуле постоянно вычисляется смещение. Это позволяет устранить смещение, вызванное рассогласованием датчика из-за магнитных возмущений. Вроде так 05.gif По крайней мере, так я думаю biggrin.gif Потом на основании этих V=(Vr-Vs)/2, считанных с двух выводов(типа х и у координаты магнитного вектора), будет вычисляться азимут. Ну, т.е., должен получиться компас. Пока просто с одним датчиком, потом надо будет подключать акселерометр для измерения кренов. Вычисления желательно делать прямо в мк. штуковина по идее должна выдавать угол и все. Чтобы можно было потом ее везде, где только можно применять без всяких хлопот. Но это все потом, пока вот надо научиться работать с контроллером
Спасибо за участие!
АДИКМ
Как зовут магнитный датчик?
Kurt
Мне нравится с каким упорством девушка двигается к намеченной цели ))
когда-то я делал подобную штуку с магниторезисторами hmc, mems-акселерометрами и msp430.

Если речь идет о датчиках hmc не понятны телодвижения с импульсами. (честно говоря мельком посмотрел, не вникая). У них есть последовательность Set/Reset в процессе которой происходит перемагничивание доменов, в зависимости от реализации схемы, времена управляющих сигналов там порядка десятков мкс и можно обойтись без таймеров. Зачем измерять в процессе перемагничивания непонятно.
Здесь выкладывал несколько примитивных процедур. Может пригодится. Простые примеры работы с АЦП, УАРТ и прочее вы можете посмотреть в TI'шных аппнотах, что-то типа slaa15.
Daria
smile.gif
Цитата(Kurt @ Jun 10 2008, 15:36) *
Мне нравится с каким упорством девушка двигается к намеченной цели ))

С упорством, достойным лучшего применения? biggrin.gif Есть такое дело. Скоро весь форум на уши подниму со своим компасом biggrin.gif Ну так ведь занятно же. И надо. То то смеху будет, если цель когда-нибудь будет достигнута... smile.gif а это, между прочим, очень даже возможно.

Цитата(Kurt @ Jun 10 2008, 15:36) *
когда-то я делал подобную штуку с магниторезисторами hmc, mems-акселерометрами и msp430.

Да? Это как раз то, что мне нужно. smile.gif Именно hmc1002, mems - акселерометр и msp430. А... у вас случайно... не сохранился проект или его куски?.. biggrin.gif Ну, это так, к слову и совершенно не навязчиво wink.gif
Цитата(Kurt @ Jun 10 2008, 15:36) *
Если речь идет о датчиках hmc не понятны телодвижения с импульсами. (честно говоря мельком посмотрел, не вникая). У них есть последовательность Set/Reset в процессе которой происходит перемагничивание доменов, в зависимости от реализации схемы, времена управляющих сигналов там порядка десятков мкс и можно обойтись без таймеров. Зачем измерять в процессе перемагничивания непонятно.

Мне тоже, если честно, не понятно. Но так написано в даташите. Сначала вычисляется Vs, затем OS = (Vr-Vs)/2, а затем постоянно V= Vr-OS. А вы не делали эти телодвижения? smile.gif И, если не трудно. поясните. как без таймера посылать эти импульсы
Цитата(Kurt @ Jun 10 2008, 15:36) *
Здесь выкладывал несколько примитивных процедур. Может пригодится. Простые примеры работы с АЦП, УАРТ и прочее вы можете посмотреть в TI'шных аппнотах, что-то типа slaa15.

Спасибо. простые примеры читаю. примитивные процедуры постараюсь освоить.
Kurt
Цитата(Daria @ Jun 11 2008, 02:19) *
smile.gif
С упорством, достойным лучшего применения? biggrin.gif Есть такое дело. Скоро весь форум на уши подниму со своим компасом biggrin.gif Ну так ведь занятно же. И надо. То то смеху будет, если цель когда-нибудь будет достигнута... smile.gif а это, между прочим, очень даже возможно.
Да? Это как раз то, что мне нужно. smile.gif Именно hmc1002, mems - акселерометр и msp430. А... у вас случайно... не сохранился проект или его куски?.. biggrin.gif Ну, это так, к слову и совершенно не навязчиво wink.gif

Мне тоже, если честно, не понятно. Но так написано в даташите. Сначала вычисляется Vs, затем OS = (Vr-Vs)/2, а затем постоянно V= Vr-OS. А вы не делали эти телодвижения? smile.gif И, если не трудно. поясните. как без таймера посылать эти импульсы

Спасибо. простые примеры читаю. примитивные процедуры постараюсь освоить.


Совершенно неправильно меня поняли, отсюда сарказм. Я уверен, что Вы непременно добьетесь своей цели с нашей помощью или нет. Отсутствие некоторого опыта с лихвой заменяет здоровый энтузиазм и настойчивость. ))
Я постараюсь Вам помочь, надо пошукать в закромах.
Daria
Господа! Как ни странно, оно работает! yeah.gif Ну, в какой-то степени. То есть, координату я считываю, похоже, правильно - загрузилась и поворачивала плату в соответствии со стрелкой обычного компаса, так вот - когда ось датчика параллельна оси компаса, х-вая координата достигает максимального уровня, а, когда ось перпендикулярна стрелке - то уровень напряжения соответствует нулевому. Ну и с другой координатой тоже получается smile.gif Шум только сильный, надо фильтровать. Простое усреднение не поможет? например, брать по 10 отсчетов и усреднять?
И вот теперь такая проблема -
int calculation (x,y,x0,y0,kx0,ky0)
{ (float)((x-x0)*ky0);

return (int) (270 + atan((x-x0)*ky0/(y-y0)*kx0)*180/3,14);

}
void main(void)
{ const int Ox = 2030, Oy = 1810;
const float Kx = 1.3, Ky = 1.3;

int i, Vs[2], Vr[2], offset[2], Vx, Vy, azimut ;
...
и потом

ADC12CTL0 |= ADC12SC + ENC;
Vr[0] = ADC12MEM3;
Vr[1] = ADC12MEM4;
ADC12CTL0 &= ENC;

offset[0] = abs(Vs[0] - Vr[0])/2;
offset[1] = abs(Vs[1] - Vr[1])/2;
Vx=Vr[0]-offset[0];
Vy =Vr[1]-offset[1];
azimut = calculation (Vx,Vy,Ox,Oy,Kx,Ky);
send_int(azimut);

так хочу посчитать угол, вводя пока только ориентировочные калибровочные константы.

Проблема - отношение координат под арктангенсом получается или 0 или 1. Числа int, но ведь вроде так делается переопределение?
Даже вот безотносительно всех этих формул - просто переопределяю int x как float, делю на int y, потом обратно return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1.
Я понимаю, что вопрос, наверное, очень тупой, но не смейтесь, пожалуйста, просветите. Работаю в IAR.

Что касается ответов - rezident, большое спасибо. с опорным напряжением, кажется, разобралась smile.gif Что касается операций + и "или", спасибо, учту. но вот про таймер все же не совсем ясно. Управляющим можно сделать и вывод P1.2, без проблем, но не понятно пока, как использовать выход таймера, ведь 1 должна посылаться все 918 прерываний. Вы, кстати, обещали написать, как бы Вы это сделали. Работает-то оно, вроде работает, но ведь можно, конечно, гораздо лучше сделать, я-то пока чайник из чайников smile.gif Так что будете в наших краях, заглядывайте, жду smile.gif
Kurt, спасибо большое, Ваше письмо получила, обязательно в скором времени зайду, вот только с интернетом пока проблемы, и с реальным временем тоже 05.gif На работе его нет 05.gif
Вот. Такие вопросы, ответьте, кто-нибудь и не смейтесь smile.gif
rezident
Да я не забыл про обещание. Просто пока нет времени, чтобы еще раз осмыслить задачу и написать работающую программу, а не какую-нибудь глюкавую "отписку"-заготовку. Пока лишь временами заглядываю что тут в форуме происходит.
Вам же я посоветую обратить внимание на два момента.
1. если вы хотите задействовать аппаратные возможности таймера по формированию импульсов, то сразу же используйте и аппаратную возможность синхронизации запуска АЦП. Обратите внимание, что вместо того, чтобы программно "дергать" битом ASC12SC можно аппаратно управлять запуском преобразования от сигналов TA1 или TB0, TB1. Т.е. как я и предлагал ранее - формировать времянку с помощью выходного сигнала TA1 и им же управлять запуском АЦП. Конечно же придется разобраться с различными режимами работы выходного модуля таймера, но там все просто. Возможно с точки зрения синхронности работы с АЦП было бы лучше запустить таймер в режиме Count Up с формированием 400мкс интервалов. И уже из этих 400мкс интервалов формировать минутные, переключая лишь режим работы Output Unit TimerA - RESET, SET, SET/RESET.
2. Насчет шумов АЦП и осреднения. Время сэмплирования и преобразования нужно выбирать, исходя в т.ч. из соображений сопротивления источника сигнала. Вы не слишком ли малое время сэмплирования выбрали? Поскольку у вас количество каналов измерения значительно меньше, чем количество каналов АЦП, то усреднение можно сделать полуаппаратно. Запускаете АЦП в режиме последовательности каналов которые сконфигурированы на один и тот же вход АЦП. А затем простым вычислением среднего арифметического значения нескольких значений ADC12MEMx усредняете. Чтобы не нужно было формировать импульс запуска на каждый канал используйте возможности аппаратуры, установив бит MSC в ADC12CTL0 и используя собственный генератор Sample-and-Hold АЦП.
Daria
Цитата(rezident @ Jun 12 2008, 23:18) *
1. если вы хотите задействовать аппаратные возможности таймера по формированию импульсов, то сразу же используйте и аппаратную возможность синхронизации запуска АЦП. Обратите внимание, что вместо того, чтобы программно "дергать" битом ASC12SC можно аппаратно управлять запуском преобразования от сигналов TA1 или TB0, TB1. Т.е. как я и предлагал ранее - формировать времянку с помощью выходного сигнала TA1 и им же управлять запуском АЦП.

Спасибо, постараюсь разобраться smile.gif
Цитата(rezident @ Jun 12 2008, 23:18) *
2. Насчет шумов АЦП и осреднения. Время сэмплирования и преобразования нужно выбирать, исходя в т.ч. из соображений сопротивления источника сигнала. Вы не слишком ли малое время сэмплирования выбрали? Поскольку у вас количество каналов измерения значительно меньше, чем количество каналов АЦП, то усреднение можно сделать полуаппаратно. Запускаете АЦП в режиме последовательности каналов которые сконфигурированы на один и тот же вход АЦП. А затем простым вычислением среднего арифметического значения нескольких значений ADC12MEMx усредняете.

А я вот примерно так и собиралась сделать smile.gif даже и не знаю, как по-другому biggrin.gif спасибо еще раз.
Господа, товарищи, и все же
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Объясните, пожалуйста!
заранее спасибо.
Dog Pawlowa
Цитата(Daria @ Jun 15 2008, 00:39) *
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело?

Я думаю, что дело в том, что x никогда не бывает больше 2y-1.
Я предпочитаю работать с целочисленной арифметикой, но при этом нужно держать в памяти диапазоны возможных значений аргументов. Впрочем, как Вы используете float, тоже нужно smile.gif
rezident
Цитата(Daria @ Jun 15 2008, 03:39) *
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Объясните, пожалуйста!
Это не переопределение, а приведение типа. Чтобы операция деления производилась с числами именно типа float нужно приведение типов сделать непосредственно в выражении
Код
return ((int)((float)x/(float)y))
причем int и второй float можно не указывать, т.к. в операции деления приведение типа к более "высокому" будет сделано автоматически. И результат операции будет приведен к типу int автоматически в соответствии с типом результата, возвращаемым функцией. Но для наглядности можно написать так, как я указал.
Второй способ - использовать временные (локальные) переменные требуемого типа. Большого расхода памяти это не вызовет, т.к. компилятор оптимизирует сам обращение к таким переменным.
Код
float fTmp;
if (y!=0)         //проверка исключения "деление на нуль"
{ fTmp=(float)x;  //приведение типа для наглядности
  fTmp/=(float)y; //опять же здесь приведение типа только для наглядности
}
else
  fTmp=0;        //вынужденная обработка возникшего исключения
return((int)fTmp);
Daria
Большое спасибо, rezident, теперь все получилосьsmile.gif))
rezident
Я рад вашим успехам smile.gif
Кстати, если вам требуется округление, то можно (до преобразования в int) при вычислениях с float прибавлять число 0.5f.
VAI
Цитата
прибавлять число 0.5f.

если число положительное, и вычитать 0.5, если число отрицательное.
Примерно, в общем виде, где-то так:
Код
/* --- round() -------------------------------------------------------------------------------------------- **
*  На выходе получаем округлённый float-результат
*  value    - что округлять
*  accuracy - с какой точностью округлять (например 2. или 0.03 или 0.1 и т.д.)
* -------------------------------------------------------------------------------------------------------- */
float round( float value, float accuracy )
{
  return( ((long)( value / accuracy + ( value < (float)0. ? (float)-0.5 : (float)0.5 ))) * accuracy );
}
Daria
Цитата(rezident @ Jun 17 2008, 00:30) *
Я рад вашим успехам smile.gif

Зря иронизируете, я медленно(очень медленно), но верно расту biggrin.gif
Цитата(rezident @ Jun 17 2008, 00:30) *
Кстати, если вам требуется округление, то можно (до преобразования в int) при вычислениях с float прибавлять число 0.5f.

Спасибо за совет - пригодится smile.gif



Цитата(VAI @ Jun 17 2008, 07:32) *
если число положительное, и вычитать 0.5, если число отрицательное.
Примерно, в общем виде, где-то так...

Спасибо, VAI.
rezident
Цитата(Daria @ Jun 18 2008, 01:48) *
Зря иронизируете, я медленно(очень медленно), но верно расту biggrin.gif
Никакой иронии! Это чистосердечно. Смайлик неподходящий выбрал. Вот такие надо было. a14.gif
Daria
Здравствуйте, и снова вопросы smile.gif много, много вопросов smile.gif
1.!! Сначала по поводу усреднения отсчетов для уменьшения шума -
предлагали использовать бит MSC в регистре ADC12CTL0. Правильно ли я понимаю, что тогда значения выборок будут постоянно(до сброса бита ENC) записываться в регистры ADC12MEMx, и получить усредненное значение можно считывая значения из разных регистров ADC12MEMx и деля на их количество? Но у меня 16 каналов АЦП, задействовано в дальнейшем будет 5. Т.е. я могу использовать для усреднения только три значения из регистров ADC12MEMx - маловато будет... sad.gif
ну, или я все же не понимаю, поясните тогда принцип использования бита MSC.
Делаю усреднение пока так(знаю, что криво, но)
int filter(int r[10])// среднее арифметическое 10 значений
{
int s, t;
s = 0;
for(t = 0 ; t < 10 ; t++)
s+=r[t];
return s/10;
}
...
ADC12CTL0 = ADC12ON + REFON + SHT0_8;// настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+ SHS_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
index = 0;
...
И, собственно
if (TACCTL0 & CCIFG)// если таймер переключился
{

if (P1OUT & BIT5)// и, если вывод все еще в единице,т.е. еще идет длинный импулсьс
{

ADC12CTL0 |= ENC;
Vr[0][index] = ADC12MEM3; // записываем в массив значения из ADC12MEMх
Vr[1][index] = ADC12MEM4;
ADC12CTL0 &= ENC;

index++;
if (index >= 10)// когда значений в массиве 10
{
index = 0;
offset[0] = (Vs[0] - filter(Vr[0]))/2; // Вычисление смещений уровня сигнала
offset[1] = (Vs[1] - filter(Vr[1]))/2;

Vx = filter(Vr[0]) - offset[0]; //вычисление координат вектора маг.индукции
Vy = filter(Vr[1]) - offset[1];

azimut = calculation (Vx,Vy); //вычисление азимута

}


send_int(azimut);

} send_int(azimut) - вычисленный азимут посылается на СOM. Описание send_int было выше в теме, да и не в ней суть, на вычисления тоже можно не обращать внимания smile.gif
ВОПРОС! -
2.!! В данном случае вычисляю азимут 10 раз, а посылаю только один. т.е. 10 раз посылается одно и то же значение. Если переношу строчку send_int(azimut); под строку
azimut = calculation (Vx,Vy); - т.е. сразу после вычисления и отправляю, то программа не работает sad.gif На СOM ничего не приходит! 07.gif Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?!
3.!! Вопрос не по теме MSP430, уж извините, но вдруг кто-нибудь знает - Когда считываю уровень сигнала с датчика, он самопроизвольно "плывет", плата лежит неподвижно, а уровень за минуту убегает довольно прилично, при вычислении азимута получается, что в минуту градусов +/- 5 07.gif С чем это может быть связано? Датчик, напоминаю, HMC1002 biggrin.gif Вопрос в основном к Курту, если он заглянет. Да, Kurt, отправила Вам письмо - загляните в ящик - там еще куча вопросов по компасу конкретно biggrin.gif Ну, Вы сами обещали помочь biggrin.gif
Ну вот, пока все - помогите, кто может чем сможет biggrin.gif Не ругайте за безграмотность и всех
с победой сбороной России biggrin.gif yeah.gif
rezident
Цитата(Daria @ Jun 22 2008, 21:37) *
ну, или я все же не понимаю, поясните тогда принцип использования бита MSC.
Бит MSC не имеет прямого отношения к усреднению. Он лишь позволяет автоматически запускать таймер сэмплирования (Sample Timer) после каждого преобразования (если выбран режим последовательности каналов). На блок-схеме из User's Guide хорошо видно, что устройство выборки-хранения (Sample-and-Hold или УВХ в отечественной терминологии), подключенное к входному 16-и канальному мультиплексору управляется сигналом SAMPCON. Лог.1. SAMPCON включает режим выборки, в котором конденсатор УВХ заряжается до напряжения входного сигнала, подключенного к выбранному входу мультиплексора, а лог.0 отключает УВХ от мультиплексора и запускает преобразование. Длительность лог.1 задается таймером сэмплирования, либо внешним сигналом в обход таймера сэмплирования. Сам таймер сэмплирования запускается по фронту сигнала SHI, который формируется либо программно от ADC12SC, либо одним из трех внешних сигналов от модулей таймера A или таймера B. Так вот установка бита MSC позволяет не ждать фронта сигнала SHI для запуска каждого последующего преобразования, а формировать его аппаратно по окончании предыдущего преобразования. Но это все работает только, если выбран режим управления от Sample Timer и режим последовательности каналов.
Цитата(Daria @ Jun 22 2008, 21:37) *
Делаю усреднение пока так(знаю, что криво, но)
int filter(int r[10])// среднее арифметическое 10 значений
{
int s, t;
s = 0;
for(t = 0 ; t < 10 ; t++)
s+=r[t];
return s/10;
}
Ну некоторая "кривизна" присутствует только при передаче аргумента функции. Передавать следует указатель на массив отсчетов и возможно еще и длину этого массива.
Код
int filter(int *ptr, int size)
{ int s=0, t;
  for(t=0; t<size; t++)
  s+=*ptr;
  ptr++;
  if (size>0)  //проверим на исключение "деление на нуль"
    return (s/size);
  else
    return 0;
}

Вызов функции будет такой
Код
x=filter(r, 10);

или
Код
x=filter(&r[0], 10);

Передавать второй аргумент имеет смысл потому, что если вы неправильно неудачно выбрали времена, то у вас будет заполнен не весь буфер. Т.е. за выбранное время будет меньше 10 преобразований. См. ниже про эту потенциальную ошибку.
Цитата(Daria @ Jun 22 2008, 21:37) *
...
ADC12CTL0 = ADC12ON + REFON + SHT0_8;// настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+ SHS_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
index = 0;
...
Еще раз обращаю внимание, что во избежание ошибок при формировании слова из отдельных битов следует пользоваться побитовым ИЛИ '|', а не оператором сложения '+'.
Цитата(Daria @ Jun 22 2008, 21:37) *
И, собственно

if (P1OUT & BIT5)// и, если вывод все еще в единице,т.е. еще идет длинный импулсьс
{
Здесь возможно имеется потенциальная алгоритмическая ошибка. Проверять нужно не только до начала преобразования, но и после окончания преобразования. И если после окончания преобразования бит сменил свое состояние, то результат последнего преобразования нужно отбрасывать. Следовательно у вас может быть не 10 отсчетов, а меньше. Поэтому выше я предложил передавать в функцию фильтрации еще и реальную длину буфера отсчетов.
Цитата(Daria @ Jun 22 2008, 21:37) *
2.!! В данном случае вычисляю азимут 10 раз, а посылаю только один. т.е. 10 раз посылается одно и то же значение. Если переношу строчку send_int(azimut); под строку
azimut = calculation (Vx,Vy); - т.е. сразу после вычисления и отправляю, то программа не работает sad.gif На СOM ничего не приходит! 07.gif Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?!
Затрудняюсь сходу дать однозначный ответ, но думаю, что причиной является факт, что получение значения измерения и передача его через UART это процессы вообще-то асинхронные, но вы их пытаетесь принудительно синхронизировать без использования буферов. Вы используете передачу по опросу бита готовности, а не по прерыванию. А каждая передача "тормозит" измерения на время передачи двух символов. Поэтому за тот же самый интервал времени (который у вас фиксированный и определяется таймером) вы получаете меньше отсчетов, чем предполагаемое вами количество (10). Следовательно условие if (index >= 10) не выполняется, результата azimut вы не получаете, и передача через UART тоже не идет. Для решения этой проблемы рекомендую использовать передачу по прерываниям и формировать для передачи свой собственный буфер, линейный или циклический.

По 3-му вопросу ответить не могу. Я не "копенгаген", да и с подобными датчиками я не работал laughing.gif
Daria
Здравствуйте снова.
Rezident, спасибо за подробный разбор, но вот я начала после Ваших комментов разбираться и окончательно зависла 07.gif biggrin.gif
Во-первых, после того, как фильтр сделала по Вашему совету - с делением не на 10, а на index. числа начали получаться жуткими и бессмысленными, вразнобой и без всякой связи с поворотом платы - как это можно объяснить? 07.gif
Во-вторых, я, наивная, полагала, что преобразование АЦП запускается сейчас синхронно с переключением таймера, я ведь вроде не битом ADC12SC "дергаю", а ставлю бит SHS_1 в ADC12CTL1 - т.е использую выход таймера А1... или нет? Проверка if (P1OUT & BIT5) идет не перед стартом преобразования, а перед тем, как записывать новый элемент в массив, т.е. как раз то, о чем Вы говорите... так мне казалось smile.gif
В третьих, тут вроде все советовали как раз использовать как можно меньше прерываний, лучше вообще без них, вот и стараюсь без них smile.gif
и вообще - Вы обещали рассказать, как в данном случае не программно дергать P1OUT, а использовать выход таймера - как это можно сделать, ведь изменение состояния вывода должно произойти только через 918 переключений таймера 05.gif
И все-таки вопрос - почему send_int(azimut) нельзя перенести в то место, в которое хочется smile.gif ? Если бы условие if (index >= 10) никогда не выполнялось, то и вычисление никогда не происходило бы, а что-то таки вычисляется. Без фильтра работает smile.gif только сильно скачет, что не есть хорошо.
Вот такие непонятки smile.gif
будет время, ответьте, пожалуйста.
rezident
Daria, давайте все исходники (весь проект). Варианты возможных нюансов в многоветвистое дерево вырастают, а телепатия что-то тяжело нынче идет smile.gif
Я бы вам посоветовал отладить работу АЦП не с датчиком, а с постоянными напряжениями для начала. Вы еще не до конца разобрались с синхронной работой ADC12 и TimerA и вообще с функционированием ADC12.
Daria
Цитата(rezident @ Jun 25 2008, 00:13) *
Я бы вам посоветовал отладить работу АЦП не с датчиком, а с постоянными напряжениями для начала.

да пробовала smile.gif Вроде нормально идет. Правда, пробовала без всяких усреднений...
Цитата(rezident @ Jun 25 2008, 00:13) *
Вы еще не до конца разобрались с синхронной работой ADC12 и TimerA и вообще с
функционированием ADC12.

Эт точно biggrin.gif да и с USART похоже тоже. Видимо все дело в том, как я отправляю число. Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме? Пробовала без флажка 0xFF, означающего конец посылки, но при "слеплении" получаются ошибки.
вы говорили, что нужно как-то по прерываниям работать, как? smile.gif Да, вот что странно, когда я разрешаю прерывания по передаче, вообще перестает работать.
А проект пока маленький совсем, прикладываю текст.
Не ругайтесь на "+", я потом обязательно исправлю, все как-то недосуг smile.gif
Вообще спасибо за поддержкуsmile.gif
NoName
Цитата(Daria @ Jun 25 2008, 21:18) *
Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме?


Имеет смысл сразу организовать протокол обмена.
Пример:
адрес получателя 1 или 2 байта
идентификатор пакета 2 байта - соответвует идентификатору запроса.
длина данных пакета 1 или 2байт
данные []
адрес отправителя 1 или 2 байта
СRC 2 байт

истина прописная, протокол то все равно прийдется организовывать )))
либо воспользоватся общепринятыи протоколом для Вашей конторы ...
Daria
Цитата(NoName @ Jun 26 2008, 18:11) *
Имеет смысл сразу организовать протокол обмена.
либо воспользоватся общепринятыи протоколом для Вашей конторы ...

Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договариваетсяsmile.gif А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего?
Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла smile.gif Чутка попозже. Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет?
rezident
Цитата(Daria @ Jun 27 2008, 00:44) *
Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договариваетсяsmile.gif А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего?
Для вывода одного числа будет удобно, если преобразовать его в строку символов ASCII. Тогда это число можно будет наблюдать в обычной терминальной программе без доп. ухищрений. например, для вывода числа 360, нужно вывести последовательно 0x33, 0x36, 0x30, 0x0D, 0x0A. Можно даже значок градусов ° (0xB0) в конце строки перед символами CR, LF добавлять smile.gif
Цитата(Daria @ Jun 27 2008, 00:44) *
Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла smile.gif Чутка попозже.
Начал править ваш проект из предыдущего сообщения, но чувствую, что сегодня уже не доделаю. Спать хочется. Вы еще раз уточните какие входы/выходы у вас используются? А то немного непонятно. Сначала разговор про одни шел, а в проекте вроде другие выводы MSP430 используются.
5 аналоговых входов или только 2?
Управляющие сигналы на P1.5 и P1.6 изменяются синхронно? 60сек - лог.1. и 400мс - лог.0, так?
Допустимо выводить на UART строку символов вместо бинарного числа?
Цитата(Daria @ Jun 27 2008, 00:44) *
Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет?
Блочный режим используется, если управляющая программа записи в ОЗУ расположена. Если же у вас программа записи исполняется прямо из Flash, то можно писать побайтово или пословно.
Daria
Цитата(rezident @ Jun 27 2008, 00:30) *
5 аналоговых входов или только 2?
Управляющие сигналы на P1.5 и P1.6 изменяются синхронно? 60сек - лог.1. и 400мс - лог.0, так?

Пока два, потом будет пять. Аналоговые входы P6.3, P6.4. Управляющий только один - P1.5, 60сек - лог.1. и 400мс - лог.0
Цитата(rezident @ Jun 27 2008, 00:30) *
Допустимо выводить на UART строку символов вместо бинарного числа?

Да все равно как, главное, видеть, что приходит smile.gif

Цитата(rezident @ Jun 27 2008, 00:30) *
Блочный режим используется, если управляющая программа записи в ОЗУ расположена. Если же у вас программа записи исполняется прямо из Flash, то можно писать побайтово или пословно.

Но слово - это же два байта вроде?.. То есть писать функцию, которая пословно записывает число, и функцию, которая будет пословно считывать?
NoName
Цитата(Daria @ Jun 26 2008, 21:44) *
Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договариваетсяsmile.gif А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего?
Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла smile.gif Чутка попозже. Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет?


Daria пишите побайтово - последовательно записывая 2 байта (short), когда пишете флоат - пишите 4 байта, будет работать также хорошо ( данные пишете во flash MSP что ли?? )
---------------------------------
CR, LF - '\r'.'\n' )) вариант с выводом в терминал конешно хорош.
но это только на этапе проверки фукционирования устройства.

используюя протокол Вы можете использовать различные режимы настройки без перепрошики
в общем я за написания протокола + внешней программы в которой можете уже смотреть и настраивать как Вам будет угодно. )
Daria
Цитата(NoName @ Jun 29 2008, 15:23) *
Daria пишите побайтово - последовательно записывая 2 байта (short), когда пишете флоат - пишите 4 байта, будет работать также хорошо ( данные пишете во flash MSP что ли?? )

Да, пишу во flash MSP - после калибровки датчика нужно сохранять калибровочные константы в памяти.
Цитата(NoName @ Jun 29 2008, 15:23) *
в общем я за написания протокола + внешней программы в которой можете уже смотреть и настраивать как Вам будет угодно. )

Спасибо, попробую.
Dog Pawlowa
Цитата(Daria @ Jun 26 2008, 21:44) *
Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договариваетсяsmile.gif А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего?

Имеет - не имеет? Придется!
Информация в один байт не помещается, значит их будет больше. Тогда на приемной стороне нужно распознавать, какой байт первый а какой второй (приемник ведь может включиться в любой момент).
Можно сделать просто - например, выделить старший разряд для передачи флага первый/второй, а во всех остальных передавать данные. Тогда в двух байтах можно передать 14 значащих разрядов. Запишите на бумажке правила, как именно Вы будете передавать данные - это и будет называться гордым словом ПРОТОКОЛ - правила, однозначно устанавливающие порядок приема и передачи информации. smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.