Помогите подружить мк 8051 ( в протеусе взял функциональный аналог AT89C51RD2) и ацп ADC0808. Вроде все просто, нашел схему, нашел даже пример кода на си, сделал, вывожу данные через uart, на выходе 6 -ти значные числа, хотя максимум может быть 255, уже не знаю в чем дело может быть. Пример взял вот отсуда http://www.8051projects.net/wiki/ADC080 ... g_Tutorial, прикрепляю проект в протеусе.
Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.
denya, 1 - замените в симуляции генератор на логическом элементе генератором протеуса на 300-500 кГц. 2 - Vref сделайте 5 В, ваши 12 В... это уж слишком путает показания. 3 - посмотрите в своем проекте функцию
Цитата:
printf ("%u\n", ADC_rezult());
Сейчас она передает в терминал слово, а не байт. Если перевести принятые цифры в шестнадцатиричный вид, то вы увидите, что то что принимает сейчас терминал выглядит так: ХХ00 - это два байта, где ХХ это байт с вашей полезной информацией, той что принял МК от АЦП через порт1. А 00 это, то что вы добавляете в программе функцией printf, просто два нуля. Поэтому такие странные цифры в терминале Проще говоря, смотрите printf или выводите инфу в терминал просто загрузив байт данных в SBUF
Да, ошибка была как раз в том, что выводило слово, а не байт. Исправил вызовом функции через переменную: U_AB = ADC_AB_U(); Теперь выводит диапазон верно, но значение не совсем корректны: например при опорном напряжении в 5 вольт и входящем 1, выдает значение 204, что соответствовать должно 4 вольтам, а не 1. Соответственно наоборот тоже самое, подаю 4 вольта, на выходе 51. Что странно, 0, 2, 3 и 5 вольт если подать, выдает корректно. В даташиде посмотрел формулу: U = N/256*Uref. В чем может быть ошибка?
Да, ошибка была как раз в том, что выводило слово, а не байт. Исправил вызовом функции через переменную: U_AB = ADC_AB_U();... ...В даташиде посмотрел формулу: U = N/256*Uref. В чем может быть ошибка?
U = (N*Vref)/256 Надеюсь вы эту формулу имеете ввиду, ваша запись не совсем понятна Однако дело не в этом. Посмотрите ДШ еще более внимательно и вы увидите, что у вас просто перепутаны местами MSB и LSB! Картинка, которую вы нашли вместе с проектом и на которой показано подключение микросхем АЦП и МК вводит в заблуждение Теперь сделайте новое подключение порта МК к АЦП так: 21 вывод АЦП к Р1.7 20 вывод АЦП к Р1.6 ... 17 вывод АЦП к Р1.0 После этого ваша программа заработает правильно Или, не трогая схему подключения, в программе "отзеркальте" принятый байт с АЦП. Например, приняли А0Н, измените его в 05Н. Приняли 80Н, измените его в 01Н и так далее. Совет, протеусу все равно, а вам удобнее будет если частоту на АЦП подавать небольшую. Чтобы данные в терминале были нагляднее сделайте Vref = 2,55 Вольт. Тогда цифры в терминале будут соответствовать входному напряжению, но без десятичной точки. P.S. А вот как вы через переменную перешли от 2х байт к одному при работе функции printf не понял?
Исправил вызовом функции через переменную: U_AB = ADC_AB_U();
- не понял как работает? Вообще, заглянул в доку от Кейла и понял, что проще можно делать. Например так:
Код:
number = 173; //например надо вывести 1,73 V. Выводим: printf ("%bu,%bu%bu%c V\n",number/100,(number/10)%10,number%10);
В терминале будет: 1,73 V Или просто вывести 173:
Код:
printf ("%bu\n",number);
denya писал(а):
p/s. Нашел метод отзеркаливания байта, но не понял до конца суть работы:
Хорошая функция, мне понравилась, только в названии InverseByte некорректно. Но это неважно. В условии if( b & 1 ) единица это маска, накладываемая на байт:
Код:
0b00110000 //исходный байт & 0b00000001 //маска
Условие сравнивает биты в самом младшем разряде байтов. То есть, восемь раз проверяем, что находится самом младшем бите изменяемого байта b. Если проверяемый(самый младший) бит равен единице, то пишем единицу в соответствующую позицию измененного(зеркального) байта ret. Если нет, то там остается нуль. Затем сдвиг вправо исходного байта и счетчика i, значит потом будет проверяться следующий бит.
Хорошая функция, мне понравилась, только в названии InverseByte некорректно.
Действительно, название функции некорректно. Правильное название этой операции РЕВЕРСИЯ. В книге Генри Уоррена "Алгоритмические трюки для программистов" приводится вариант этой операции без использования цикла. Думаю, что с учётом сказанного функцию можно переписать в виде:
uint8_t ReverseByte(uint8_t b) { uint8_t ret;
ret = ((b & 0x55)<<1) | ((b & 0xAA)>>1); ret = ((ret & 0x33)<<2) | ((ret & 0xCC)>>2); ret = ((ret & 0x0F)<<4) | ((ret & 0xF0)>>4);
return ret; } Такая функция, тоже должна понравиться
Во многих силлабовских 8051 контроллерах (например, серия C8051F9xx и в новой серии EFM8) имеется модуль CRC для подсчёта контрольной суммы, в состав которого входит блок аппаратной инверсии битов байта. Для этого байт b подлежаший инвертированию следует сначала записать в регистр CRC0FLIP. При последующем чтении из этого регистра порядок битов ранее записанного байта автоматически инвертируется. На С это занимает 2 строчки кода: CRC0FLIP = b; b = CRC0FLIP;
Хорошая функция, мне понравилась, только в названии InverseByte некорректно.
Действительно, название функции некорректно. Правильное название этой операции РЕВЕРСИЯ. В книге Генри Уоррена "Алгоритмические трюки для программистов" приводится вариант этой операции без использования цикла. Думаю, что с учётом сказанного функцию можно переписать в виде:
uint8_t ReverseByte(uint8_t b) { uint8_t ret;
ret = ((b & 0x55)<<1) | ((b & 0xAA)>>1); ret = ((ret & 0x33)<<2) | ((ret & 0xCC)>>2); ret = ((ret & 0x0F)<<4) | ((ret & 0xF0)>>4);
return ret; } Такая функция, тоже должна понравиться
Да, я использовал именно эту функцию, а с циклом для общего развития интересовался
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения