AVR. Учебный Курс. Выдача данных с АЦП на UART. Мультиплексирование каналов АЦП

Несколько постов назад я заикнулся о том, что выдам на гора программу-пример для работы с АЦП. Пора за базар отвечать :) Делать мы будем простенький цифровой вольтметр с замашками осциллографа. Точнее осциллографом это можно назвать с большой натяжкой, скорей самописец. Так, побаловаться.

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

Теоретическую часть я уже разобрал, осталось поставить эксперимент в реальном железе.

Собираем схему на демоплате 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, то со второго.

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

Сложно? Нет! Буквально пара команд, а сколько удовольствия!

Скачать проект для AVR Studio

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

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

57 thoughts on “AVR. Учебный Курс. Выдача данных с АЦП на UART. Мультиплексирование каналов АЦП”

  1. Не смотрел код, но по описанию я не вижу здесь проверки завершения передачи данных по УАРТу. Представления не имею, надо ли это в данном случае, задние полушария говорят, что АЦП медленнее УАРТа при средних скоростях, но все же.

    И вообще. Если юзается восьмибитный УАРТ, то ИМХО правильнее писать не так. В обработчике прерывания АЦП скидываем значение в переменную — и ВСЕ. Потом в основном цикле та переменная сливается в УАРТ, но только если завершена предыдущая передача. Т.о. не будет никаких перегрузок пропускной способности УАРТа только из-за скорости АЦП. То же самое можно делать и в обработчике, просто я не любитель растягивать обработчики хоть на один байт больше необходимого.

  2. недавно наткнулся на uzebox — где чел собрал игрой комп на основе авра.
    вот это я понимаю ) полное изучение возможностей + тетрис под рукой.
    всегда мечтал свой такой изобрести, возможно скоро начну.
    имхо на таком приятней изучать, что и как

    http://belogic.com/uzebox/index.htm

  3. А почему бы и нет? Игрались в своё время на синклере? А мега по производительности рвёт z80 как Тузик грелку. Ведь RISC всё-таки. (Хотя, глядя на систему команд z80, систему команд меги трудно назвать сокращённой)

    1. Сделать комп — не проблема. Проблема — программы. Собрав Синклера или хотя бы Микрошу, ты сразу получал доступ к сотням уже готовых программ для них, в том числе и компиляторы Бэйсика, Ассемблера, Форта, редакторы текстовые и графические, игры, и много еще чего. Для Синклера была даже удобная оболочка для загрузки программ, похожая на Нортон Командера. Сделав же свой, не похожий на другие, комп, ты должен будешь писать все это сам, начиная с драйверов клавиатуры, дисплея, джойстиков, графики, и кончая самими играми, редакторами, компиляторами. Даже собрав в 84г свой компьютер, совместимый программно и аппаратно (по основным сигналам шины) с «МИКРО 80», я уже мог воспользоваться его программой «МОНИТОР», и BASIC, и Макро Ассемблером, хотя и в 16-ричном коде пописал немало, в основном программки для программаторов. Тогда, в начале пути, это было интересно и вызывало большой энтузиазм. Сейчас, когда без мыша и Виндов вроде и делать нечего, самодельный комп покажется скучной и никчемной железякой. Ну, соединишь между собой пару микросхем и разьемы, подключишь к телевизору, потыркаешься в «TETRIS». Через неделю все это надоест, и ты закинешь его подальше… И пойдешь опять гонять Фар кри или Контрол страйк.

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

        какие-нибудь самодельные осциллографы? хороший hp цифровой — это сказка.

        сенсоры, передатчики, забавные игрушки? так же по пунктам.

        такой миникомп нужен в основном не для игр или ностальжи, а для того, чтобы чел, его собравший, поверил в свои силы. 90% из моих знакомых, кто знает про такое — только на словах могут объяснить, как они легко его соберут.

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

        1. Так это и будет не компьютер, а микроконтроллер. И под конкретную задачу его можно хорошо оптимизировать. И почему бы тогда не сделать его в виде робота? Возможностей и интереса будет намного больше, чем просто у коробки на столе, привязанной кабелем к телевизору. Одни мозги, без какой-либо периферии, когда не на что реагировать и нечем управлять — это скучно…

          1. тогда с роботом тоже надо подходить основательно.
            я помню, как в детстве читал книжки про «это» и ходил в соответствующие кружки. в районе 60-70ых таких роботов делали, что выглядели как роботы )))

            и всякой механики, и научных идей. и всё из подручных элементов. тем бы людям наши вычислительные мощности — они б на луну ракету запустили )

            1. Так и запускали. И не только ракеты, но и пара луноходов месяцами бегали, и пробурили Луну на несколько метров вглубь, и колонку грунта метра три длиной на Землю привезли еще в начале 70х. У американцев в то время была только высадка на Луну, и то до сих пор многие американцы в это не верят, хотя вроде аж несколько человек побывало.
              Потом были полеты к Марсу, Венере, комете Галлея… Кстати, у американцев с Венерой ничего серьезного так и не получилось, и они предпочли более простой и удобный Марс. А Советские аппараты на Венеру опускались, и даже некоторое время работали на поверхности, при 500 градусной температуре.
              Роботу не обязательно выглядеть как человек или роботы из фильмов. Конструкция должна быть рациональной и функциональной. А вот уж над функциональностью стоит повозиться. Робот для одной функции — это просто автомат. Чем их больше — тем интересней, тем «разумней» он будет выглядеть и действовать, тем больше опыта приобретешь. Ну и двухсторонняя связь желательна для интерактивного общения. Он тебе постоянно сообщает о своем состоянии и окружении, ходе выполнения задач, ты даешь ему новые задания…

              1. я пролистал последние выпуски журнала Хацкер, про который пишет ДиХальт
                там роботами называют даже моторчик со свето- и фотодиодом.

                роботы, которые летали на Венеру — эт хорошо. но я сомневаюсь, что на этом блоге есть больше 2ух человек, кто хотя бы раз удачно запускал своего робота )

  4. Было бы «культурней» в обработчике UART сохранять регистор SREG, ибо флаги портятся (командой CPI …). Это хорошо, что в основном цикле пусто, а то были бы глюки.
    И может стоить заметить, что читать ОДНУ половинку ADCx можно только старшую (ADCH). А если бы понадобилась только младшая (допустим если сдвиг вправо), то читать надо обязателно обе и притом сначала ADCL, а потом ADCH.

    1. Ну я же говорю все через задницу тут :) По поводу половинок регистра ацп, да, но на то есть теоретическая часть :) Ну и я планирую еще пару практических примеров по АЦП сделать. С алгоритмами усреднения и накопления. Типо программное повышение точности.

  5. И, кстати первый коментарий совершенно справедлив. И дело не в скоростях UART и АЦП. У тебя передача по УАРТ в двух местах (эхо при приёме с компа и при завершении АЦП), и в обоих не проверяется его готовность. Могут быть накладки, хотя и не смертельно…

    1. Ага и это тоже, согласен. УАРТ захлебывается и теряет байты. В данном случае это некритично т.к. они один фиг идут потоком из более быстрого АЦП, но на ответственной передаче такой поток недопустим.

  6. Стоолкнулся вот с такой проблемкой:
    Мое устройство изначально безошибочно работало (не важно , что выполняло)результат пересылало в ПК, но потом я задумал снимать аналоговую велечину. Для проверки АЦП я через реастат подавал напряжения в пределах от 0.2-3.5В на вход ADC0. И Вот что случилось: все замерло. Промучался полдня и не фига не выходит. Есть подозрения, что мог запортачить микруху, но как? разве можно через вход ацп?
    При этом программатор ее не видит и УАРТ перестал код гнать. Сразу скажу, что осцилографа нет.
    Помогите словом. Что случилось?

  7. Можно побробней о USB датакабеле на чипе Profilic. Это куда его тут воткнуть можно? И разве в USB дата-кабелях есть чипы?

    P.S. Описочка:
    «О том что значат быти конфигурации UART»
    д.б. «биты»

    1. У меня есть такой кабель. Покупал для своего телефона Motorola E365 (ныне покойного). Купил в стандартном ларьке, торгующими телефонами за 100 рублей. Сам удивился цене. При установки в систему, насколько я помню, создаёт виртуальный COM порт.

  8. DI HALT, подскажи, пожалуйста, на чём можно сделать. ТЗ такое: сделать многоканальный вольтметр с подключением по USB. Скорость опроса вольтметра не очень высока: на большинстве каналов хватит 10-20 в секунду; но надо сделать один-два побыстрее для некоего подобия осциллографа в звуковом диапазоне. Число каналов от 4х. А на стороне компа желательно чтобы это всё программами виделось как COM-порт[ы], ибо написано много в Инете про него.

    1. На форуме Elementus уже сделал почти такое. Можешь у него спросить, правда он на пиках.

      А так все просто — АЦП опрашивает по очереди каналы и шлет данные в сом порт.

  9. Нужна помощь. ниче понять не могу. мега8 работает на 8Мгц от внутреннего генератора. посылаю 2 байта данных с компа по ЮАРТ на скорости 9600 — работает нормально, контроллер шлет их обратно, меняю скорость — бред получаю.

    1. Может у тебя срыв стека или кривой выход из прерывания? Или конфликт прерываний. А на скорости 9600 все очень удачно разруливалось само собой?

      Скорость (значение бодрейта) верно высчитал?

  10. с мегой 16 та же фигня. на 9600 шлет с Ацп по юарту на terminal четко, а на других скоростях такое гонит. надо бы через настоящий com посмотреть, а не через FT232.

  11. Все понял. На медленных скоростях, до 38400, и без кварца все нормально, а вот на высоких — гонево. Поставил кварц заточенный под ЮАРТ — 7.3728 Мгц- и все прет как надо на 115200.

  12. что то никак :( кварц 7.3728 Мгц скорость 9600, в терминал летят одни буквы «Я» на любую посылку, причем гадит пока дисконект не сделаешь. как сделать на основе этого проектика заглушку для уарта т.е чтоб эхо контроллер реализовывал.

    1. й ножке потенциометра (как в приведенной в данной статье схеме), и выводит содержимое регистра ADCH в PORTB. А к порту B я подключаю плату с восемью светодиодами. Т.е. по идее, должно работать так: я кручу ручку потенциометра туда-сюда, а светодиоды показывают содержимое ADCH. Однако, так происходит лишь до некоторого значения напряжения (где-то 0.8 В), по достижении которого АЦП как бы замораживается и в порт B выводится комбинация, соответствующая этому значению напряжения — 0.8 В. При этом если я кручу ручку потенциометра назад, на порту B все равно остается эта комбинация. После отключения питания при следующем запуске снова работает.
      Не подскажите, что бы это могло быть? Может, какая-то защита срабатывает от чего-то? Код несколько раз перепроверил, даташит перечитал, ничего такого нет.
      Подскажите, пожалуйста, заранее спасибо.
      При старте АЦП запускаю на одно преобразование, затем каждый раз в прерывании АЦП вывожу ADCH в PORTB и снова запускаю АЦП.

  13. а у меня не работает=(..прошил 16 мегу,подключил к макс232 и к КОМ-порту…включаю терминалку…отправляю 0,1 …и ничего..что делать?

  14. Такая проблема с ацп.

    Написал код, по команде с uart запускающий АЦП на одно преобразование и затем выдающий на uart результат. После первой отправки результата он не реагирует на команды АЦП, потому что считает, что принятый ‘1’ не равен ‘1’ в блоке switch.. case (если менять на if, результат тот же). К тому же через некоторое время после такой отправки контроллер начинает спамить в uart случайными символами. Я понимаю, что при отправке ломаю конфигурацию, но как и чем, не пойму. Код написан на Си, с использованием прерываний.

  15. Здравствуйте. Решил переписать данный код с 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

  16. Доброе утро Di Halt. Более 2 х месяцев читаю твой сайт и знаний набрался больше чем за годы в универе. Созрел недавно на создание своего устройства (контроль и коррекция лямбда зонда автомобиля). Время впрыска считывает идеально,а вот с АЦП возникли проблемы следующего характера. Выставляю REFS 1..0 =01 т.е должно братся напряжение питания.У меня 5 вольт. считываю только старший байт смещение влево ADLAR=1. Но при достижении 2,5 вольт показания уже 11111111 то есть уже заполнены хотя это должно было произойти только при 5 вольтах. При увеличения напряжения происходит сброс опять 00000000 и опять до 5 вольт нарастание до 11111111 менял чипы , писал в разных программах результат тот же. Подскажите в чем может быть дело голову уже сломал.

    1. Ну так у тебя выравнивание в другую сторону. Элементарно же :) Т.е. ты читаешь 8 младших бит, а у тебя еще остается 2 старших.

      Ищи ошибку в выставлении ADLAR возможно ты его не поставил. Ради эксперимента считай оба байта ADC и увидишь сам.

  17. Спасибо за оператиный ответ скорее всего партия бракованная т.к без AVCC «Прекрасно » работает. Завтра куплю новый чип буду его мучать. Так как в симуляторе все прекрасно.

  18. Дико извиняюсь может быть за глупый вопрос но череп уже лопается. 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 выручайте ребята амтопром ждет.

  19. Тактовая частота контроллера 8 МГц. Коэффициент деления предделителя модуля АЦП равен 8. Итого получается тактовая частота модуля АЦП 1 МГц. Не укладывается в диапазон 50-200 кГц.

  20. А можно подробнее на С про маски в прерывании где происходит перебор каналов и запись готовых значений ? в Асм ничего не понимаю.

  21. DI хочу у тебя спросить — как значения с ацп (двоичное число в нашем буфере)
    преобразовать в ASCII код чтобы отправить и отобразить на дисплее в виде десятичного числа )))
    Не подскажешь какой нибудь алгоритмик …. я в инете поискал но там какие то длинные
    варианты приведены, может что-нибудь попроще знаешь ???….
    заранее СПАСИБО )

  22. 1. Во втором листинге ты принимаешь «1» , «2» и «3» , а эхом отправляешь 1, 2 и 3. Косячог? :)
    2. Результат вычисления bauddivider не целый. Это значит что скорость будет не совсем 1200? Я правильно понимаю, что для низких скоростей это некритично? А начиная с какой скорости это становится критичным?
    3. Насколько для обмена через COM-порт важна стабильность опорного генератора? Скажем, для средних скоростей (9600-38400) можно ли обойтись встроенной RC или обязателен кварц (считаем что устройство работает при температуре +16…+30 град)?

    1. 1. каким эхом? Там же данные с канала уходят.

      2. До 55к нормально все. Да сам можешь посчитать расхождение.

      3. До 38400 и даже выше обычно хватает встроенного. Но тут есть такой прикол, что иногда он бывает кривой. Т.е. попадались мне партии МК такие, что все окей, отлично работает, но частота встроенного генера не 8мгц, а в районе 8.3мгц.

          1. Чуть выше:
            LDI R16,0; (или 1 или 2 или 3) — быстро, решительно меняем R16 :)
            Думаю, в данной программе можно в качестве номеров каналов использовать ASCII, т.е. как раз «1» и т.д. В конце концов, какая разница: будет это 1-й канал или $21-й.
            Для этого надо поставить кавычки везде где идёт выбор номера канала.
            Кстати, в АВР есть что-то аналогичное команде HALT (только не DI HALT :)), т.е. «подождать до следующего прерывания»? Чтобы не крутить пустой цикл почём зря… Это надо курить Sleep Modes?

      1. М-да… Щас взял новую Tiny2313, завернул генератор наружу чарез CKOUT — 8.3 МГц кажет. Калибровке поддаётся, конечно, но в устройство проще кварц поставить :) Документация грит, что они внутренний ген настраивают для 3-вольтового питания (надо будет проверить).

Добавить комментарий

Ваш e-mail не будет опубликован.

Перед отправкой формы:
Human test by Not Captcha