|
АЦП MSP430F149, Чего я неправильно делаю? |
|
|
|
Jun 30 2009, 08:36
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
в качестве совета. В IDE обычно всегда есть хедеры со всеми константами, не надо делать так: ADC12CTL0 |= 0x0001; ADC12MCTL0 = 0x10; ADC12CTL1 = 0x5000+SHP+ADC12SSEL1+ADC12DIV0; и пр. Ваш код пока не смотрел, ибо докипод рукой нет, а на память не помню. Если резидент не опередит, что обычно бывает  то скажу в чем проблема к вечеру.
|
|
|
|
|
Jul 1 2009, 17:32
|
Местный
  
Группа: Свой
Сообщений: 445
Регистрация: 7-02-05
Из: Зеленоград
Пользователь №: 2 468

|
Цитата(Сергей Борщ @ Jun 30 2009, 15:32)  Если открыто окно отладчика с регистрами АЦП - то да. Но точно такие же чудеса будут происходить и с таймерами (TAIV, TBIV), и с UART - вообще с любой периферией, значение регистров которой изменяется чтением. Ух ты, вот оно что ! Теперь ясно...
|
|
|
|
|
Aug 2 2009, 10:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Теперь я запутался. Проц 169. Задача: а) оцифровать 3 канала по внешнему "пинку" б) оцифровывать все время 3 канала по таймеру-В. Инициализирую АЦП: Код ADC12CTL0 = 0; ADC12CTL1 = SHP + ADC12DIV_1 + ADC12SSEL_2 + CONSEQ_1; // start=SC, s/h=timer, clk from MCLK 1/2 = 4Mhz = 0.2uS, sequence. ADC12MCTL0 = SREF_1 + INCH_0; ADC12MCTL1 = SREF_1 + INCH_1; ADC12MCTL2 = SREF_1 + INCH_2 + EOS; ADC12IE = 0; ADC12IFG = 0; ADC12CTL0 = SHT0_1 + REF2_5V + REFON + ADC12ON + ENC + MSC; Тестовый кусок кода: Код ADC12CTL0 |= ADC12SC; // start single conversion while(1){ LED_ON; while((ADC12IFG & 0x07)!=0x07); LED_OFF; ADC12IFG &=0x07; // clear IRQ flags DAC12_0DAT= ADC12MEM0; // вывожу оцифрованное для контроля в ЦАПы, жаль третьего нет: DAC12_1DAT= ADC12MEM1; } Таймер инициализировал так: Код TBCTL = TBSSEL_2 | TBCLR; // XT2 Clock input (8Mhz) TBCCR0 = 500; // 16kHz output TBCCTL0 = CCIE; TBCTL |= MC_1; В таймере даю "пинок": Код #pragma vector=TIMERB0_VECTOR __interrupt void TIMERB0_interrupt(){ LED2_TOGGLE; ADC12CTL0 |= ADC12SC; #endif Все работает, но если в ините ADC12CTL0 я убираю MSC, то работать перестает. Я не понял, MSC это ведь только время S/H, без него по идее, должно быть просто меньше время общего преобразования? Теперь вариант Б: добавляю SHS_2 в АЦП: Код ADC12CTL1 = SHP + ADC12DIV_1 + ADC12SSEL_2 + CONSEQ_1 + SHS_2; таймер инициализирую так: Код TBCTL = TBSSEL_2 | TBCLR; // XT2 Clock input (8Mhz) TBCCR0 = 500; // 16kHz output TBCCTL0 = OUTMOD_1; TBCTL |= MC_1; Получаю естессно фигвам. Вопрос - чего я забыл еще включить ?
|
|
|
|
|
Aug 3 2009, 12:03
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Пробегаю по диагонали, потому как в отпуске: 1) ADC12IFG &=0x07; // clear IRQ flags Сбрасывает все флаги, кроме трех младших. Если я правильно понял, вы хотели наоборот. 2) Цитата(Allregia @ Aug 2 2009, 13:12)  Я не понял, MSC это ведь только время S/H, без него по идее, должно быть просто меньше время общего преобразования? Нет. Это значит, что один "пинок" будет запускать либо каждое преобразование, либо всю серию до ячейки с ENC(преобразование следующего канала начнется сразу после окончания преобразорвания предыдущего). 3) Для постоянной оцифровки трех каналов у вас должна быть инициализация с CONSEQ = 3 (Repeat-sequence-of-channels). В прерывании таймера надо CONSEQ поставить в 1 (Sequence-of-channels), переставить CSTARTADD на группу тех трех каналов, которые вам надо оцифровать по "пинку", для последнегно канала этой группы разрешить прерывание. В прерывании вернуть CONSEQ и CSTARTADD, а также дернуть ADC12SC. В таком варианте (насколько я понимаю описание) после прерывания таймера АЦП закончит последовательность трех постоянных каналов и перейдет к оцифровке "пинаемых". Если же вам надо начать преобразование "пинаемых" немедленно, то в прерывании таймера надо несколько поколдовать с ENC и CONSEQ (см. раздел Stopping Conversions).
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 3 2009, 14:16
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(Сергей Борщ @ Aug 3 2009, 15:03)  Пробегаю по диагонали, потому как в отпуске: 1) ADC12IFG &=0x07; // clear IRQ flags Сбрасывает все флаги, кроме трех младших. Если я правильно понял, вы хотели наоборот. Да, конечно, я забыл испрвить - у меня там на самом деле стоит ADC12IFG =0; Цитата 2) Нет. Это значит, что один "пинок" будет запускать либо каждое преобразование, либо всю серию до ячейки с ENC(преобразование следующего канала начнется сразу после окончания преобразорвания предыдущего).
3) Для постоянной оцифровки трех каналов у вас должна быть инициализация с CONSEQ = 3 (Repeat-sequence-of-channels). В прерывании таймера надо CONSEQ поставить в 1 (Sequence-of-channels), переставить CSTARTADD на группу тех трех каналов, которые вам надо оцифровать по "пинку", для последнегно канала этой группы разрешить прерывание. В прерывании вернуть CONSEQ и CSTARTADD, а также дернуть ADC12SC. В таком варианте (насколько я понимаю описание) после прерывания таймера АЦП закончит последовательность трех постоянных каналов и перейдет к оцифровке "пинаемых". Если же вам надо начать преобразование "пинаемых" немедленно, то в прерывании таймера надо несколько поколдовать с ENC и CONSEQ (см. раздел Stopping Conversions). Я наверное не очень обьяснил, "пинок" - это было чисто для проверки, а мне надо постоянно оцифровывать только 3 канала 0-1-2, но запуск осуществлять по таймеру В (чтобы не получиь джиттер). Так что, CONSEQ = 3 (Repeat-sequence-of-channels) не нужно совершено - оно запусукает непрерывный процесс без участия таймера, поэтому я и ставлю CONSEQ_1 - однократныую оцифровку последовательности каналов. Вот если я эту оцифровку запускаю в прерывании таймера, сигналом ADC12SC - все работает. Далее я могу использовать прерывание от последнего канала, или просто читать ADC12MEMx из программы. Но(!), я думал что есть возможность запускать преобразование без прерывания таймера а аппаратно (не хочется терять время на обработчик таймерного прерывания), и вот это-то у меня пока и не получилось.
|
|
|
|
|
Aug 3 2009, 14:39
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Allregia @ Aug 3 2009, 20:16)  Я наверное не очень обьяснил, "пинок" - это было чисто для проверки, а мне надо постоянно оцифровывать только 3 канала 0-1-2, но запуск осуществлять по таймеру В (чтобы не получиь джиттер). Остальное цитировать не буду, т.к. все ваши непонятки от того, что вы невнимательно прочитали раздел, посвященный ADC12, в User's Manual. А конкретные непонятки у вас в функционировании узле выборки-хранения, который обведен на блок-схеме. Поясните точнее, что вы хотите: а) полностью контролировать и длительность выборки и периодичность каждого преобразования? б) контролировать только периодичность каждого преобразвоания? в) контролировать только периодичность преобразований всей группы? В зависимости от этого и советы будут точнее.
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 3 2009, 15:10
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(rezident @ Aug 3 2009, 17:39)  Остальное цитировать не буду, т.к. все ваши непонятки от того, что вы невнимательно прочитали раздел, посвященный ADC12, в User's Manual. А конкретные непонятки у вас в функционировании узле выборки-хранения, который обведен на блок-схеме. Цитата
Может я ошибаюсь, но помоему конретные непонятнки у меня больше с настройкой Таймера_В. С АЦП - есть непонятнка с ENC, но об этом позже.
Поясните точнее, что вы хотите: а) полностью контролировать и длительность выборки и периодичность каждого преобразования? б) контролировать только периодичность каждого преобразвоания? в) контролировать только периодичность преобразований всей группы? В зависимости от этого и советы будут точнее. Попробую описать что я хочу: 1) Запрограммировать таймер_В допустим на 16кгц, без прерываний. 2) по этому таймеру запускать преобразование группы из 3-х каналов. Сейчас я п.2 делаю в прерывании таймера (взвожу ADC12SC), а хотелось бы чтобы это было без прерывания, чисто аппаратно (если это возможно). Т.е. "запустил и забыл" - далее в программе я когда хочу, читаю результаты в ADC12MEM0,1,2, зная что каждый канал оцифровывается с частотой 16кгц. Но у меня таймер не запусакает АЦП. Я настраиваю АЦП на запуск от "выход 0 таймера В" используя SHS_2 в ADC12CTL1. Далее - таймер я настраиваю так, чтобы при достижении CCR0 выход 0 устанавливался в "1" (что должно запускать АЦП), а вот кто его сбрасывать в 0 будет - я пока не разобрался. И еще - мне не совсем понятна фраза в даташите, про необходимость дергать ENC перед кадой серией - это что, надо делать программно? Т.е. сделать так, чтобы ежиножды настроив АЦП и Таймер, запуск серии происходил все время автоматически аппаратно по таймеру нельзя, без софта?
|
|
|
|
|
Aug 3 2009, 15:54
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Allregia @ Aug 3 2009, 21:10)  Попробую описать что я хочу: 1) Запрограммировать таймер_В допустим на 16кгц, без прерываний. 2) по этому таймеру запускать преобразование группы из 3-х каналов. Т.е. вы хотите оцифровать последовательность каналов и с периодом 1/16кГц=62,5мкс получать постоянно три готовых результата измерения без каких-либо манипуляций с АЦП, так? Это в принципе возможно, но нужно внимательно посмотреть на времена выборки. Достаточно ли их длительностей будет для оцифровки ваших сигналов? Посчитаем. Максимальная тактовая у ADC12 - 6,3МГц. Каждое преобразование - 13 тактов ADC12CLK. 62,5мкс-13*3/6,3МГц=56,5мкс суммарно на все выборки или 56,5мкс/3=18,8мкс на каждую Для ваших сигналов достаточно такого времени выборки? Если да, то ближайшее подходящее значение таймера выборки-хранения SHT0/1=5 даст 96 тактов ADC12CLK или 15,2мкс на каждую выборку при тактовой ADC12CLK = 6,3МГц. Устраивает? Тогда взводим биты MSC и SHP, биты SHSx и ISSH в зависимости от сигнала таймера, выбираем режим CONSEQ_3 и получаем повторяющуюся последовательность каналов с периодом запуска 1/16кГц и общим временем преобразования (96+13)*3=327 тактов ADC12CLK. Вот только с произвольным считыванием результата без использования DMA может быть небольшой облом-с.  Для чтения ADC12MEMx в произвольный момент времени тактовая ADC12CLK должна быть обязательно синхронна тактовой частоте ядра. Т.е. ADC12CLK должен тактироваться от MCLK или другого CLK, синхронного ему.
|
|
|
|
|
Aug 4 2009, 07:40
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(rezident @ Aug 3 2009, 18:54)  Т.е. вы хотите оцифровать последовательность каналов и с периодом 1/16кГц=62,5мкс получать постоянно три готовых результата измерения без каких-либо манипуляций с АЦП, так? Именно! Цитата Это в принципе возможно, но нужно внимательно посмотреть на времена выборки. Достаточно ли их длительностей будет для оцифровки ваших сигналов? Достаточно, проверил  Цитата Посчитаем. Максимальная тактовая у ADC12 - 6,3МГц. Каждое преобразование - 13 тактов ADC12CLK. 62,5мкс-13*3/6,3МГц=56,5мкс суммарно на все выборки или 56,5мкс/3=18,8мкс на каждую Для ваших сигналов достаточно такого времени выборки? Если да, то ближайшее подходящее значение таймера выборки-хранения SHT0/1=5 даст 96 тактов ADC12CLK или 15,2мкс на каждую выборку при тактовой ADC12CLK = 6,3МГц. Устраивает? ADC12CLK у меня 4 Mhz = MCLK/2 Одно преобразование - 13*0.25uS=3.25uS. Выборки я ставлю SHT0_1, т.е. 8 тактов - 8*0.25=2uS, зачем делать 96 тактов ? Получается полное время преобразования 3-х каналов - 3*(3.25+2)=15.75uS Впрочем, это сейчас неважно, могу и 96 тактов поставить. Цитата Тогда взводим биты MSC и SHP, биты SHSx и ISSH в зависимости от сигнала таймера, Я пока не разобрался как сам таймер запрограммировать так, чтобы он запускал АЦП ? Цитата выбираем режим CONSEQ_3 и получаем повторяющуюся последовательность каналов с периодом запуска 1/16кГц и общим временем преобразования (96+13)*3=327 тактов ADC12CLK. Может я конечно совсем тупой, но не понимаю - если CONSEQ_3, то это Repeat-sequence-of-channel, т.е. после преобразования последнего канала сразу начнется преобразование самого первого, и так по кругу, т.е. без участия в этой таймера вообще. Поэтому я и ставил CONSEQ_1 - Sequence-of-channels. Цитата Вот только с произвольным считыванием результата без использования DMA может быть небольшой облом-с.  Для чтения ADC12MEMx в произвольный момент времени тактовая ADC12CLK должна быть обязательно синхронна тактовой частоте ядра. Т.е. ADC12CLK должен тактироваться от MCLK или другого CLK, синхронного ему. Ядро у меня от тех-же 8мгц MCLK кормится, так что с этим проблем не будет.
|
|
|
|
|
Aug 4 2009, 10:03
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Allregia @ Aug 4 2009, 13:40)  Выборки я ставлю SHT0_1, т.е. 8 тактов - 8*0.25=2uS, зачем делать 96 тактов ? А вас точность преобразования совсем не волнует?  Ведь во время выборки перезаряжается конденсатор схемы выборки-хранения (около 40пФ) от входного сигнала. Даже если предположить, что выходное сопротивление источника сигнала близко к нулю, то проходное сопротивление мультиплексора ADC12 (около 2кОм) вы никуда не денете. Поэтому в даташите MSP430F169 явно указано минимальное время выборки 1,22мкс при 3В питании. Напомню эмпирические правила 5-ти и 20-ти RC. Через время равное 5*RC напряжение на C достигает 99% от входного и соответственно через 20*RC - 99,9% от входного. Следовательно время выборки нужно выбирать в зависимости от выходного сопротивления источника сигнала, но не менее указанного в даташите. Цитата(Allregia @ Aug 4 2009, 13:40)  Я пока не разобрался как сам таймер запрограммировать так, чтобы он запускал АЦП ? Дык программируете его в режим CountUp. Период перезагрузки задается в CCR0. 8МГц/16кГц=500, следовательно в CCR0 заносим число 499. Дополнительно нужно задать режим PWM установкой OUTMOD_x в регистре CCTLx. Цитата(Allregia @ Aug 4 2009, 13:40)  Может я конечно совсем тупой, но не понимаю - если CONSEQ_3, то это Repeat-sequence-of-channel, т.е. после преобразования последнего канала сразу начнется преобразование самого первого, и так по кругу, т.е. без участия в этой таймера вообще. А, пардон! Вы не правы (см. фрагмент из User's Manual во вложении), но и я тоже ерунду предложил  . Действительно, если вы хотите синхронизировать начало последовательности преобразований от таймера, то бит MSC в этом режиме (CONSEQ_3) использовать нельзя. Да и SHP тогда использовать тоже не имеет смысла. Надо сигнал SAMPCON полностью формировать таймером с помощью PWM так, как это указано на времянках в User's Manual ( Figure 17−3. Extended Sample Mode). Тут другой затык получается - нужно три сигнала SAMPCON за период 1/16кГц сформировать, но при имеющейся тактовой (8МГц) частоту перезагрузки таймера кратную 1/(3*16кГц) точно получить нельзя (8МГц/(3*16кГц)=166,6(6)).  Кварц заменить можете? Например, из ряда 7,2МГц, 7,392МГц, 7,488МГц, 7,68МГц, 7,776МГц? Цитата(Allregia @ Aug 4 2009, 13:40)  Поэтому я и ставил CONSEQ_1 - Sequence-of-channels. А вот это неправильно. В этом режиме нужно бит ENC тогглить, в отличие от режима CONSEQ_3.
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 4 2009, 12:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(rezident @ Aug 4 2009, 13:03)  А вас точность преобразования совсем не волнует?  Ведь во время выборки перезаряжается конденсатор схемы выборки-хранения (около 40пФ) от входного сигнала. Даже если предположить, что выходное сопротивление источника сигнала близко к нулю, то проходное сопротивление мультиплексора ADC12 (около 2кОм) вы никуда не денете. Поэтому в даташите MSP430F169 явно указано минимальное время выборки 1,22мкс при 3В питании. Так у меня 2мкс, будет надо - увеличу, не в этом сейчас проблема. Цитата Дык программируете его в режим CountUp. Период перезагрузки задается в CCR0. 8МГц/16кГц=500, следовательно в CCR0 заносим число 499. Дополнительно нужно задать режим PWM установкой OUTMOD_x в регистре CCTLx. Я это и сделал, но видимо не все что нужно. Собственно, это как раз именно то, что я второй день спрашиваю  Цитата А, пардон! Вы не правы (см. фрагмент из User's Manual во вложении), но и я тоже ерунду предложил  . Действительно, если вы хотите синхронизировать начало последовательности преобразований от таймера, то бит MSC в этом режиме (CONSEQ_3) использовать нельзя. Да и SHP тогда использовать тоже не имеет смысла. Надо сигнал SAMPCON полностью формировать таймером с помощью PWM так, как это указано на времянках в User's Manual ( Figure 17−3. Extended Sample Mode). Тут другой затык получается - нужно три сигнала SAMPCON за период 1/16кГц сформировать, но при имеющейся тактовой (8МГц) частоту перезагрузки таймера кратную 1/(3*16кГц) точно получить нельзя (8МГц/(3*16кГц)=166,6(6)).  Кварц заменить можете? Например, из ряда 7,2МГц, 7,392МГц, 7,488МГц, 7,68МГц, 7,776МГц? А вот это неправильно. В этом режиме нужно бит ENC тогглить, В смысле "руками"? Цитата в отличие от режима CONSEQ_3. В общем, выходит что исходя из Ваших обьяснений - сделать автоматический запуск преобразования последовательности по таймер - нельзя.
|
|
|
|
|
Aug 4 2009, 14:04
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Allregia @ Aug 4 2009, 18:03)  В смысле "руками"? Не "руками", а программно. Устанавливаете в ADC12IE бит, соответствующий последнему каналу в последовательности. По прерыванию от АЦП считываете содержимое всех нужных регистров ADC12MEMx. Сбрасываете/устанавливаете бит ENC и по следующему импульсу от таймера запускается вновь последовательность преобразований. Только вам нужно будет успевать обработать прерывание ADC12 за промежуток времени между готовностью результатов и следующим импульсом запуска цепочки преобразований. Это примерно 30 тактов MCLK. Цитата(Allregia @ Aug 4 2009, 18:03)  В общем, выходит что исходя из Ваших обьяснений - сделать автоматический запуск преобразования последовательности по таймер - нельзя. Откуда такой вывод? Нафига, спрашивается, я распинался, если вывод с точностью наоборот?  Учитывая все ваши исходные данные в режиме повторяющейся последовательности каналов нельзя точно выдерживать интервал 1/16кГц, но сделать автоматическую оцифровку тем не менее можно.
|
|
|
|
|
Aug 4 2009, 20:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(rezident @ Aug 4 2009, 17:04)  Не "руками", а программно. Устанавливаете Это я и имел ввиду, когда говорил "руками". Цитата в ADC12IE бит, соответствующий последнему каналу в последовательности. По прерыванию от АЦП считываете содержимое всех нужных регистров ADC12MEMx. Сбрасываете/устанавливаете бит ENC и по следующему импульсу от таймера запускается вновь последовательность преобразований. Так - понятно. Собственно, почти так у меня и сделано - только я в таймерном прерывании дергаю ADC12SC. Цитата Только вам нужно будет успевать обработать прерывание ADC12 за промежуток времени между готовностью результатов и следующим импульсом запуска цепочки преобразований. Это примерно 30 тактов MCLK. Почему 30 ?! 30 тактов MCLK это 3.75 мкс, у меня период между измерениями - 62.5мкс, время преобразования я выше говрил - 15мкс, ну дже если увеличу выборку втрое, будет 30мкс, еще ~30мкс остается, это 240 тактов MCLK. Цитата Откуда такой вывод? Нафига, спрашивается, я распинался, если вывод с точностью наоборот? Большое спасибо за "распинание", но видимо у нас разное мнение о том, что такое "автоматическое перобразование", и я описание в даташите понял совсм по другому чем Вы и чем оно есь на самом деле. Цитата  Учитывая все ваши исходные данные в режиме повторяющейся последовательности каналов нельзя точно выдерживать интервал 1/16кГц, но сделать автоматическую оцифровку тем не менее можно. Да неважно 16 или сколько - любое число. Ладно, оставим это, поскольку тут уже все пошло из чистого любоптства, ане необходимости решить задачу. Ее я решил, пусть и не так как планировал с самого начала. P.S. А кстати, вопрос с определением работоспособности ХТ1 и ХТ2, о чем я спрашивал неделю назад в соседней теме, я тоже решил, теперь выпаиваю любой из квацев (или замыкаю) или оба вместе - и четко выбивает код ошибки.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|