• Объявления

    • admin

      Просьба всем принять участие!   24.11.2017

      На форуме разыгрывается спектроанализатор Arinst SSA-TG LC (цена 18500 руб). Просьба всем перейти по ссылке ниже и принять участие!
shematehnik

Глюк Stm8S003 Или Ошибка В Коде?

20 сообщений в этой теме

shematehnik    1

При написании программы под контроллер STM8S003 столкнулся с такой проблемой.

Когда я работаю с одним каналом АЦП, то все работает правильно, измеренные показания соответствуют действительности.

Но когда начинаю сканировать два канала, то они влияют на показания друг друга и в результате я получаю какой-то бред, вместо правильных показаний.

По отдельности они работают отлично. Режим выбрал "Single mode". Запускаю преобразования битом ADON. По прерыванию EOC забираю значение из регистра данных, выбираю следующий канал в ADC_CSR_bit.CH и снова битом ADON запускаю новое преобразование.

Что не так я делаю или есть какой-то заводской глюк. Другие режимы мне не подходят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Yurkin2015    274

Вход АЦП не успевает перезарядиться на новое напряжение другого канала. Видимо источник измеряемого напряжения довольно высокоомный.

Надо бы между выборкой следующего канала и стартом ADON добавить небольшую задержку, типа 100мкс, если не жалко.

Либо уменьшить скорость работы АЦП, изменив биты SPSEL. Так как после каждого ADON=1, АЦП сначала 3 такта накапливает сигнал на входе, а потом 10 тактов конвертирует то, что накопилось. Уменьшая тактовую частоту АЦП, тем самым увеличиваете время выборки входного сигнала.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Пробовал в SPSEL записывать максимально возможное значение. Все равно это не помогло. Пробовал один и тот же канал выбирать подряд по 10 раз, потом второй (ну грубо говоря сразу 10 раз один канал сканировать потом другой), но все равно показания "прыгают".

На первый канал подключена клавиатура с 5-ю кнопками, которая представляет собой делитель напряжения и в зависимости от нажатой кнопки соотношение меняется, а соответственно и напряжение на входе АЦП разное.

В исходном состоянии все кнопки отпущены и вход подтянут к земле резистором 1МОм. На второй вход АЦП поступает с делителя выходное напряжение источника. Так вот с этого входа максимальное показание достигает где 500 отсчетов, причем при вращении потенциометра показания АЦП периодически проходят через 0 и снова нарастают. Или может показывать 500 единиц, но если при этом на втором канале АЦП нажать кнопку, то показания могут на несколько сотен уменьшиться. По отдельности что клавиатура, что измеритель выходного напряжения работают отлично...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274

Ну, сделайте задержку перед стартом АЦП после переключения канала. Это проще проверить, чем строить хардварные буферные какскады на ОУ перед каналами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Ну, сделайте задержку перед стартом АЦП после переключения канала. Это проще проверить, чем строить хардварные буферные какскады на ОУ перед каналами.

Задержка тоже не помогает. Можно было бы попробовать применить режим сканирования, но у меня другие входы AIN работают в цифровом режиме

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274

Видимо без схемы и кода в студию тут не обойтись. Иначе какое-то гадание получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

//******************************************************************************
//Инициализация АЦП
//******************************************************************************
void adc_init(){
//Отключение триггеров Шмитта по всем каналам
ADC_TDRL = 0xff;
ADC_TDRH = 0xff;
ADC_CR1_bit.SPSEL = 0x07; //Предделитель Fosc/18
ADC_CR1_bit.CONT = 0;	 //Одиночный режим конвертирования
ADC_CSR_bit.EOCIE = 0;	 //Выключить прерывания по завершению преобразования
ADC_CSR_bit.AWDIE = 0;	 //Выключить прерывания watchdog
ADC_CR2 = 0;
ADC_CR2_bit.ALIGN = 1;	 //Правое выравнивание результата преобразования
CLK_PCKENR2 &= ~0x08;	 //Выключаем тактирование АЦП (по умолчанию вкл)

adc_stage = ADC_STG_INIT;
}
//******************************************************************************
//Запуск преобразований АЦП
//******************************************************************************
char adc_start(){
//Включаем тактирование АЦП
CLK_PCKENR2 |= 0x08;	

//Если нет списка каналов, то не запускаемся
if(adc_channels_list.list == NULL)
return 0;
else {
adc_channels_list.current = adc_channels_list.list;
ADC_CSR_bit.CH = adc_channels_list.current->channel;
}

ADC_CSR_bit.EOCIE = 1;	 //Включить прерывания по завершению преобразования
ADC_CR1_bit.ADON = 1;	 //Первая установка бита выводит из спящего реж.
ADC_CR1_bit.ADON = 1;

adc_stage = ADC_STG_STRT;

return 1;
}

..............

//******************************************************************************
//Обработка результатов измерения АЦП
//******************************************************************************
#pragma vector=ADC1_EOC_vector
__interrupt void adc_conv_done(void){

//Завершение преобразования
if(ADC_CSR_bit.EOC){
ADC_CSR_bit.EOC = 0;
if(adc_channels_list.list){
//Считываем показания АЦП и запоминаем их в переменную
*adc_channels_list.current->variable = ADC_DRH;
*adc_channels_list.current->variable <<= 8;
*adc_channels_list.current->variable |= ADC_DRL;
//Выбираем следующий канал АЦП
adc_channels_list.current = adc_channels_list.current->next_channel;
ADC_CSR_bit.CH = adc_channels_list.current->channel;
}
}

//Запуск следующего преобазования
ADC_CR1_bit.ADON = 1;
}

Схема тут не добавляется

Изменено пользователем shematehnik

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Вот максимально упростил программу для работы только с АЦП. Проблема пока осталась.

#include <iostm8s003f3.h>
#include <intrinsics.h>
unsigned int adc_ain5, adc_ain6;
void adc_init(){

   CLK_PCKENR2 |= 0x08;	    //Включаем тактирование АЦП (по умолчанию вкл)

   //Отключение триггеров Шмитта по всем каналам
   //ADC_TDRL = 0xff;
   //ADC_TDRH = 0xff;
   ADC_CR1_bit.SPSEL = 0x07;  //Предделитель Fosc/18
   ADC_CR1_bit.CONT = 0;	  //Одиночный режим конвертирования
   ADC_CSR_bit.EOCIE = 0;	 //Выключить прерывания по завершению преобразования
   ADC_CSR_bit.AWDIE = 0;	 //Выключить прерывания watchdog
   ADC_CR2 = 0;
   ADC_CR2_bit.ALIGN = 1;	 //Правое выравнивание результата преобразования

   ADC_CR1_bit.ADON = 1;
   ADC_CR1_bit.ADON = 1;
}
void adc_conv(){
 //Выбор канала
 if(ADC_CSR_bit.CH != 5)
   ADC_CSR_bit.CH = 5;
 else
   ADC_CSR_bit.CH = 6;

 for(unsigned long int delay = 0; delay < 0xfff; delay++);

 //начало преобразования
 ADC_CR1_bit.ADON = 1;			  

 //ждем окончания преобразования
 while(!ADC_CSR_bit.EOC);	  

 //сброс флага окончания
 ADC_CSR_bit.EOC = 0;			   

 //Забираем результат
 if(ADC_CSR_bit.CH == 5){
  adc_ain5 = ADC_DRH << 8;
  adc_ain5 |= ADC_DRL;
 } else {
   adc_ain6 = ADC_DRH << 8;
   adc_ain6 |= ADC_DRL;
 }
}
void main()
{
 adc_init();
 while(1){
   adc_conv();
 }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274

Оптимизатор пустой цикл выбрасывает? Попробуйте такую задержку поставить - задержка на время преобразования, просто одно холостое преобразование :

ADC_CR1_bit.ADON = 1;

while(!ADC_CSR_bit.EOC);

ADC_CSR_bit.EOC = 0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Оптимизацию я отключил пока:

// 27
// 28 for(unsigned long int delay = 0; delay < 0xfff; delay++);
??adc_conv_1:
 CLRW	 X
 LDW	 S:?w1, X
 LDW	 S:?w0, X
??adc_conv_2:
 LDW	 X, S:?w0
 CPW	 X, #0x0
 JRNE	 L:??adc_conv_3
 LDW	 X, S:?w1
 CPW	 X, #0xfff
??adc_conv_3:
 JRNC	 L:??adc_conv_4
 CALL	 L:?inc32_l0_l0
 JRA	 L:??adc_conv_2

Сделал запуск АЦП по внешнему триггеру от таймера 1 с периодом запуска 20 мс, вроде все работает отлично, но это в режиме "Single scan mode"

Сейчас попробую сделать запуск от таймера, но с ручным переключением каналов, т.е. "Single mode".

Попробовал, такая же беда, как и без таймера

Вообщем ST Electronics где-то накосячили... Видимо режим Single mode предназначен только для одного входа, но в то же время нет других режимов, которые позволяли сканировать только выбранные входы, можно только сразу все, что неудобно из-за такой вот вещи:

When using scan mode, it is not possible to use channels AIN0 to AINn in output mode

because the output stage of each channel is disabled when it is selected by the ADC

multiplexer.

А это как раз мой случай, когда другие AIN используются как цифровые выходы...

Мда.. еще ни с одним контроллером не было столько секаса. Видно сильно торопились выпустить самый дешевый мк.

Изменено пользователем shematehnik

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274

Тут дело в следующем, видимо. У вашего АЦП время выборки 3 тика, то есть на это время открываются ворота и заряжается входная ёмкость АЦП. Потом ворота закрываются и начинается преобразование. Вот эту внутренную ёмкость АЦП и не успевает зарядить источник напряжения. Поэтому никакие задержки тут не помогут. Когда один канал опрашивается через некоторое количество опросов напряжение на ёмкости добивается до правильного. А когда каналы переключаются - получается фигня.

Тут есть выход. Надо на каждый вход АЦП повесить дополнительную ёмкость , типа 10 нФ, со входа на землю. Это значительно ускорит заряд внутренней ёмкости выборки-хранения и даст правильный результ сразу.

Изменено пользователем Yurkin2015

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Оставил сканирующий режим АЦП. Влияние режима на цифровые входы "на глаз" не замечено) Пусть будет пока так. В схему внести изменения не могу, это готовое устройство со своей прошивкой. Просто нужно изменить алгоритм работы. Все равно тогда не понятно: как в сканирующем режиме открытия "ворот" хватает на заряд конденсатора? Ведь суть одна и та же, просто каналы мультиплексируются аппаратно. Я бы на месте производителя лучше вообще убрал этот одиночный режим, а в режиме сканирования добавил возможность самому создавать набор нужных каналов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Сегодня осциллографом проверил пин, на котором генерируется ШИМ и который является одним из входов AIN. АЦП в сканирующем режиме вносит не хилые помехи в ШИМ-сигнал, о чем собственно и писали в документации, что нельзя AIN использовать в качестве выходов :wacko:

Долбаный stm8 :wall:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
shematehnik    1

Делюсь решением проблемы, может найдется еще такой бедолага, у которого возникнет такая же проблема :D Наконец-то нашел причину. Все просто до смеха.

Попробовал читать регистры ADC_DRH и ADC_DRL в обратной последовательности и все стало работать правильно без влияния каналов друг на друга.

Видимо чтение регистра ADC_DRH запускает следующее преобразования, а тем временем я еще забираю оставшуюся часть значения из ADC_DRL.

Пришел к такому выводу чисто в отладке. В IAR есть такое окно Live Watch, где можно почти в реальном времени видеть состояние любого регистра или переменной.

Так вот настроил на одном входе 0 В, а на другом 3.3В. По логике должны быть поочередно в регистрах ADC_DRH и ADC_DRL значения 0x00:0x00 и 0x03:0xff соответственно или близкие к ним.

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

Потом вычитал два регистра как один 16-битный (в IAR не было такого дефайна): adc_ain6 = *(unsigned int*)&ADC_DRH

Значения стали записываться правильные. Потом попробовал наоборот читать ADC_DRL сразу, потом ADC_DRH и все также хорошо работало.

Странно, почему же в мануале написали порядок чтения наоборот...

Кстати, возникла мысль, что после чтения регистра ADC_DRH у меня возникает следующее прерывания до того, как я прочитаю ADC_DRL . Но в отладке такого замечено не было. До сих пор не совсем точно понимаю почему напряжения смешивались..

Изменено пользователем shematehnik

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Viktor26    300

не знаю как в стм но в аврках все 16 битные регистры(в таймерах и ацп) записываются начиная со старшего, читаются начиная с младшего. может вы прочитали невнимательно, всякое бывает когда долго мудохаешся, все от усталости.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    274

Вот ещё обратите внимание на работу такой конструкции

adc_ain5 = ADC_DRH << 8;

Процессор 8-ми битный, и регистр ADC_DRH тоже 8-ми битный. Поэтому сдвиг влево на 8 полностью обнуляет результат, потому что нет места для выдвигаемый битов. В результате adc_ain5 = 0 после такого сдвига.

А если переменная adc_ain5 типа unsigned int, то по уму надо делать так

adc_ain5 = ADC_DRH;
adc_ain5 <<= 8;

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

Или сделать явное преобразование типа

adc_ain5 = (unsigned int)ADC_DRH << 8;

Изменено пользователем Yurkin2015

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

I am sorry for not writing in Russian,

 

but maybe you could share the final code of this? I can not understand myself.

Изменено пользователем Rita Jonkutė

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Sergey-Ufa    545

Они совершенно не говорят по русски, но все понимают!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

извините, Я могу и по русский, но  легче по английский. Я понимаю только ответить трудно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сообщения

    • @Trisector  Пусть админы не считают это рекламой, заказывал в этой группе ВК :WaveCorp
    • Скорее всего при такой малой нагрузке ПОС по току почти бездействует. У меня начинал стартовать от 10Вт.
    • если вам нужно только принять сигнал, не нужно ничего согласовывать. достаточно поставить резистор на соответствующий ток (10к и больше) если порт защищён диодами, если нет поставить. и не надо никаких делителей и стабилитронов. многие здесь любят такой огород.
    • Так вам надо к источнику тока добавить двух-пороговый компаратор с раздельной установкой порогов . Напряжение упало ниже некоторого уровня - включается  зарядка , увеличилось более нужного - отключается  . Уровни у аккумуляторщиков спросите и будете на каждый тип  аккумулятора выставлять самый подходящий .
    • Напряжение на АБ при зарядке желательно глянуть. Батарея или заряженная, как выше предположили или не сильно живая.  Коротить выход желательно через нагрузку, для начала. Лампа, резистор мощный низкоомный.  Может девай на КЗ обидится , а может и нет.
    • Очень дешевый, но довольно качественный усилитель. Как то недавно выкладывали дорогущее изделие, я же наоборот, по максимуму стараюсь на всем экономить. Расскажу как за 2 тыс. рублей можно собрать с нуля усилитель мощностью более 100 ватт на канал: ИИП мощностью около 400ватт на основе хорошего ШИМ SG3525 + мощных полевиков FQPF10N60 (10А 600В). Усилитель B-класса доработан, имеет не плохие характеристики и хорошее звучание. Также есть защита ИИП от КЗ, самих усилителей от КЗ и перегрузки, а также от появления постоянного напряжения на выходе любого из каналов.   Плата очень крохотная, зато все вместе Далее купил очень хорошие радиаторы, которые нарезаются в любой размер: Толщина основания 10мм , по-моему это очень круто. Транзисторы ВК расположил по бокам, чтобы можно было закрепить на радиаторы Потом друга попросил нарезать дюральки 2 мм, передняя панель держится на клее очень хорошо Ну и дальше ничего сложного, пилим, сверлим крепим и так далее..   Питание +-37в на хх, мощность снял более 120ватт с канала, пропайка силовых дорожек медным проводом снизило искажения до 0,006% (1кГц 4 ом) Себестоимость малая, я стараюсь затариваться оптом у китайцев, но не более 3т.р выйдет точно: Кто хочет собрать подобное вот очень простая схемка:  Ну и бонусом прилагаю последюю версию печатки , и еще есть короткое видео работы ( для тех кто не верит, что это работает): Видео DarkAmp H_150.lay6