|
MSP430 - вопросы от чайника, генератор опорного напряжения |
|
|
|
 |
Ответов
(1 - 55)
|
May 18 2008, 20:19
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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 не подскажу, т.к. не использую эту среду разработки.
|
|
|
|
|
May 26 2008, 08:42
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(rezident @ May 25 2008, 22:58)  Вам нужен готовый или схема для самостоятельного изготовления? Готовые - пожалуйста, в большом ассортименте в Терраэлектронике. А если хотите сами делать, то схемы оригинальных MSP-FET430PIF (LPT) и MSP-FET430UIF (USB) имеются в апликухе от производителя - slau138. Прошивку для MSP-FET430UIF где-то тут в форуме выкладывали. Большое спасибо
|
|
|
|
|
Jun 3 2008, 19:24
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Здравствуйте. Такой вопрос - запускаю таймер( в TACCRO записываю 50000), в обработчике прерываний посылаю на COM число 0хАА, передаю и принимаю на скорости 9600, число исправно приходит, но на каждом 30-м и 31-м шаге появлются какие-то лишние биты, получается 0хЕА и 0хСА. Есть варианты, почему это может происходить? Посылаю с вывода P3.4, при начальной конфигурации записываю P3SEL=Bit4, P3OUT=0(на всякий случай). На эмуляторе видно, что таймер работает и в буфере передачи только 0хаа. (Но достаточно долго наблюдать работу не получается, так как происходит переполнение стека - почему, кстати, оно происходит?) Я не считаю модуляцию, U0MCTL оставляю нулевым - может, в этом дело? Но нужно ли считать модуляцию при такой скорости? Частота тактирования 8МГц. Заранее спасибо, если кто ответит.
Сообщение отредактировал Daria - Jun 3 2008, 19:25
|
|
|
|
|
Jun 3 2008, 22:07
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Что-то полная путаница. При чем тут модуль TimerA, если для передачи вы пользуетесь модулем USART0? Вы бы хоть кусок кода привели. Как именно инициализируете модули, а особенно систему тактирования? Как выглядят обработчики прерываний? Что за кристалл вообще вы используете? В сообщениях выше вы "махнули рукой", а теперь снова не уточнив ничего мечетесь с вопросами. Насчет делителя и модуляции. 8000000/9600=833,3(3). Значение для делителя 0x0341, если представлять его как целое число в HEX формате. Если не использовать модулятор, то получается реальный битрейт 8000000/833=9603,8 и ошибка составляет меньше 0,05%. Для UART такая ошибка сущие мелочи. Так что думаю проблема у вас не там, где в программе приемо-передача, а как это обычно бывает у новичков, там где инициализация источников тактирования. Переполнения стека бывают чаще всего при использовании функций активно его использующих (типа printf/sprintf) и/или при неконтролируемом использовании вложенных прерываний.
|
|
|
|
|
Jun 4 2008, 04:38
|

Частый гость
 
Группа: Участник
Сообщений: 99
Регистрация: 22-06-06
Из: Сарапула
Пользователь №: 18 275

|
Цитата(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 скорее всего никак не связана с таймером. Прпробуйте отладить передатчик отдельно от таймера. От себя хочу посоветовать посмотреть, как происходит контроль бита четности на приемнике и передатчике, т.е. устанавливается ли он (и каким образом) передатчиком и контролируется ли он (и каким образом) приемником... Механизм переполнения стэка примерно такой: когда вызывается подпрограмма (в т.ч. обработки прерывания) регистр состояния проца, адрес возврата и передаваемые подпрограмме переменные (если они есть) закидываются в стек, после окончания подпрограммы они оттуда удаляются. Если в процессе выполнения подпрограммы снова происходит вызов подпрограммы (более приоритетное прерывание или вложенная подпрограмма), происходит то же самое (регистр состояния и пр. закидывается в стек) и размер стека увеличивается. Если и дальше производить вызовы подпрограмм рано или поздно данные, загружаемы в стек, попадут в облать переменных или "кучи" и будут модифицированы случайными значениями, которые в свою очередь будут испольованы как регистр состояния или адрес возврата при выходе из подпрограммы.
--------------------
Сделал трэш - разбудил Ктулху!!!
|
|
|
|
|
Jun 5 2008, 19:51
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Спасибо, следуя вашему совету, начинаю разбираться с начала. Вот текст простенькой программки работы таймера, с которой все начиналось #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? Вот пока такой вопрос
Сообщение отредактировал Daria - Jun 5 2008, 19:55
|
|
|
|
|
Jun 6 2008, 20:02
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(rezident @ Jun 6 2008, 04:08)  А у вас высокочастотный кварц 8Мгц куда подключен? К генератору XT1/LFXT что ли? Что за кристал-то в конце-концов у вас??? Это военная тайна или вы внучка-последовательница Зои Космодемьянской? И не нужно какой-то абстрактный пример приводить, приведите текст реальной программы, которую вы используете! Пускай он выглядит как угодно некузяво. В примере же вами приведенном как минимум имеется один недочет, связанный с алгоритмом инициализации системы тактирования. Но раз вы не желаете диалога, то читайте Chapter 4..2 Basic Clock Module Operation из MSP430x1xx Family User's Guide самостоятельно и с тщательным вниманием. Желаю я диалога, очень желаю!  Никакая не тайна, просто по рассеянности все время забываю указать кристалл - MSP430F149, кварц подключен к XT1/LFXT, пример вполне конкретный - начиная разбираться, я закомментила все, кроме вот этого текста, который Вам привела. и вот такая ошибка, которую не могу понять. Тактовая частота 8МГц, делю на 8 (ID_3), получается, что один такт - 1 мкс, задаю длительности, и получаю, что при уменьшении с 500 на 400 длительность импульса на осциллографе изменяется совсем чуть-чуть, а при дальнейшем уменьшении - вообще не изменяется. А вот если задать 1000 и больше - то все нормально. Вы же сами говорили не кидаться кучей вопросов, а разбираться с нуля. ну вот. Не ругайтесь на меня, пожалуйста  :)USART действительно вполне нормально инициилизирован, я проверяла без таймера, так что наверное все дело в этом. А руководство я читаю, вникаю, пыхчу, но вот никак пока не получается, может - не дано, а, может просто опыта нет - что такое контроллер - узнала только зимой  бывают такие темные личности. А, если Вам, действительно, не лень разбираться в моей проге - то обязательно приведу весь текст. со всей некузявостью, но он и сам пока небольшой
Сообщение отредактировал Daria - Jun 6 2008, 20:06
|
|
|
|
|
Jun 6 2008, 20:45
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
При использовании высокочастотного кварца нужна определенная последовательность действий в процедуре инициализации модуля тактирования. По старту тактирование 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; }
|
|
|
|
|
Jun 8 2008, 17:22
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Здравствуйте, снова я  Опять проблемы привожу весь свой маленький текст, чтобы не ругались потом. будто что-то скрываю #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. То, что буфере один байт, а число получается двухбайтовым, я знаю  , посылаю пока младший байт, не в этом суть. В ЧЕМ ПРОБЛЕМА - напряжения на 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 - извините за глупые вопросы, но вот непонятно И вообще, если кому-то вдруг не лень будет почитать текст - есть ли здесь ошибки при конфигурировании АЦП или USART? Заранее огромное спасибо
|
|
|
|
|
Jun 9 2008, 19:52
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Нет, тут опять ошибки  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, потом флаг. Как можно это сделать проще? Ау, кто-нибудь
|
|
|
|
|
Jun 9 2008, 20:24
|

Знающий
   
Группа: Свой
Сообщений: 630
Регистрация: 2-08-05
Пользователь №: 7 294

|
Посылать по 6 бит никто не запрещает конечно, но все таки лучше посылать например сначала младший байт, потом старший . а уже в компьютере их склеивать. Тем более, что ничего вы не теряете. примерно так - mov &adc12mem0 , r10 - копируем результат измерения mov.b r10, &TXBUF0 - передаем младший байт ждем UTXIFG0 swpb r10 mov.b r10, &TXBUF - передаем старший байт ждем UTXIFG0 я бы порекомендовал вам посмотреть на эту книгу. там очень хорошо описаны многие вопросы, правда на английском
--------------------
летаю на пепелаце...
|
|
|
|
|
Jun 9 2008, 20:47
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(АДИКМ @ Jun 10 2008, 00:24)  Посылать по 6 бит никто не запрещает конечно, но все таки лучше посылать например сначала младший байт, потом старший . а уже в компьютере их склеивать. Тем более, что ничего вы не теряете. Проблема в том, как потом записать флаг. Любое число не будет уникальным, если младший байт будет 8-ми битовым. А так получается, что 0xFF никогда не может прийти в младшем байте. Мысль была такая.  Или я чего-то не понимаю? Книгу обязательно почитаю, спасибо
|
|
|
|
|
Jun 9 2008, 21:10
|

Знающий
   
Группа: Свой
Сообщений: 630
Регистрация: 2-08-05
Пользователь №: 7 294

|
Цитата(Daria @ Jun 9 2008, 23:47)  Проблема в том, как потом записать флаг. Любое число не будет уникальным, если младший байт будет 8-ми битовым. А так получается, что 0xFF никогда не может прийти в младшем байте. Мысль была такая.  Или я чего-то не понимаю? Книгу обязательно почитаю, спасибо Расскажите, что это за флаг и почему число должно быть уникальным? Далее, что Вы измеряете и какой амплитуды у Вас сигнал? С какой позиции выбрано опорное 1.5 В, а не 2.5 или 3.3 ? Если Вы передаете данные в компьютер, то гораздо проще переложить вычисления на него. Ну или расскажите, что Вы задумали сделать.
--------------------
летаю на пепелаце...
|
|
|
|
|
Jun 9 2008, 21:21
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Daria @ Jun 8 2008, 23:22)  Здравствуйте, снова я  Опять проблемы привожу весь свой маленький текст, чтобы не ругались потом. будто что-то скрываю  Текст программы пока комментировать не буду, лучше после уточнений приведу для сравнения свой вариант. Сделаю лишь несколько замечаний. 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. То, что буфере один байт, а число получается двухбайтовым, я знаю  , посылаю пока младший байт, не в этом суть. Опять-таки лучше было бы посылать не просто код, а преобразовывать его в символьную строку. Тогда результат можно наблюдать даже в виндусовом гипертерминале. А если напряжение вычислять не в абстрактных попугаях, а, например, в миллиВольтах, то для вычислений не понадобится даже плавающая арифметика и результат измерения будет достаточно точным. Цитата(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 - извините за глупые вопросы, но вот непонятно  А вот здесь мне непонятно. Что за двуполярное напряжение? На вход АЦП можно подавать сигнал, который попадает в диапазон от 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? После уточнения параметров задания с вашей стороны приведу свой вариант программы.
|
|
|
|
|
Jun 9 2008, 22:00
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(АДИКМ @ Jun 10 2008, 01:10)  Расскажите, что это за флаг и почему число должно быть уникальным? Далее, что Вы измеряете и какой амплитуды у Вас сигнал? С какой позиции выбрано опорное 1.5 В, а не 2.5 или 3.3 ? Если Вы передаете данные в компьютер, то гораздо проще переложить вычисления на него. Ну или расскажите, что Вы задумали сделать. Пробовала сначала просто посылать один байт, потом другой. но получалась путаница. Поэтому отправляю байт, означающий конец посылки. С опорным, если честно, не понятно. выбрано потому, что по схеме вроде требуется 1,5 В напряжения для правильного включения усилителя мощности - вот с Vref+ и подается. А что дальше с ним делать не знаю  Темная я, темная  Что хочу сделать, сейчас расскажу - в ответе rezident Спасибо за участие! Так. Режим переполнения таймера я пока не разбирала  Так что сейчас, да еще ночью, если честно не все ясно. Просмотрю внимательно Ваши комментарии утром, спасибо огромное, кстати Чего хочу сделать - вообще когда-нибудь это должно стать программой цифрового компаса  Для правильной работы магнитного датчика необходимо подавать с мк такие импульсы на преобразователь IRF7105, с выводов IRF7105 (транзисторная сборка) импульсы(получаются противоположные по направлению тока) идут на датчик. Короткий импульс приводит датчик в рабочее состояние, вычисляются эти Vs, Vr и по формуле постоянно вычисляется смещение. Это позволяет устранить смещение, вызванное рассогласованием датчика из-за магнитных возмущений. Вроде так  По крайней мере, так я думаю  Потом на основании этих V=(Vr-Vs)/2, считанных с двух выводов(типа х и у координаты магнитного вектора), будет вычисляться азимут. Ну, т.е., должен получиться компас. Пока просто с одним датчиком, потом надо будет подключать акселерометр для измерения кренов. Вычисления желательно делать прямо в мк. штуковина по идее должна выдавать угол и все. Чтобы можно было потом ее везде, где только можно применять без всяких хлопот. Но это все потом, пока вот надо научиться работать с контроллером Спасибо за участие!
Сообщение отредактировал Daria - Jun 9 2008, 22:11
|
|
|
|
|
Jun 10 2008, 11:36
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 16-06-04
Из: Россия, Уфа
Пользователь №: 31

|
Мне нравится с каким упорством девушка двигается к намеченной цели )) когда-то я делал подобную штуку с магниторезисторами hmc, mems-акселерометрами и msp430. Если речь идет о датчиках hmc не понятны телодвижения с импульсами. (честно говоря мельком посмотрел, не вникая). У них есть последовательность Set/Reset в процессе которой происходит перемагничивание доменов, в зависимости от реализации схемы, времена управляющих сигналов там порядка десятков мкс и можно обойтись без таймеров. Зачем измерять в процессе перемагничивания непонятно. Здесь выкладывал несколько примитивных процедур. Может пригодится. Простые примеры работы с АЦП, УАРТ и прочее вы можете посмотреть в TI'шных аппнотах, что-то типа slaa15.
|
|
|
|
|
Jun 10 2008, 20:19
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(Kurt @ Jun 10 2008, 15:36)  Мне нравится с каким упорством девушка двигается к намеченной цели )) С упорством, достойным лучшего применения?  Есть такое дело. Скоро весь форум на уши подниму со своим компасом  Ну так ведь занятно же. И надо. То то смеху будет, если цель когда-нибудь будет достигнута...  а это, между прочим, очень даже возможно. Цитата(Kurt @ Jun 10 2008, 15:36)  когда-то я делал подобную штуку с магниторезисторами hmc, mems-акселерометрами и msp430. Да? Это как раз то, что мне нужно.  Именно hmc1002, mems - акселерометр и msp430. А... у вас случайно... не сохранился проект или его куски?..  Ну, это так, к слову и совершенно не навязчиво Цитата(Kurt @ Jun 10 2008, 15:36)  Если речь идет о датчиках hmc не понятны телодвижения с импульсами. (честно говоря мельком посмотрел, не вникая). У них есть последовательность Set/Reset в процессе которой происходит перемагничивание доменов, в зависимости от реализации схемы, времена управляющих сигналов там порядка десятков мкс и можно обойтись без таймеров. Зачем измерять в процессе перемагничивания непонятно. Мне тоже, если честно, не понятно. Но так написано в даташите. Сначала вычисляется Vs, затем OS = (Vr-Vs)/2, а затем постоянно V= Vr-OS. А вы не делали эти телодвижения?  И, если не трудно. поясните. как без таймера посылать эти импульсы Цитата(Kurt @ Jun 10 2008, 15:36)  Здесь выкладывал несколько примитивных процедур. Может пригодится. Простые примеры работы с АЦП, УАРТ и прочее вы можете посмотреть в TI'шных аппнотах, что-то типа slaa15. Спасибо. простые примеры читаю. примитивные процедуры постараюсь освоить.
|
|
|
|
|
Jun 11 2008, 03:18
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 16-06-04
Из: Россия, Уфа
Пользователь №: 31

|
Цитата(Daria @ Jun 11 2008, 02:19)  С упорством, достойным лучшего применения?  Есть такое дело. Скоро весь форум на уши подниму со своим компасом  Ну так ведь занятно же. И надо. То то смеху будет, если цель когда-нибудь будет достигнута...  а это, между прочим, очень даже возможно. Да? Это как раз то, что мне нужно.  Именно hmc1002, mems - акселерометр и msp430. А... у вас случайно... не сохранился проект или его куски?..  Ну, это так, к слову и совершенно не навязчиво Мне тоже, если честно, не понятно. Но так написано в даташите. Сначала вычисляется Vs, затем OS = (Vr-Vs)/2, а затем постоянно V= Vr-OS. А вы не делали эти телодвижения?  И, если не трудно. поясните. как без таймера посылать эти импульсы Спасибо. простые примеры читаю. примитивные процедуры постараюсь освоить. Совершенно неправильно меня поняли, отсюда сарказм. Я уверен, что Вы непременно добьетесь своей цели с нашей помощью или нет. Отсутствие некоторого опыта с лихвой заменяет здоровый энтузиазм и настойчивость. )) Я постараюсь Вам помочь, надо пошукать в закромах.
|
|
|
|
|
Jun 12 2008, 15:35
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Господа! Как ни странно, оно работает!  Ну, в какой-то степени. То есть, координату я считываю, похоже, правильно - загрузилась и поворачивала плату в соответствии со стрелкой обычного компаса, так вот - когда ось датчика параллельна оси компаса, х-вая координата достигает максимального уровня, а, когда ось перпендикулярна стрелке - то уровень напряжения соответствует нулевому. Ну и с другой координатой тоже получается  Шум только сильный, надо фильтровать. Простое усреднение не поможет? например, брать по 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, большое спасибо. с опорным напряжением, кажется, разобралась  Что касается операций + и "или", спасибо, учту. но вот про таймер все же не совсем ясно. Управляющим можно сделать и вывод P1.2, без проблем, но не понятно пока, как использовать выход таймера, ведь 1 должна посылаться все 918 прерываний. Вы, кстати, обещали написать, как бы Вы это сделали. Работает-то оно, вроде работает, но ведь можно, конечно, гораздо лучше сделать, я-то пока чайник из чайников  Так что будете в наших краях, заглядывайте, жду Kurt, спасибо большое, Ваше письмо получила, обязательно в скором времени зайду, вот только с интернетом пока проблемы, и с реальным временем тоже  На работе его нет Вот. Такие вопросы, ответьте, кто-нибудь и не смейтесь
|
|
|
|
|
Jun 12 2008, 19:18
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Да я не забыл про обещание. Просто пока нет времени, чтобы еще раз осмыслить задачу и написать работающую программу, а не какую-нибудь глюкавую "отписку"-заготовку. Пока лишь временами заглядываю что тут в форуме происходит. Вам же я посоветую обратить внимание на два момента. 1. если вы хотите задействовать аппаратные возможности таймера по формированию импульсов, то сразу же используйте и аппаратную возможность синхронизации запуска АЦП. Обратите внимание, что вместо того, чтобы программно "дергать" битом ASC12SC можно аппаратно управлять запуском преобразования от сигналов TA1 или TB0, TB1. Т.е. как я и предлагал ранее - формировать времянку с помощью выходного сигнала TA1 и им же управлять запуском АЦП. Конечно же придется разобраться с различными режимами работы выходного модуля таймера, но там все просто. Возможно с точки зрения синхронности работы с АЦП было бы лучше запустить таймер в режиме Count Up с формированием 400мкс интервалов. И уже из этих 400мкс интервалов формировать минутные, переключая лишь режим работы Output Unit TimerA - RESET, SET, SET/RESET. 2. Насчет шумов АЦП и осреднения. Время сэмплирования и преобразования нужно выбирать, исходя в т.ч. из соображений сопротивления источника сигнала. Вы не слишком ли малое время сэмплирования выбрали? Поскольку у вас количество каналов измерения значительно меньше, чем количество каналов АЦП, то усреднение можно сделать полуаппаратно. Запускаете АЦП в режиме последовательности каналов которые сконфигурированы на один и тот же вход АЦП. А затем простым вычислением среднего арифметического значения нескольких значений ADC12MEMx усредняете. Чтобы не нужно было формировать импульс запуска на каждый канал используйте возможности аппаратуры, установив бит MSC в ADC12CTL0 и используя собственный генератор Sample-and-Hold АЦП.
|
|
|
|
|
Jun 14 2008, 21:39
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(rezident @ Jun 12 2008, 23:18)  1. если вы хотите задействовать аппаратные возможности таймера по формированию импульсов, то сразу же используйте и аппаратную возможность синхронизации запуска АЦП. Обратите внимание, что вместо того, чтобы программно "дергать" битом ASC12SC можно аппаратно управлять запуском преобразования от сигналов TA1 или TB0, TB1. Т.е. как я и предлагал ранее - формировать времянку с помощью выходного сигнала TA1 и им же управлять запуском АЦП. Спасибо, постараюсь разобраться Цитата(rezident @ Jun 12 2008, 23:18)  2. Насчет шумов АЦП и осреднения. Время сэмплирования и преобразования нужно выбирать, исходя в т.ч. из соображений сопротивления источника сигнала. Вы не слишком ли малое время сэмплирования выбрали? Поскольку у вас количество каналов измерения значительно меньше, чем количество каналов АЦП, то усреднение можно сделать полуаппаратно. Запускаете АЦП в режиме последовательности каналов которые сконфигурированы на один и тот же вход АЦП. А затем простым вычислением среднего арифметического значения нескольких значений ADC12MEMx усредняете. А я вот примерно так и собиралась сделать  даже и не знаю, как по-другому  спасибо еще раз. Господа, товарищи, и все же Помогите разобраться с переопределением типов!!! int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Объясните, пожалуйста! заранее спасибо.
|
|
|
|
|
Jun 15 2008, 09:37
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Daria @ Jun 15 2008, 00:39)  Помогите разобраться с переопределением типов!!! int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Я думаю, что дело в том, что x никогда не бывает больше 2y-1. Я предпочитаю работать с целочисленной арифметикой, но при этом нужно держать в памяти диапазоны возможных значений аргументов. Впрочем, как Вы используете float, тоже нужно
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 15 2008, 20:37
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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);
|
|
|
|
|
Jun 17 2008, 03:32
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37

|
Цитата прибавлять число 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 ); }
--------------------
Если зайца бить, его можно и спички научить зажигать Сколько дурака не бей - умнее не будет. Зато опытнее
|
|
|
|
|
Jun 17 2008, 19:48
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(rezident @ Jun 17 2008, 00:30)  Я рад вашим успехам  Зря иронизируете, я медленно(очень медленно), но верно расту Цитата(rezident @ Jun 17 2008, 00:30)  Кстати, если вам требуется округление, то можно (до преобразования в int) при вычислениях с float прибавлять число 0.5f. Спасибо за совет - пригодится Цитата(VAI @ Jun 17 2008, 07:32)  если число положительное, и вычитать 0.5, если число отрицательное. Примерно, в общем виде, где-то так... Спасибо, VAI.
|
|
|
|
|
Jun 22 2008, 15:37
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Здравствуйте, и снова вопросы  много, много вопросов 1.!! Сначала по поводу усреднения отсчетов для уменьшения шума - предлагали использовать бит MSC в регистре ADC12CTL0. Правильно ли я понимаю, что тогда значения выборок будут постоянно(до сброса бита ENC) записываться в регистры ADC12MEMx, и получить усредненное значение можно считывая значения из разных регистров ADC12MEMx и деля на их количество? Но у меня 16 каналов АЦП, задействовано в дальнейшем будет 5. Т.е. я могу использовать для усреднения только три значения из регистров ADC12MEMx - маловато будет... ну, или я все же не понимаю, поясните тогда принцип использования бита 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 было выше в теме, да и не в ней суть, на вычисления тоже можно не обращать внимания ВОПРОС! - 2.!! В данном случае вычисляю азимут 10 раз, а посылаю только один. т.е. 10 раз посылается одно и то же значение. Если переношу строчку send_int(azimut); под строку azimut = calculation (Vx,Vy); - т.е. сразу после вычисления и отправляю, то программа не работает  На СOM ничего не приходит!  Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?! 3.!! Вопрос не по теме MSP430, уж извините, но вдруг кто-нибудь знает - Когда считываю уровень сигнала с датчика, он самопроизвольно "плывет", плата лежит неподвижно, а уровень за минуту убегает довольно прилично, при вычислении азимута получается, что в минуту градусов +/- 5  С чем это может быть связано? Датчик, напоминаю, HMC1002  Вопрос в основном к Курту, если он заглянет. Да, Kurt, отправила Вам письмо - загляните в ящик - там еще куча вопросов по компасу конкретно  Ну, Вы сами обещали помочь Ну вот, пока все - помогите, кто может чем сможет  Не ругайте за безграмотность и всех с победой сбороной России
|
|
|
|
|
Jun 22 2008, 18:38
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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); - т.е. сразу после вычисления и отправляю, то программа не работает  На СOM ничего не приходит!  Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?! Затрудняюсь сходу дать однозначный ответ, но думаю, что причиной является факт, что получение значения измерения и передача его через UART это процессы вообще-то асинхронные, но вы их пытаетесь принудительно синхронизировать без использования буферов. Вы используете передачу по опросу бита готовности, а не по прерыванию. А каждая передача "тормозит" измерения на время передачи двух символов. Поэтому за тот же самый интервал времени (который у вас фиксированный и определяется таймером) вы получаете меньше отсчетов, чем предполагаемое вами количество (10). Следовательно условие if (index >= 10) не выполняется, результата azimut вы не получаете, и передача через UART тоже не идет. Для решения этой проблемы рекомендую использовать передачу по прерываниям и формировать для передачи свой собственный буфер, линейный или циклический. По 3-му вопросу ответить не могу. Я не "копенгаген", да и с подобными датчиками я не работал
Эскизы прикрепленных изображений
|
|
|
|
|
Jun 24 2008, 19:17
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Здравствуйте снова. Rezident, спасибо за подробный разбор, но вот я начала после Ваших комментов разбираться и окончательно зависла Во-первых, после того, как фильтр сделала по Вашему совету - с делением не на 10, а на index. числа начали получаться жуткими и бессмысленными, вразнобой и без всякой связи с поворотом платы - как это можно объяснить? Во-вторых, я, наивная, полагала, что преобразование АЦП запускается сейчас синхронно с переключением таймера, я ведь вроде не битом ADC12SC "дергаю", а ставлю бит SHS_1 в ADC12CTL1 - т.е использую выход таймера А1... или нет? Проверка if (P1OUT & BIT5) идет не перед стартом преобразования, а перед тем, как записывать новый элемент в массив, т.е. как раз то, о чем Вы говорите... так мне казалось В третьих, тут вроде все советовали как раз использовать как можно меньше прерываний, лучше вообще без них, вот и стараюсь без них и вообще - Вы обещали рассказать, как в данном случае не программно дергать P1OUT, а использовать выход таймера - как это можно сделать, ведь изменение состояния вывода должно произойти только через 918 переключений таймера И все-таки вопрос - почему send_int(azimut) нельзя перенести в то место, в которое хочется  ? Если бы условие if (index >= 10) никогда не выполнялось, то и вычисление никогда не происходило бы, а что-то таки вычисляется. Без фильтра работает  только сильно скачет, что не есть хорошо. Вот такие непонятки будет время, ответьте, пожалуйста.
Сообщение отредактировал Daria - Jun 24 2008, 19:19
|
|
|
|
|
Jun 25 2008, 18:18
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(rezident @ Jun 25 2008, 00:13)  Я бы вам посоветовал отладить работу АЦП не с датчиком, а с постоянными напряжениями для начала. да пробовала  Вроде нормально идет. Правда, пробовала без всяких усреднений... Цитата(rezident @ Jun 25 2008, 00:13)  Вы еще не до конца разобрались с синхронной работой ADC12 и TimerA и вообще с функционированием ADC12. Эт точно  да и с USART похоже тоже. Видимо все дело в том, как я отправляю число. Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме? Пробовала без флажка 0xFF, означающего конец посылки, но при "слеплении" получаются ошибки. вы говорили, что нужно как-то по прерываниям работать, как?  Да, вот что странно, когда я разрешаю прерывания по передаче, вообще перестает работать. А проект пока маленький совсем, прикладываю текст. Не ругайтесь на "+", я потом обязательно исправлю, все как-то недосуг Вообще спасибо за поддержку
Сообщение отредактировал Daria - Jun 25 2008, 18:25
Прикрепленные файлы
1.txt ( 6.62 килобайт )
Кол-во скачиваний: 108
|
|
|
|
|
Jun 26 2008, 14:11
|
Участник

Группа: Участник
Сообщений: 36
Регистрация: 4-03-05
Из: Киев
Пользователь №: 3 078

|
Цитата(Daria @ Jun 25 2008, 21:18)  Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме? Имеет смысл сразу организовать протокол обмена. Пример: адрес получателя 1 или 2 байта идентификатор пакета 2 байта - соответвует идентификатору запроса. длина данных пакета 1 или 2байт данные [] адрес отправителя 1 или 2 байта СRC 2 байт истина прописная, протокол то все равно прийдется организовывать ))) либо воспользоватся общепринятыи протоколом для Вашей конторы ...
|
|
|
|
|
Jun 26 2008, 18:44
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(NoName @ Jun 26 2008, 18:11)  Имеет смысл сразу организовать протокол обмена. либо воспользоватся общепринятыи протоколом для Вашей конторы ... Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договаривается  А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего? Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла  Чутка попозже. Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет?
Сообщение отредактировал Daria - Jun 26 2008, 18:50
|
|
|
|
|
Jun 26 2008, 20:30
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

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

|
Цитата(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 строку символов вместо бинарного числа? Да все равно как, главное, видеть, что приходит Цитата(rezident @ Jun 27 2008, 00:30)  Блочный режим используется, если управляющая программа записи в ОЗУ расположена. Если же у вас программа записи исполняется прямо из Flash, то можно писать побайтово или пословно. Но слово - это же два байта вроде?.. То есть писать функцию, которая пословно записывает число, и функцию, которая будет пословно считывать?
|
|
|
|
|
Jun 29 2008, 11:23
|
Участник

Группа: Участник
Сообщений: 36
Регистрация: 4-03-05
Из: Киев
Пользователь №: 3 078

|
Цитата(Daria @ Jun 26 2008, 21:44)  Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договаривается  А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего? Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла  Чутка попозже. Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет? Daria пишите побайтово - последовательно записывая 2 байта (short), когда пишете флоат - пишите 4 байта, будет работать также хорошо ( данные пишете во flash MSP что ли?? ) --------------------------------- CR, LF - '\r'.'\n' )) вариант с выводом в терминал конешно хорош. но это только на этапе проверки фукционирования устройства. используюя протокол Вы можете использовать различные режимы настройки без перепрошики в общем я за написания протокола + внешней программы в которой можете уже смотреть и настраивать как Вам будет угодно. )
|
|
|
|
|
Jun 29 2008, 21:10
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(NoName @ Jun 29 2008, 15:23)  Daria пишите побайтово - последовательно записывая 2 байта (short), когда пишете флоат - пишите 4 байта, будет работать также хорошо ( данные пишете во flash MSP что ли?? ) Да, пишу во flash MSP - после калибровки датчика нужно сохранять калибровочные константы в памяти. Цитата(NoName @ Jun 29 2008, 15:23)  в общем я за написания протокола + внешней программы в которой можете уже смотреть и настраивать как Вам будет угодно. ) Спасибо, попробую.
|
|
|
|
|
Jun 30 2008, 06:50
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Daria @ Jun 26 2008, 21:44)  Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договаривается  А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего? Имеет - не имеет? Придется! Информация в один байт не помещается, значит их будет больше. Тогда на приемной стороне нужно распознавать, какой байт первый а какой второй (приемник ведь может включиться в любой момент). Можно сделать просто - например, выделить старший разряд для передачи флага первый/второй, а во всех остальных передавать данные. Тогда в двух байтах можно передать 14 значащих разрядов. Запишите на бумажке правила, как именно Вы будете передавать данные - это и будет называться гордым словом ПРОТОКОЛ - правила, однозначно устанавливающие порядок приема и передачи информации.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 30 2008, 16:58
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(Dog Pawlowa @ Jun 30 2008, 10:50)  Запишите на бумажке правила, как именно Вы будете передавать данные - это и будет называться гордым словом ПРОТОКОЛ - правила, однозначно устанавливающие порядок приема и передачи информации.  Да вообщем-то сейчас так и делаю, функция send_int, описанная в теме выше.  Но вся эта процедура занимает много времени, по-моему - после отправки каждого байта(старшего, младшего и флага, означающего конец посылки) жду очистки флагов. Может, можно как-то проще и быстрее? Как-нибудь так настроить USART, чтобы передача трех байтов занимала как можно меньше времени. Вот, в чем был вопрос. все равно спасибо.
|
|
|
|
|
Jul 15 2008, 19:37
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Снова я, здравствуйте Такой вопрос - контроллер, напоминаю - MSP430F149, гружу программу с помощью IAR, boot memory - 1КВ, а прога уже значительно больше. Как быть? Надо как-то писать основную прогу во flash, в code memory? А в boot - маленький модуль, вызывающий основную? Как это сделать? И rezident, если будете в наших краях, все же расскажите, как бы Вы написали работу таймера  Очень жду. Вышла вот из отпуска и жду
|
|
|
|
|
Jul 16 2008, 09:33
|
Участник

Группа: Участник
Сообщений: 36
Регистрация: 4-03-05
Из: Киев
Пользователь №: 3 078

|
Цитата(Daria @ Jul 15 2008, 22:37)  Снова я, здравствуйте Такой вопрос - контроллер, напоминаю - MSP430F149, гружу программу с помощью IAR, boot memory - 1КВ, а прога уже значительно больше. Как быть? Надо как-то писать основную прогу во flash, в code memory? вопрос не понятен, если используете разбивку по умолчанию то подлючается файл X:\....\IAR Systems\Embed.....\config\lnk430F149.xcl если желаете исправить данный файл, то копируете к своему проекту и подлючаете Options >> Linker >> Config >> Linker command file -> my_lnk430F149.xcl ( пример ) в оригинальном файле сегмент для кода -Z(CODE)CODE=1100-FFDF явно больше 1кБ )) после выхода из __low_level_init выполняется main, если не переоприделяли (обьявлений типа main () @ "boot_memory" не нашел в Вашем коде ) то он должен находится в сегменте CODE ИАР при компиляции ругается на выход за пределы сегмента?
|
|
|
|
|
Jul 16 2008, 18:31
|
Местный
  
Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345

|
Цитата(NoName @ Jul 16 2008, 13:33)  вопрос не понятен, если используете разбивку по умолчанию то подлючается файл X:\....\IAR Systems\Embed.....\config\lnk430F149.xcl
если желаете исправить данный файл, то копируете к своему проекту и подлючаете Options >> Linker >> Config >> Linker command file -> my_lnk430F149.xcl ( пример )
в оригинальном файле сегмент для кода -Z(CODE)CODE=1100-FFDF явно больше 1кБ )) после выхода из __low_level_init выполняется main, если не переоприделяли (обьявлений типа main () @ "boot_memory" не нашел в Вашем коде ) то он должен находится в сегменте CODE
ИАР при компиляции ругается на выход за пределы сегмента? Да, ругается.  Использую по умолчанию. Попробую Options >> Linker >> Config >> Linker command file ->  Спасибо. Завтра напишу, получилось или нет
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|