Несколько постов назад я заикнулся о том, что выдам на гора программу-пример для работы с АЦП. Пора за базар отвечать :) Делать мы будем простенький цифровой вольтметр с замашками осциллографа. Точнее осциллографом это можно назвать с большой натяжкой, скорей самописец. Так, побаловаться.
Задача:
Получить по очереди напряжение с трех каналов АЦП и отправить его по последовательному порту в комп. По запросу с компа показвыать напряжение на каждом из измеряемых каналов. В компе полученный поток байт представить в виде графика.
Теоретическую часть я уже разобрал, осталось поставить эксперимент в реальном железе.
Собираем схему на демоплате Pinboard.
Нам нужны три разных напряжения. Их проще всего получить с переменных резисторов, включенных потенциометрами. При этом средняя точка переменного резистора подключается к каналу АЦП, а крайние точки к +5 и GND питания. При этом при вращении рукоятки резистора напряжение на его средней точке будет меняться от нуля до +5 вольт. Резистор, подключенный к каналу ADC0 уже так включен и никаких лишних движений не требует. А вот два других надо будет подключить. На видео и на фотках хорошо видно что и куда идет.
![]() |
Теперь осталось написать код. Код я сделаю на прерываниях и конечных автоматах.
Вначале переменные:
1 2 3 4 5 | ; RAM ======================================================== .DSEG RX_sel: .byte 1 ; Переменная состояния отправки данных ADCH_sel: .byte 1 ; Переменная текущего канала АЦП ADCCH: .byte 8 ; Восемь байт под хранение результатов АЦП. По байту на канал. |
Таблица прерываний стандартная, ее я приводить не буду. Сами увидите в проекте, что можно будет скачать в конце статьи
Прерывание по приему байта. Работает просто. Принятый байт проверяет на код цифры 0, 1 или 2. Если совпадает — то выставляет соответствующую переменную и в терминал начинают валиться данные с этого канала АЦП. Если не совпадает — выставляет значение которое блокирует отправку любых данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ; Interrupts ============================================== RX_OK: PUSHF ; Сохраняем SREG и R16 в стеке IN R16,UDR ; Берем принятый байт CPI R16,'0' ; Case 0 BREQ Ch_0 CPI R16,'1' ; Case 1 BREQ Ch_1 CPI R16,'2' ; Case 2 BREQ Ch_2 LDI R16,3 ; Defaul RJMP EXIT_RX Ch_0: LDI R16,0 ; Если выбран 0 канал RJMP EXIT_RX Ch_1: LDI R16,1 ; Если выбран 1 канал RJMP EXIT_RX Ch_2: LDI R16,2 RJMP EXIT_RX ; Если выбран 2 канал EXIT_RX: OUT UDR,R16 ; Даем эхо и инициируем передачу. STS RX_sel,R16 ; Сохраняем выбраное значение канала POPF ; Достаем регистры из стека RETI |
Прерывание по окончании отправки одного байта берет следующее значение и шлет его снова. Тем самым инициализируюя непрерывную передачу данных по прерываниям.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ;-------------------------------------------------------------------- TX_OK: PUSHF ; Сохраняем флаги и R16 LDS R16,RX_sel ; Смотрим какой канал надо слать CPI R16,0 ; Case 0 BREQ Send0 CPI R16,1 ; Case 1 BREQ Send1 CPI R16,2 ; Case 2 BREQ Send2 ; Default RJMP EXIT_TX Send0: LDS R16,ADCCH ; Шлем выбраный канал в UART OUT UDR,R16 ; Смещение адреса канала задается относительно базы ADCCH RJMP EXIT_TX Send1: LDS R16,ADCCH+1 ; Тут лежат данные первого канала OUT UDR,R16 RJMP EXIT_TX Send2: LDS R16,ADCCH+2 ; А тут второго. Адреса все фиксированные. OUT UDR,R16 RJMP EXIT_TX EXIT_TX: POPF ; Достаем все из стека, выходим. RETI |
Прерывание готовности АЦП работает несколько сложней. Суть в том, что работа АЦП у нас идет по такому алгоритму:
Запускаем одиночное АЦП преобразование и ждем прерывания готовности АЦП.
В прерывании забираем данные.
Сохраняем данные.
Переключаем канал с которого мы снимали показания.
Запускаем следующее преобразование (уже для другого канала)
Выходим из прерывания и ждем следюущего прерывания.
Данный алгоритм хорош тем, что все делается автоматически, в режиме конечного автомата. В результате у нас в памяти, в массиве ADCCH, всегда лежат 8 свежих значений, снятых с 8ми каналов АЦП. Остается их только считать и использовать. При этом главный цикл крутится по своим делам и не парится, зная, что свежие значение всегда его ждут.
В самом прерывании активно используется работа с масками. Для того, чтобы сменить номер канала. Номер канала лежит в последних трех битах регистра ADMUX и может иметь значение от 0 до 7 (000 и 111 соотвествтенно). И нам надо в каждом вызове увеличивать значение канала, перебирая их по очереди. Просто так икрементировать ADMUX нельзя, т.к. кроме номера канала там лежат еще и быти управления АЦП, выравнивания и опорного напряжения — они могут сбиться. Приходится изощряться с масками, чтобы их не задеть.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | ADC_OK: PUSHF PUSH ZL PUSH ZH PUSH R17 IN R16,ADMUX ; Берем ADMUX ANDI R16,0x07 ; Маской отрезаем лишние биты. Получаем номер канала ; С которого было снято измерение. MOV R17,R16 ; Cохранили копию номера канала LDI ZL,low(ADCCH) ; Берем адрес начала массива с будущими данными. LDI ZH,High(ADCCH) ADD ZL,R16 ; Прибавляем к адресу наш номер канала. ; Если было переполнение, то будет флаг С CLR R16 ; Флаг важен, а значение в R16 уже нет. Но нам нужен ноль ; Возьмем и сделаем его из R16. ADC ZH,R16 ; Сложим флаг возможного переполнения с ZH ; Т.о. у нас получается в Z = адрес (ADCCH+номер канала) ; И значения из разных каналов ложатся в разные переменные массива ; с адресом базы ADCCH IN R16,ADCL ; Младшее значение нам не надо. Но считать его нужно. IN R16,ADCH ; Берем в R16 значение из АЦП ST Z,R16 ; Сохраняем его в массив по нужному адресу IN R16,ADMUX ; Опять взяли ADMUX ANDI R16,0xF8 ; На этот раз обнулили номер канала. Оставив остальные биты нетронутыми INC R17 ; Увеличили на 1 заныченный ранее номер канала ANDI R17,0x07 ; Обрезали лишние биты, чтобы не было переполнения. ; Число по маске 0х07 в принципе не может быть больше 7. ; А каналов у нас от 0 до 7. То что надо. OR R16,R17 ; Слепили старое значение из ADMUX c новым значением номера OUT ADMUX,R16 ; Канала. Т.е. по факту сделали MUX = MUX+1 выбрав следующий канал ; Спихнули его в регистр ADMUX. Все, следующий канал выбран. Можно запускать ; Следующее преобразование. OUTI ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(0<<ADATE)|(3<<ADPS0) ; Запустили POP R17 ; Корректный выход из прерывания. POP ZH POP ZL POPF RETI |
Также в программе есть инициализация UART (я запустил его на скорости 1200) и инициализация и первичный запуск АЦП.
Стоит обратить внимание на инициализацию UART — там мы разрешаем прерывания по приему и передаче.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ;Internal Hardware Init =========================================== Reset: STACKINIT ; Инициализация стека RAMFLUSH ; Очистка памяти ; Usart INIT .equ XTAL = 8000000 .equ baudrate = 1200 .equ bauddivider = XTAL/(16*baudrate)-1 uart_init: LDI R16, low(bauddivider) OUT UBRRL,R16 LDI R16, high(bauddivider) OUT UBRRH,R16 LDI R16,0 OUT UCSRA, R16 ; Прерывания разерешены, прием-передача разрешен. LDI R16, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(0<<UDRIE) OUT UCSRB, R16 ; Формат кадра - 8 бит, пишем в регистр UCSRC, за это отвечает бит селектор LDI R16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1) OUT UCSRC, R16 ; ADC Init ; Опорное напряжение с AVCC, выравнивание влево, канал 0. OUTI ADMUX,1<<REFS0|1<<ADLAR|0<<MUX0 ; End Internal Hardware Init =================================== ; Run ========================================================== ; Запуск однократного преобразования. Все остальное сделаем в прерываниях. SEI OUTI ADCSRA,(1<<ADEN)|(1<<ADIE)|(1<<ADSC)|(0<<ADATE)|(3<<ADPS0) ; End Run ====================================================== |
Первый раз АЦП запускается вручную. А потом начинает молотить по прерываниям самостоятельно.
Главный же цикл вообще пустой. Он тут и не нужен. Там можно смело писать любой код, а данные АЦП загребая из памяти. Главное помнить где они лежат ;)
1 2 3 4 | ; Main ========================================================= Main: NOP ; Весь цимес в прерываниях. Нам тут делать нефиг. RJMP Main |
Прошиваем программу в контроллер, жмем RESET
Запускаем теперь чумовую программку Terminal и подсоединяемся на скорости 1200бод. Ничего не происходит, но не беда. Надо сказать контроллеру какой какой вывод АЦП мы хотим поглядеть. Отправляем 0 — в ответ нам полетят данные с нулевого канала. Если отправить 1, то с первого, а если 2, то со второго.
Включив режим показа графика начинаем яростно крутить резисторы из стороны в стороны, наблюдая как наша кривая описывает зигзаги.
![]() |
Сложно? Нет! Буквально пара команд, а сколько удовольствия!
В АЦП заложено столько возможностей, поэтому этой статьей рассказ об АЦП не оканчивается. В следующий раз я расскажу о простейших алгоритмах фильтрации данных, а также о том как сделать АЦП из аналогового компаратора в тех МК, где АЦП не было и в помине.
Данная статья была полностью переписана с учетом заточки курса на демоплату Pinboard. Но предыдущий вариант остался в виде архива.
Не смотрел код, но по описанию я не вижу здесь проверки завершения передачи данных по УАРТу. Представления не имею, надо ли это в данном случае, задние полушария говорят, что АЦП медленнее УАРТа при средних скоростях, но все же.
И вообще. Если юзается восьмибитный УАРТ, то ИМХО правильнее писать не так. В обработчике прерывания АЦП скидываем значение в переменную — и ВСЕ. Потом в основном цикле та переменная сливается в УАРТ, но только если завершена предыдущая передача. Т.о. не будет никаких перегрузок пропускной способности УАРТа только из-за скорости АЦП. То же самое можно делать и в обработчике, просто я не любитель растягивать обработчики хоть на один байт больше необходимого.
Отправку в УАРТ из переменной можно поручить обработчику конца передачи.
недавно наткнулся на uzebox — где чел собрал игрой комп на основе авра.
вот это я понимаю ) полное изучение возможностей + тетрис под рукой.
всегда мечтал свой такой изобрести, возможно скоро начну.
имхо на таком приятней изучать, что и как
http://belogic.com/uzebox/index.htm
Видел я этот комп. Прикольная вещь получилась, ага.
А почему бы и нет? Игрались в своё время на синклере? А мега по производительности рвёт z80 как Тузик грелку. Ведь RISC всё-таки. (Хотя, глядя на систему команд z80, систему команд меги трудно назвать сокращённой)
Сделать комп — не проблема. Проблема — программы. Собрав Синклера или хотя бы Микрошу, ты сразу получал доступ к сотням уже готовых программ для них, в том числе и компиляторы Бэйсика, Ассемблера, Форта, редакторы текстовые и графические, игры, и много еще чего. Для Синклера была даже удобная оболочка для загрузки программ, похожая на Нортон Командера. Сделав же свой, не похожий на другие, комп, ты должен будешь писать все это сам, начиная с драйверов клавиатуры, дисплея, джойстиков, графики, и кончая самими играми, редакторами, компиляторами. Даже собрав в 84г свой компьютер, совместимый программно и аппаратно (по основным сигналам шины) с «МИКРО 80», я уже мог воспользоваться его программой «МОНИТОР», и BASIC, и Макро Ассемблером, хотя и в 16-ричном коде пописал немало, в основном программки для программаторов. Тогда, в начале пути, это было интересно и вызывало большой энтузиазм. Сейчас, когда без мыша и Виндов вроде и делать нечего, самодельный комп покажется скучной и никчемной железякой. Ну, соединишь между собой пару микросхем и разьемы, подключишь к телевизору, потыркаешься в «TETRIS». Через неделю все это надоест, и ты закинешь его подальше… И пойдешь опять гонять Фар кри или Контрол страйк.
точно такие же мысли можно подвести под всё, что тут описывается.
минироботы на пиках и аврах? в магазине есть уже давно на порядок лучше и по цене доступные. плавают и летают.
какие-нибудь самодельные осциллографы? хороший hp цифровой — это сказка.
сенсоры, передатчики, забавные игрушки? так же по пунктам.
такой миникомп нужен в основном не для игр или ностальжи, а для того, чтобы чел, его собравший, поверил в свои силы. 90% из моих знакомых, кто знает про такое — только на словах могут объяснить, как они легко его соберут.
зы! кроме того, сделать-придумать узкоспециализированную задачу для такого компа думаю, что не сложно. написать один раз программу и пусть он сидит и тупо с видимокамеры движущихся человечков засекает или из шума голоса нужные гармоники )
Так это и будет не компьютер, а микроконтроллер. И под конкретную задачу его можно хорошо оптимизировать. И почему бы тогда не сделать его в виде робота? Возможностей и интереса будет намного больше, чем просто у коробки на столе, привязанной кабелем к телевизору. Одни мозги, без какой-либо периферии, когда не на что реагировать и нечем управлять — это скучно…
тогда с роботом тоже надо подходить основательно.
я помню, как в детстве читал книжки про «это» и ходил в соответствующие кружки. в районе 60-70ых таких роботов делали, что выглядели как роботы )))
и всякой механики, и научных идей. и всё из подручных элементов. тем бы людям наши вычислительные мощности — они б на луну ракету запустили )
Так и запускали. И не только ракеты, но и пара луноходов месяцами бегали, и пробурили Луну на несколько метров вглубь, и колонку грунта метра три длиной на Землю привезли еще в начале 70х. У американцев в то время была только высадка на Луну, и то до сих пор многие американцы в это не верят, хотя вроде аж несколько человек побывало.
Потом были полеты к Марсу, Венере, комете Галлея… Кстати, у американцев с Венерой ничего серьезного так и не получилось, и они предпочли более простой и удобный Марс. А Советские аппараты на Венеру опускались, и даже некоторое время работали на поверхности, при 500 градусной температуре.
Роботу не обязательно выглядеть как человек или роботы из фильмов. Конструкция должна быть рациональной и функциональной. А вот уж над функциональностью стоит повозиться. Робот для одной функции — это просто автомат. Чем их больше — тем интересней, тем «разумней» он будет выглядеть и действовать, тем больше опыта приобретешь. Ну и двухсторонняя связь желательна для интерактивного общения. Он тебе постоянно сообщает о своем состоянии и окружении, ходе выполнения задач, ты даешь ему новые задания…
я пролистал последние выпуски журнала Хацкер, про который пишет ДиХальт
там роботами называют даже моторчик со свето- и фотодиодом.
роботы, которые летали на Венеру — эт хорошо. но я сомневаюсь, что на этом блоге есть больше 2ух человек, кто хотя бы раз удачно запускал своего робота )
Было бы «культурней» в обработчике UART сохранять регистор SREG, ибо флаги портятся (командой CPI …). Это хорошо, что в основном цикле пусто, а то были бы глюки.
И может стоить заметить, что читать ОДНУ половинку ADCx можно только старшую (ADCH). А если бы понадобилась только младшая (допустим если сдвиг вправо), то читать надо обязателно обе и притом сначала ADCL, а потом ADCH.
Ну я же говорю все через задницу тут :) По поводу половинок регистра ацп, да, но на то есть теоретическая часть :) Ну и я планирую еще пару практических примеров по АЦП сделать. С алгоритмами усреднения и накопления. Типо программное повышение точности.
И, кстати первый коментарий совершенно справедлив. И дело не в скоростях UART и АЦП. У тебя передача по УАРТ в двух местах (эхо при приёме с компа и при завершении АЦП), и в обоих не проверяется его готовность. Могут быть накладки, хотя и не смертельно…
Ага и это тоже, согласен. УАРТ захлебывается и теряет байты. В данном случае это некритично т.к. они один фиг идут потоком из более быстрого АЦП, но на ответственной передаче такой поток недопустим.
Стоолкнулся вот с такой проблемкой:
Мое устройство изначально безошибочно работало (не важно , что выполняло)результат пересылало в ПК, но потом я задумал снимать аналоговую велечину. Для проверки АЦП я через реастат подавал напряжения в пределах от 0.2-3.5В на вход ADC0. И Вот что случилось: все замерло. Промучался полдня и не фига не выходит. Есть подозрения, что мог запортачить микруху, но как? разве можно через вход ацп?
При этом программатор ее не видит и УАРТ перестал код гнать. Сразу скажу, что осцилографа нет.
Помогите словом. Что случилось?
Можно побробней о USB датакабеле на чипе Profilic. Это куда его тут воткнуть можно? И разве в USB дата-кабелях есть чипы?
P.S. Описочка:
«О том что значат быти конфигурации UART»
д.б. «биты»
У меня есть такой кабель. Покупал для своего телефона Motorola E365 (ныне покойного). Купил в стандартном ларьке, торгующими телефонами за 100 рублей. Сам удивился цене. При установки в систему, насколько я помню, создаёт виртуальный COM порт.
Помогите сделать такое же на stk500? Что то у меня не выходит :(
з.ы. Atmega 8535
DI HALT, подскажи, пожалуйста, на чём можно сделать. ТЗ такое: сделать многоканальный вольтметр с подключением по USB. Скорость опроса вольтметра не очень высока: на большинстве каналов хватит 10-20 в секунду; но надо сделать один-два побыстрее для некоего подобия осциллографа в звуковом диапазоне. Число каналов от 4х. А на стороне компа желательно чтобы это всё программами виделось как COM-порт[ы], ибо написано много в Инете про него.
На форуме Elementus уже сделал почти такое. Можешь у него спросить, правда он на пиках.
А так все просто — АЦП опрашивает по очереди каналы и шлет данные в сом порт.
Нужна помощь. ниче понять не могу. мега8 работает на 8Мгц от внутреннего генератора. посылаю 2 байта данных с компа по ЮАРТ на скорости 9600 — работает нормально, контроллер шлет их обратно, меняю скорость — бред получаю.
Может у тебя срыв стека или кривой выход из прерывания? Или конфликт прерываний. А на скорости 9600 все очень удачно разруливалось само собой?
Скорость (значение бодрейта) верно высчитал?
работаю через FT232RL. может это как-то влияет?
Я через фт всегда гнал не обращая внимания на скорость.
с мегой 16 та же фигня. на 9600 шлет с Ацп по юарту на terminal четко, а на других скоростях такое гонит. надо бы через настоящий com посмотреть, а не через FT232.
Все понял. На медленных скоростях, до 38400, и без кварца все нормально, а вот на высоких — гонево. Поставил кварц заточенный под ЮАРТ — 7.3728 Мгц- и все прет как надо на 115200.
что то никак :( кварц 7.3728 Мгц скорость 9600, в терминал летят одни буквы «Я» на любую посылку, причем гадит пока дисконект не сделаешь. как сделать на основе этого проектика заглушку для уарта т.е чтоб эхо контроллер реализовывал.
Я собрал схему на Атмеге16, которая считывает с помощью АЦП значение напряжения на средне
й ножке потенциометра (как в приведенной в данной статье схеме), и выводит содержимое регистра ADCH в PORTB. А к порту B я подключаю плату с восемью светодиодами. Т.е. по идее, должно работать так: я кручу ручку потенциометра туда-сюда, а светодиоды показывают содержимое ADCH. Однако, так происходит лишь до некоторого значения напряжения (где-то 0.8 В), по достижении которого АЦП как бы замораживается и в порт B выводится комбинация, соответствующая этому значению напряжения — 0.8 В. При этом если я кручу ручку потенциометра назад, на порту B все равно остается эта комбинация. После отключения питания при следующем запуске снова работает.
Не подскажите, что бы это могло быть? Может, какая-то защита срабатывает от чего-то? Код несколько раз перепроверил, даташит перечитал, ничего такого нет.
Подскажите, пожалуйста, заранее спасибо.
При старте АЦП запускаю на одно преобразование, затем каждый раз в прерывании АЦП вывожу ADCH в PORTB и снова запускаю АЦП.
При этом весь код:
http://easyelectronics.ru/repository.php?act=view&id=19
а у меня не работает=(..прошил 16 мегу,подключил к макс232 и к КОМ-порту…включаю терминалку…отправляю 0,1 …и ничего..что делать?
Такая проблема с ацп.
Написал код, по команде с uart запускающий АЦП на одно преобразование и затем выдающий на uart результат. После первой отправки результата он не реагирует на команды АЦП, потому что считает, что принятый ‘1’ не равен ‘1’ в блоке switch.. case (если менять на if, результат тот же). К тому же через некоторое время после такой отправки контроллер начинает спамить в uart случайными символами. Я понимаю, что при отправке ломаю конфигурацию, но как и чем, не пойму. Код написан на Си, с использованием прерываний.
Сорри, ложная тревога.
Здравствуйте. Решил переписать данный код с ASM-a на Си. Использую компилятор toolchain с AVR Studio 4. Все скомпелировалось с предупреждениями: ../easy_acp_uart.c:8:0: warning: «F_CPU» redefined :0:0: note: this is the location of the previous definition ../easy_acp_uart.c: In function ‘__vector_16’: ../easy_acp_uart.c:44:7: warning: assignment makes pointer from integer without a cast ../easy_acp_uart.c: In function ‘USART_RXC’: ../easy_acp_uart.c:20:1: warning: ‘USART_RXC’ appears to be a misspelled signal handler ../easy_acp_uart.c: In function ‘USART_TXC’: ../easy_acp_uart.c:30:1: warning: ‘USART_TXC’ appears to be a misspelled signal handler Но они непринципиальны, собрал плату Pinboard 1.1, открыл терминал, но при посылки 0,1 или 2 МК не реагирует. Вот решил спросить у вас может подскажите где накосячил, или пните где можно узнать. Пишу сюда т.к. это первоисточник. С уважением Дмитрий.
Ссылка на код http://easyelectronics.ru/repository.php?act=view&id=91
Написал решение http://forum.easyelectronics.ru/viewtopic.php?f=23&t=9992&p=192224#p192224.
Спасибо за статью.
Ошибся http://forum.easyelectronics.ru/viewtopic.php?f=23&t=9992&p=192224#p192224.
Доброе утро Di Halt. Более 2 х месяцев читаю твой сайт и знаний набрался больше чем за годы в универе. Созрел недавно на создание своего устройства (контроль и коррекция лямбда зонда автомобиля). Время впрыска считывает идеально,а вот с АЦП возникли проблемы следующего характера. Выставляю REFS 1..0 =01 т.е должно братся напряжение питания.У меня 5 вольт. считываю только старший байт смещение влево ADLAR=1. Но при достижении 2,5 вольт показания уже 11111111 то есть уже заполнены хотя это должно было произойти только при 5 вольтах. При увеличения напряжения происходит сброс опять 00000000 и опять до 5 вольт нарастание до 11111111 менял чипы , писал в разных программах результат тот же. Подскажите в чем может быть дело голову уже сломал.
Ну так у тебя выравнивание в другую сторону. Элементарно же :) Т.е. ты читаешь 8 младших бит, а у тебя еще остается 2 старших.
Ищи ошибку в выставлении ADLAR возможно ты его не поставил. Ради эксперимента считай оба байта ADC и увидишь сам.
Спасибо за оператиный ответ скорее всего партия бракованная т.к без AVCC «Прекрасно » работает. Завтра куплю новый чип буду его мучать. Так как в симуляторе все прекрасно.
Дико извиняюсь может быть за глупый вопрос но череп уже лопается. DI HALT Выручайте.
Забил на ADLAR предположил что микроконтроллер кривой взял новый мега 8535
работал напрямую с ячейками памяти . По следующему алгоритму
ADLAR=0 Смещения влево нет
0-> r10
0->r11 (Очищаем регистры)
P$04->r10 (Считываем младший байт АДС по его адресу)
p$05->r11 (Счит старший)
r10>>
r10>> (два раза вправо смещаем младший)
<<r11
<<r11
<<r11
<<r11
<<r11
<> (для верности уменьшаем наполовину)
r11->p$0C (Выдаем в UDR)
Но прикол в том что при таком алгоритме и даже максимальном напряжении на АЦП должно выйти не более 128 на деле же терминал показывает все 1 т.е 11111111 вместо 01111111 выручайте ребята амтопром ждет.
Упс опечатка
<>
r11->p$0C
Вот так правильно.
HTML гад кавычки убрал
«»
«» R11 ! R10
r11 >.> (Смещаем вправо) чтобы уменьшить в 2 раза
r11->p$0C»» в UDR
Тактовая частота контроллера 8 МГц. Коэффициент деления предделителя модуля АЦП равен 8. Итого получается тактовая частота модуля АЦП 1 МГц. Не укладывается в диапазон 50-200 кГц.
А можно подробнее на С про маски в прерывании где происходит перебор каналов и запись готовых значений ? в Асм ничего не понимаю.
DI хочу у тебя спросить — как значения с ацп (двоичное число в нашем буфере)
преобразовать в ASCII код чтобы отправить и отобразить на дисплее в виде десятичного числа )))
Не подскажешь какой нибудь алгоритмик …. я в инете поискал но там какие то длинные
варианты приведены, может что-нибудь попроще знаешь ???….
заранее СПАСИБО )
Только bdc конверсия. Только так. Она длинная, т.к. там деление на десять.
1. Во втором листинге ты принимаешь «1» , «2» и «3» , а эхом отправляешь 1, 2 и 3. Косячог? :)
2. Результат вычисления bauddivider не целый. Это значит что скорость будет не совсем 1200? Я правильно понимаю, что для низких скоростей это некритично? А начиная с какой скорости это становится критичным?
3. Насколько для обмена через COM-порт важна стабильность опорного генератора? Скажем, для средних скоростей (9600-38400) можно ли обойтись встроенной RC или обязателен кварц (считаем что устройство работает при температуре +16…+30 град)?
1. каким эхом? Там же данные с канала уходят.
2. До 55к нормально все. Да сам можешь посчитать расхождение.
3. До 38400 и даже выше обычно хватает встроенного. Но тут есть такой прикол, что иногда он бывает кривой. Т.е. попадались мне партии МК такие, что все окей, отлично работает, но частота встроенного генера не 8мгц, а в районе 8.3мгц.
EXIT_RX: OUT UDR,R16 ; Даем эхо и инициируем передачу.
Это разве не эхо?
Ну так у нас R16 же не меняется. В нее что пришло (код канала) то же и возвращается.
Чуть выше:
LDI R16,0; (или 1 или 2 или 3) — быстро, решительно меняем R16 :)
Думаю, в данной программе можно в качестве номеров каналов использовать ASCII, т.е. как раз «1» и т.д. В конце концов, какая разница: будет это 1-й канал или $21-й.
Для этого надо поставить кавычки везде где идёт выбор номера канала.
Кстати, в АВР есть что-то аналогичное команде HALT (только не DI HALT :)), т.е. «подождать до следующего прерывания»? Чтобы не крутить пустой цикл почём зря… Это надо курить Sleep Modes?
Да где ты там это увидел?
Второй листинг, начиная с метки Ch_0:
А, ну да. Там возвращает номер канала как есть. Что тебя смущает то?
Ничо не смущает кроме слова «эхо». Ведь эхо должно возвращать ровно то, что отправлено :)
М-да… Щас взял новую Tiny2313, завернул генератор наружу чарез CKOUT — 8.3 МГц кажет. Калибровке поддаётся, конечно, но в устройство проще кварц поставить :) Документация грит, что они внутренний ген настраивают для 3-вольтового питания (надо будет проверить).