С Новым годом! Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/56: Рейтинг темы: голосов - 56, средняя оценка - 4.79
0 / 0 / 0
Регистрация: 18.11.2015
Сообщений: 5
1

Данные с двух каналов АЦП по очередно.[Решено]

09.01.2017, 23:48. Показов 10214. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.
Столкнулся с непоняткой, чип stm8s003f на время теста подцепил два переменных резистора на 100к и 68к на пины PD3 и PD2
код чтения ацп для канала 3 для канал 4 такой же
Код
int ADC_ch_3(void){

int data=0, t=0;
ADC_CSR_CH3;           //Выбераем канал
ADC_CR1_SPSEL8;        //Делитель на 18
ADC_TDRL_DIS(0);       //Отключаем тригер Шмидта
ADC_CR2_ALIGN_LEFT;    //Выравнивание по левому краю
ADC_CR1_ADON_ON;       //Запуск ADC

for(t=0;t<64;t++){     //Пауза
__asm__("nop\n");
}
data=ADC_DRH;          //Считываем показания
return data;
}
в программе сначала читаю 3 канал сохраняю в переменную, затем читаю 4 канал и сохраняю в другую переменную и по очиредно вывожу эти переменные в порт РС.
МК виснет.
Если опрашивать только один канал не важно 3 или 4 все работает.
НО на stm8s003k3 этот код работает как задумано.
Вопрос: я что то упустил/не правильно сделал в программе или я не учел каких то особенностей 003f3 ?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.01.2017, 23:48
Ответы с готовыми решениями:

АЦП несколько каналов
Нужно замерять сигналы с трех выводов АЦП МК, как это сделать грамотно?

Использование нескольких каналов АЦП
Всем привет. Пишу небольшую прогу для ATmega8, и возник вопрос как считывать данные сразу с двух...

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

Stm8l и несколько каналов АЦП
Здравствуйте! Помогите, пожалуйста разобраться в совместной работе ADC и DMA. Пробовал и в...

Большое количество АЦП каналов
Здравствуйте! Подскажите микроконтроллеры с количеством АЦП 50 или больше каналов. И есть ли...

16
0 / 0 / 0
Регистрация: 07.08.2016
Сообщений: 432
10.01.2017, 13:00 2
А если на stm8s003k3 опрашивать существующие каналы, например 2 и 3, то работает?
0
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
10.01.2017, 13:31 3
А если еще и вот так сделать после считывания:
Код
ADC_CSR &= 0x3f; // clear EOC & AWD flags
?
Кстати, а что делает функция ADC_TDRL_DIS(0); ?
Скажем, у меня конфигурация третьего канала такова:
Код
    // select PD2[AIN3] & enable interrupt for EOC
ADC_CSR = 0x23;
ADC_TDRL = 0x08; // disable Schmitt triger for AIN3
// right otygnment
ADC_CR2 = 0x08; // dont forget: first read ADC_DRL!
// f_{ADC} = f/18 & continuous non-buffered conversion & wake it up
ADC_CR1 = 0x73;
ADC_CR1 = 0x73; // turn on ADC (this needs second write operation)
И почему у вас младший регистр АЦП не считывается?
0
0 / 0 / 0
Регистрация: 18.11.2015
Сообщений: 5
10.01.2017, 23:09 4
Цитата Сообщение от Kitvym
А если на stm8s003k3 опрашивать существующие каналы, например 2 и 3, то работает?
С stm8s003k3 ошибся, я проверял на 0 и 1 каналах - работает, если 2 и 3 то данные выводит только с 3 канала.
Цитата Сообщение от Iddy_Im
А если еще и вот так сделать после считывания:
Код:
ADC_CSR &= 0x3f; // clear EOC & AWD flags

?
не чего не меняется

Цитата Сообщение от Iddy_Im
Кстати, а что делает функция ADC_TDRL_DIS(0); ?
ADC_TDRL_DIS(номер канала)-->#define ADC_TDRL_DIS(bit) ADC_TDRL|=(1<<bit)
Цитата Сообщение от Iddy_Im
И почему у вас младший регистр АЦП не считывается?
У меня выравнивание по левому краю, в регистре ADC_DRL остаются "моргающие биты"
или считывание ADC_DRL обязательно?
0
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
12.01.2017, 00:30 5
Обязательно!
0
0 / 0 / 0
Регистрация: 04.11.2012
Сообщений: 81
12.01.2017, 18:25 6
Причем в строго определенном порядке, в зависимости от выравнивания.
0
0 / 0 / 0
Регистрация: 18.11.2015
Сообщений: 5
12.01.2017, 23:23 7
Проблема решена.
Причина: невнимательность(в принципе как всегда)
#define ADC_CSR_CH3 ADC_CSR|=(1<<1)|(1<<0) тут устанавливается 1 в нулевой бит
#define ADC_CSR_CH2 ADC_CSR|=(1<<1) а тут этот бит не сбрасывается и получается всегда выбран 3 канал

Спасибо ребята, ваши советы учтены, код подправлен.
0
1 / 1 / 0
Регистрация: 01.02.2010
Сообщений: 2,010
13.01.2017, 00:35 8
Скинь пожалуйста последний вариант, сохраню себе чтобы потом долго не разбираться...
С одним каналом я давно разобрался, а вот с несколькими - вдруг там нюансы какие...
0
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
13.01.2017, 00:44 9
Не нужно magick numbers использовать. Лучше все в заголовочном файле определить!!
0
0 / 0 / 0
Регистрация: 18.11.2015
Сообщений: 5
13.01.2017, 22:58 10
Вот код, ни чего специфического если внимательно)
Код
void main(void)
{
unsykned int i=1, s=0;       //переменные для хранения данных
Init_HSE();                           //инициализируем переферию
gpio_init();

ADC_CR1|=(1<<6);         //Делитель на 18
ADC_TDRH|=(1<<5);       //Отключаем тригер Шмидта для канала 5
ADC_TDRH|=(1<<6);       //Отключаем тригер Шмидта для канала 6
ADC_CR2&=~(1<<3);      //Выравнивание по левому краю
ADC_CR1|=(1<<0);         //Первый запуск ADC

while(1)
{
/***********************читаем 5 канал************************************/
ADC_CSR&=~((1<<3)|(1<<2)|(1<<1)|(1<<0)); //сбрасываем выбранный до этого канал
ADC_CSR|=(1<<2)|(1<<0);                                 //Выбераем канал 5
ADC_CR1|=(1<<0);                                              //запуск преобразования
while(!(ADC_CSR&(1<<7)))                                 //ждем окончания преобразования
{
__asm__("nop\n");
}
s=ADC_DRH;                                                         //первым читается значемый регистр в данном случае ADC_DRH
i=ADC_DRL;
ADC_CSR&=~(1<<7);                                           //очищаем флаг окончания преобразования
PC_ODR=s;                                                           //выводим данные в порт С
delay(100);
s=i=0;
/***********************читаем 6 канал*************************************/
ADC_CSR&=~((1<<3)|(1<<2)|(1<<1)|(1<<0));
ADC_CSR|=(1<<2)|(1<<1);
ADC_CR1|=(1<<0);
while(!(ADC_CSR&(1<<7)))
{
__asm__("nop\n");
}
s=ADC_DRH;
i=ADC_DRL;
ADC_CSR&=~(1<<7);
PC_ODR=s;
delay(100);
s=i=0;
/**************************************************************/
}

}
0
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
13.01.2017, 23:14 11
АЦП можно обрабатывать в прерываниях, например, вот так.
0
1 / 1 / 0
Регистрация: 01.02.2010
Сообщений: 2,010
14.01.2017, 04:15 12
Код
   ADC_CR1|=(1<<6);         //Делитель на 18
ADC_TDRH|=(1<<5);       //Отключаем тригер Шмидта для канала 5
ADC_TDRH|=(1<<6);       //Отключаем тригер Шмидта для канала 6
ADC_CR2&=~(1<<3);      //Выравнивание по левому краю
ADC_CR1|=(1<<0);         //Первый запуск ADC
Почему так сделал?

у меня сделано так:

Код
   //настройка ADC
ADC_CR1_bit.ADON = 1;               //включить ADC
ADC_CSR_bit.CH = 0x03;               //номер канала
ADC_CR1_bit.SPSEL = 0x07;            //делитель скорости
ADC_CR2_bit.ALIGN = 0;               //выровнять влево
ADC_CR1_bit.ADON = 1;               //включить ADC
Или твой вариант (битовые операции) меньше кода занимает?
0
1 / 1 / 0
Регистрация: 01.02.2010
Сообщений: 2,010
14.01.2017, 04:20 13
Цитата Сообщение от Iddy_Im
И почему у вас младший регистр АЦП не считывается?
У меня вроде тоже не читается младший регистр, и все работает.
Код
   if (ADC_DRH < ADC_MARK_VOT)      PWR_ODR_bit = 1;   //шунтируется балласт и питание увеличивается
else                     PWR_ODR_bit = 0;   //добавляется балласт и питание уменьшается
ADC_CR1_bit.ADON = 1;                        //старт ADC
А какая может быть проблема, если не читать младший разряд?
0
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
14.01.2017, 11:05 14
Цитата Сообщение от ShodS
А какая может быть проблема, если не читать младший разряд?
Потом замахаешься искать, почему код то работает, то нет. АЦП устроен так, что при считывании первого байта второй считывается в промежуточный буфер. Если не считать второй, нарушается логика работы АЦП. В даташите картинки нарисованы.

У меня инит АЦП сделан так:
Код
#define ADC1_TDRH_MASK ((u8)((1 << (ADC1_CSR_CH8 - 8))      * 0 \
| (1 << (ADC1_CSR_CH9 - 8))      * 0 \
| (1 << (ADC1_CSR_CH10 - 8))   * 0 \
| (1 << (ADC1_CSR_CH11 - 8))   * 0 \
| (1 << (ADC1_CSR_CH12 - 8))   * 0 \
| (1 << (ADC1_CSR_CH13 - 8))   * 0 \
| (1 << (ADC1_CSR_CH14 - 8))   * 0 \
| (1 << (ADC1_CSR_CH15 - 8))   * 0))      // маска триггеров шмитта каналов 8-12

#define ADC1_TDRL_MASK   ((u8)((1 << ADC1_CSR_CH0)   * 1 \
| (1 << ADC1_CSR_CH1)   * 1 \
| (1 << ADC1_CSR_CH2)   * 1 \
| (1 << ADC1_CSR_CH3)   * 1 \
| (1 << ADC1_CSR_CH4)   * 1 \
| (1 << ADC1_CSR_CH5)   * 1 \
| (1 << ADC1_CSR_CH6)   * 1 \
| (1 << ADC1_CSR_CH7)   * 0))   // маска триггеров шмитта каналов 0-7

/*****************************************************************************
* Настройка АЦП
*****************************************************************************/
void init_adc (void)
{
// Инициализация АЦП
ADC1->CR1 &= ~ADC1_CR1_ADON;   // выключить АЦП для изменения настроек
ADC1->TDRH = ADC1_TDRH_MASK;   // маска используемых входов
ADC1->TDRL = ADC1_TDRL_MASK;   // маска используемых входов

ADC1->CSR = ADC_IN                   // измерять до входа 6
| ADC1_CSR_AWDIE   * 0      // запретить прерывания аналогового вочдога
| ADC1_CSR_EOCIE   * 1;   // Разрешить прерывание по окончании измерения
ADC1->CR1 = ADC1_CR1_SPSEL4            // частота преобразования 16МГц / 4 = 4 МГц
| ADC1_CR1_CONT    * 0      // режим однократного измерения
| ADC1_CR1_ADON      * 0;
ADC1->CR2 = ADC1_CR2_EXTTRIG   * 0      // внутренний триггер
| ADC1_CR2_EXTSEL   * 0      // внешний триггер не используется
| ADC1_CR2_ALIGN    * 0      // выравнивание влево
| ADC1_CR2_SCAN    * 1;   // Режим сканирования
ADC1->CR3 = ADC1_CR3_DBUF      * 1;   // с использованием буфера

ADC1->CR1 |= ADC1_CR1_ADON;            // включить АЦП
}
Использую сканирование сразу семи каналов.
Запускаю из прерывания таймера:
Код
/******************************************************************************
* Системное прерывание 1 мс
******************************************************************************/
INTERRUPT_HANDLER (SysTick_Timer_ISR, 23)
{
static u16         ADC_timer      = 0;

TIM4->SR1 = 0;   // Сбросим флаг прерывания
// счётчики работают с интервалом в 1 мс
system_time++;   // системный счётчик времени
if ((system_time - ADC_timer) >= ADC_TIMER)
{
ADC_timer = system_time;
ADC1->CR1 |= ADC1_CR1_ADON;   // запустить АЦП
}
}
И получаю результаты:
Код
static u8   buf [7];   // массив отсчётов ацп

/*****************************************************************************
* прерывание по окончании измерения
* здесь считывается напряжение сети
*****************************************************************************/
INTERRUPT_HANDLER (ADC1_End_of_conversion_ISR, 22)
{
u8 flags = ADC1->CSR;
flags &= ~ADC1_CSR_EOC;      // снять флаг прерывания
ADC1->CSR = flags;

buf [0] = ADC1->DB0RH;   // сохраняем значения
buf [1] = ADC1->DB1RH;
buf [2] = ADC1->DB2RH;
buf [3] = ADC1->DB3RH;
buf [4] = ADC1->DB4RH;
buf [5] = ADC1->DB5RH;
buf [6] = ADC1->DB6RH;

control_func ();
}
Кстати, при использовании буфера отпадает необходимость считывать два байта результата.
0
0 / 0 / 0
Регистрация: 18.11.2015
Сообщений: 5
14.01.2017, 16:09 15
Цитата Сообщение от ShodS
Код:
ADC_CR1|=(1<<6); //Делитель на 18
ADC_TDRH|=(1<<5); //Отключаем тригер Шмидта для канала 5
ADC_TDRH|=(1<<6); //Отключаем тригер Шмидта для канала 6
ADC_CR2&=~(1<<3); //Выравнивание по левому краю
ADC_CR1|=(1<<0); //Первый запуск ADC
Почему так сделал?

у меня сделано так:

Код
   //настройка ADC
ADC_CR1_bit.ADON = 1;               //включить ADC
ADC_CSR_bit.CH = 0x03;               //номер канала
ADC_CR1_bit.SPSEL = 0x07;            //делитель скорости
ADC_CR2_bit.ALIGN = 0;               //выровнять влево
ADC_CR1_bit.ADON = 1;               //включить ADC
Или твой вариант (битовые операции) меньше кода занимает?

нет, я пользуюсь SDCC, там нет библиотек, а свою пока не написал.

Цитата Сообщение от ShodS
У меня вроде тоже не читается младший регистр, и все работает.
Код:
if (ADC_DRH < ADC_MARK_VOT) PWR_ODR_bit = 1; //шунтируется балласт и питание увеличивается
else PWR_ODR_bit = 0; //добавляется балласт и питание уменьшается
ADC_CR1_bit.ADON = 1; //старт ADC

А какая может быть проблема, если не читать младший разряд?
у меня тоже работает без чтения младшего регистра, насколько я понял из мануала очистка этих регистров происходит автоматически после их прочтения. как и где это используется я пока не знаю.
0
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
14.01.2017, 16:15 16
У меня тоже как раз под sdcc писано: https://sourceforge.net/projects/stm8samples/
Правда, сейчас больше в сторону STM32F0 смотрю. Интересней они. Хотя, конечно, можно и с STM8 что-нибудь интересное сделать. Заказал "про запас" на работе десяток STM8S003 — их можно хоть даже как "умные регистры/триггеры" использовать.
0
1 / 1 / 0
Регистрация: 01.02.2010
Сообщений: 2,010
15.01.2017, 02:06 17
Цитата Сообщение от Iddy_Im
И почему у вас младший регистр АЦП не считывается?
Цитата Сообщение от SOVO
Потом замахаешься искать, почему код то работает, то нет. АЦП устроен так, что при считывании первого байта второй считывается в промежуточный буфер. Если не считать второй, нарушается логика работы АЦП.
Цитата Сообщение от somyk
у меня тоже работает без чтения младшего регистра, насколько я понял из мануала очистка этих регистров происходит автоматически после их прочтения. как и где это используется я пока не знаю.
Заинтересовало меня это...

Почитал DS, и вроде - правильное чтение двух регистров важно только в случае использования 10 бит значения... иначе, при чтении 8 бит - нет необходимости в чтении второго регистра...
так что в нашем случае - чтение только ADC_DRH - это нормально...

Еще у меня не выключались триггеры шмидта на задействованных ADC входах, я смотрю все их выключают, я сначала подумал что это как то влияет на результаты замеров ADC, но опять же из DS следует что это нужно только для уменьшения энергопотребления, и как я понял - никак не влияет на результаты замеров, так что тоже не критично...
0
15.01.2017, 02:06
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.01.2017, 02:06
Помогаю со студенческими работами здесь

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

AVR АЦП использование нескольких каналов
Кто пробовал использовать несколько каналов АЦП одновременно (ну, почти одновременно) - как это...

Опрос нескольких регулярных каналов АЦП STM32F100
Всем привет! Проблема с опросом нескольких регулярных каналов АЦП STM32F100 (Отл плата STM32F100VL...

Atmega16, АЦП и Протеус [решено]
Блин, второй день мучаюсь. Схема на AtMiko16, меряю АЦП напряжение на аккумуляторе. Очень похожая...

[РЕШЕНО] Не отвечает АЦП AD7124-4
Не могу установить связь с АЦП, не отвечает ни на какие запросы (пробовал перебирать все адреса...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Блоги программистов
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
Полезные поделки на Arduino, которые можно сделать самому
raxper 06.01.2025
Arduino как платформа для творчества Arduino представляет собой удивительную платформу для технического творчества, которая открывает безграничные возможности для создания уникальных проектов. Эта. . .
Подборка решений задач на Python
IT_Exp 06.01.2025
Целью данной подборки является предоставление возможности ознакомиться с различными задачами и их решениями на Python, что может быть полезно как для начинающих, так и для опытных программистов. . . .
С чего начать программировать микроконтроллер­­ы
raxper 06.01.2025
Введение в мир микроконтроллеров Микроконтроллеры стали неотъемлемой частью современного мира, окружая нас повсюду: от простых бытовых приборов до сложных промышленных систем. Эти маленькие. . .
Из чего собрать игровой компьютер
inter-admin 06.01.2025
Сборка игрового компьютера требует особого внимания к выбору комплектующих и их совместимости. Правильно собранный игровой ПК не только обеспечивает комфортный геймплей в современных играх, но и. . .
Обновление сайта www.historian.b­y
Reglage 05.01.2025
Обещал подвести итоги 2024 года для сайта. Однако начну с того, что изменилось за неделю. Добавил краткий урок по последовательности действий при анализе вредоносных файлов и значительно улучшил урок. . .
Как использовать GraphQL в C# с HotChocolate
Programming 05.01.2025
GraphQL — это современный подход к разработке API, который позволяет клиентам запрашивать только те данные, которые им необходимы. Это делает взаимодействие с API более гибким и эффективным по. . .
Модель полного двоичного сумматора с помощью логических операций (python)
AlexSky-coder 04.01.2025
def binSum(x:list, y:list): s=^y] p=x and y for i in range(1,len(x)): s. append((x^y)^p) p=(x and y)or(p and (x or y)) return s x=list() y=list()
Это мы не проходили, это нам не задавали...(аси­­­­­­­­­­­­­­­­­­­­х­р­о­н­н­ы­й счётчик с управляющим сигналом задержки).
Hrethgir 04.01.2025
Асинхронный счётчик на сумматорах (шестиразрядный по числу диодов на плате, но наверное разрядов будет больше - восемь или шестнадцать, а диоды на старшие), так как триггеры прошли тестирование и. . .
Руководство по созданию бота для Телеграм на Python
IT_Exp 04.01.2025
Боты для Телеграм представляют собой автоматизированные программы, которые выполняют различные задачи, взаимодействуя с пользователями через интерфейс мессенджера. В данной статье мы рассмотрим,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru