Перейти к содержанию

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


Рекомендуемые сообщения

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

//******************************************************************************
//Инициализация АЦП
//******************************************************************************
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
Ссылка на комментарий
Поделиться на другие сайты

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

#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();
 }
}

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

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

ADC_CR1_bit.ADON = 1;

while(!ADC_CSR_bit.EOC);

ADC_CSR_bit.EOC = 0;

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

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

// 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
Ссылка на комментарий
Поделиться на другие сайты

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

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

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

Делюсь решением проблемы, может найдется еще такой бедолага, у которого возникнет такая же проблема :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
Ссылка на комментарий
Поделиться на другие сайты

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

Не знаеш как? Спроси у Google'а !!!

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

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

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
Ссылка на комментарий
Поделиться на другие сайты

  • 2 года спустя...

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

 

Может быть, вы могли бы поделиться окончательным кодом этого? Я сам не могу понять.

Изменено пользователем Falconist
Перевод
Ссылка на комментарий
Поделиться на другие сайты

  • 6 лет спустя...

Тема конечно очень старая.  Но мне помогла, дала пинок в нужном направлении. Я аналогичным образом тупил и очень долго. Только на ST не стал мысленно гнать. Давно уже понял, что 99,(9)% глюков камня в голове у программера. Как всегда, надо читать мануал. В нем в нескольких местах написано, что порядок чтения регистров ADC_DRH и ADC_DRL, зависит от состояния бита ALIGN регистра ADC_CR2. А именно, если выравнивание результата АЦП настроено по правому краю, то сначала читается младший байт и наоборот. И это не касается буферных регистров результата АЦП.

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

В общем не могу не добавить, может кому-то пригодится.

 

Изменено пользователем Z_h_e
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

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

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...