kan35 7 23 июля, 2023 Опубликовано 23 июля, 2023 (изменено) · Жалоба Доброго дня всем! Продолжаю пилить проект с PIC18F67J94 | Microchip Technology, столкнулся с одной особенностью непонятной. Инициализирую АЦП: void adc_init(void) { TRISFbits.TRISF7 = 1; TRISGbits.TRISG3 = 1; ANCON2bits.ANSEL11 = 1; ANCON2bits.ANSEL14 = 1; ADCON1Hbits.MODE12 = 0; //10 bit ADCON1Lbits.SSRC = 7; // automatic sample and hold off and conv start ADCON3Hbits.SAMC = 0b11111; // the lowes frequency -Tad/samc ADCON3Lbits.ADCS = 63; //64·2/Fosc = TAD ADCON1Hbits.ADON = 1; } По сути самый простой режим с поллингом. Частоты очень низкие, время сэмплирования - большое. И порадовался, когда он заработал, но далее захотел оцифровать еще один канал и тут началось. unsigned char adc_convert(unsigned char input) { ADCHS0L = input; ADCON1Lbits.SAMP = 1; while(ADCON1Lbits.DONE == 0) //Wait until result available ; return (ADCBUF0>>2); } Показания начали скакать в весьма большом диапазоне. Разбирался, но идей не было, начал пробовать и помогло отключение и включение перед каждым замером: unsigned char adc_convert(unsigned char input) { ADCON1Hbits.ADON = 1; ADCHS0L = input; ADCON1Lbits.SAMP = 1; while(ADCON1Lbits.DONE == 0) //Wait until result available ; ADCON1Hbits.ADON = 0; return (ADCBUF0>>2); } Но это же не решение? Что я не так делаю? Изменено 23 июля, 2023 пользователем kan35 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Driver_GV 1 24 июля, 2023 Опубликовано 24 июля, 2023 · Жалоба Добрый день. Неправильная схема. Почитайте http://www.leoniv.diod.club/articles/adcstm32/adcstm32.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 24 июля, 2023 Опубликовано 24 июля, 2023 · Жалоба Если Вы про то, что выходное сопротивление источников слишком большое, то почему если канал не менять, то оцифровывает отлично. И скачет даже 1кОм-ный источник. Второй - 15кОм. Ну и в целом, я же сделал максимальные делители, думаю, что то в последовательности или в настройке не то... не могу разобраться, прошу опытных подсказать! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 24 июля, 2023 Опубликовано 24 июля, 2023 · Жалоба 1 час назад, kan35 сказал: Если Вы про то, что выходное сопротивление источников слишком большое, то почему если канал не менять, то оцифровывает отлично. Если совсем коротко и сильно упрощенно, не вдаваясь в подробности вашей схемы и особенности конкретного АЦП, то ситуация выглядит, примерно, так: Когда вы переключаете внутренний вход АЦП с одного внешнего канала на другой, то происходит некоторый переходной процесс, связанный с перезарядкой внешних (в том числе, паразитных) и внутренних буферных емкостей АЦП. Прежде чем начать измерение - запустить процесс АПЦ, нужно дождаться завершения этих переходных процессов. Так, чтобы напряжение на "внутреннем" входе АЦП стало равным внешнему, измеряемому сигналу, с заданной точностью. Обычно, в ДШ указыватеся это, минимально необходимое, время для определенных условий. В реальности, с учетом вашей внешней схемы, оно может быть значительно больше. Вот его и нужно попытаться рассчитать (оценить) и проверить на практике. Если это время - между переключением канала и пуском АЦП - не выдерживать, то будете оцифровывать свой переходной процесс. Отсюда и "болтанка" результатов. Примерно, так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 24 июля, 2023 Опубликовано 24 июля, 2023 (изменено) · Жалоба У меня такая мысль тоже была, и я даже ставил задержку 1мс, но это не помогало, попробую увеличить. У меня схема совсем простая - термистор 1кОм к земле и 2кОм к 3.3В, и второй источник - делитель 22кОм/62кОм. Частота тактирования АЦП = 48 000 000 / (2*64) = 375кГц -> Tad=2.7мкс Время сэмплирования = 31*Tad = 83мкс должно же это быть достаточно для 1кОм Хотя я думаю, не в этом проблема, но не нашел в даташите емкость выборки хранения. Изменено 24 июля, 2023 пользователем kan35 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 24 июля, 2023 Опубликовано 24 июля, 2023 (изменено) · Жалоба Схему входов можете показать? P.S. Временно, для проверки, поставьте непосредственно на оба входа м/с керамические конденсаторы 0,1 мкф к земле. Болтанка должна прекратиться. Изменено 24 июля, 2023 пользователем quark добавлено Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 24 июля, 2023 Опубликовано 24 июля, 2023 (изменено) · Жалоба Не, не в электрике дело, что то в цифре. У меня каналы перепутываются. Первый становится вторым, второй - первым (только сейчас это понял). Полагаю, что данные попадают в стек ADCBUF и я все время вычитываю предыдущее значение. Что то в регистрах настройки или не сбрасываю модуль как положено... не понятно... Изменено 24 июля, 2023 пользователем kan35 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 24 июля, 2023 Опубликовано 24 июля, 2023 · Жалоба 8 минут назад, kan35 сказал: Не, не в электрике дело, что то в цифре. Тем не менее, временные конденсаторы рекомендую поставить. Тогда сразу увидите, где причина - в цифре или в схеме. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 24 июля, 2023 Опубликовано 24 июля, 2023 (изменено) · Жалоба Да, это потом сделаю Убрав опрос DONE оно корректно заработало, каналы не путаются, значит не в стеке дело, а в бите готовности результата: unsigned char adc_convert(unsigned char input) { ADCHS0L = input; ADCON1Lbits.SAMP = 1; //while(ADCON1Lbits.DONE == 0) //Wait until result available vTaskDelay(1); return (ADCBUF0>>2); } как так то... Изменено 24 июля, 2023 пользователем kan35 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 24 июля, 2023 Опубликовано 24 июля, 2023 · Жалоба Похоже я догадался таки. Бит готовности в 1це пока продолжается сэмплирование, то есть он отвечает только за конвертацию результата! Наверное так это нужно понимать? Поэтому делать нужно так: unsigned char adc_convert(unsigned char input) { ADCHS0L = input; ADCON1Lbits.SAMP = 1; while(ADCON1Lbits.SAMP == 1) //Wait until sampling finish ; while(ADCON1Lbits.DONE == 0) //Wait until result available ; return (ADCBUF0>>2); } Хотя в документации пример вот какой: Конечно, он "с виду" будет работать, так как канал не меняется. Собственно как у меня и получалось. Вот такие дела. Неужели такая детская ошибка в документации???😎 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться