Форум РадиоКот https://radiokot.ru/forum/ |
|
Делаем устройство "Бегущий огонек" на микроконтроллере https://radiokot.ru/forum/viewtopic.php?f=25&t=91929 |
Страница 1 из 1 |
Автор: | forfrends [ Пт июл 12, 2013 16:27:54 ] |
Заголовок сообщения: | Делаем устройство "Бегущий огонек" на микроконтроллере |
Всем добрый день! Начал обучение программирования микроконтроллеров AVR с раздела: РадиоКот > Обучалка > Микроконтроллеры и ПЛИС > Микроконтроллеры AVR - пишем, компилируем, прошиваем... Для тестов взял Attiny2313 Вроде получалось, вроде что-то даже работало ![]() По теме "Динамическая индикация" нужно было собрать простую схемку с 7-и сегментными индикаторами. Схемку я паять не стал, так как нет у меня лишних индикаторов... а взял уже готовую, собранную по схеме "Цифровой термометр" (который у меня исправно работал). Только у меня вместо 3-х цифрового индикатора подключен 4-х цифровой. Вывод 1-цифры подключен к 7-й ноге Тиньки (как и должно быть). Все "Общие" выводы припаяны правильно: 1-я цифра к 7-й ноге тиньки, 2-я к 6-й, 3-я к 3-й, 4-я к 2-й. Как оказалось, выводы сегментов не совпадают. Перепаивать я не стал (зачем портить готовое и работающее) а просто внес изменения в символьную таблицу в коде. Было так: .db 0b00111111,0b00000110 ;0,1 .db 0b01011011,0b01001111 ;2,3 .db 0b01100110,0b01101101 ;4,5 .db 0b01111101,0b00000111 ;6,7 .db 0b01111111,0b01101111 ;8,9 а стало так: .db 0b01111110,0b00110000 ;0,1 .db 0b01101101,0b01111001 ;2,3 .db 0b00110011,0b01011011 ;4,5 db 0b01011111,0b01110000 ;6,7 .db 0b01111111,0b01110111 ;8,9 После проверки в Протеусе оказалось что отображение получатся в негативе, то есть если нужно вывести "1" то сегменты, отвечающие за единицу не светятся, зато светятся все остальные, которые не должны светиться. То же наблюдается для всех остальных цифр. Хотя, как я понял, "1" (единица из таблицы) отвечает за зажигание сегмента, а "0" (ноль из той же таблицы) говорит что сегмент погашен... Еще один момент: по заданию "Динамической индикации" нужно вывести на отображение число 1234, но вместо этого отображается 2341 (в виде инверсии) Получатся в исходном коде 2 ошибки (или я что-то не понял или не так составил исходник): 1) инверсия цифр 2) Цифры смещены в лево на 1 символ. Вместо "1234" отображает "2341" вот исходник: Спойлер.include "g:\AVR-projects\tutorial\2313def.inc".def Temp1=R16 .def Temp2=R17 .def Temp3=R18 .def Temp4=R19 .def Temp=R20 .dseg Digit: .byte 4 .cseg .org 0 rjmp RESET ; Reset Handler rjmp EXT_INT0 ; IRQ0 Handler rjmp EXT_INT1 ; IRQ1 Handler rjmp TIM_CAPT1 ; Timer1 Capture Handler rjmp TIM_COMP1 ; Timer1 Compare Handler rjmp TIM_OVF1 ; Timer1 Overflow Handler rjmp TIM_OVF0 ; Timer0 Overflow Handler rjmp UART_RXC ; UART RX Complete Handler rjmp UART_DRE ; UDR Empty Handler rjmp UART_TXC ; UART TX Complete Handler rjmp ANA_COMP ; Analog Comparator Handler EXT_INT0 : ret EXT_INT1 : ret TIM_CAPT1 : ret TIM_OVF0 : ret TIM_OVF1 : ret UART_RXC : ret UART_DRE : ret UART_TXC : ret ANA_COMP : ret TIM_COMP1 : ret reset: ldi Temp1,RamEnd ;инициализация стека out SPL,Temp1 cli ldi Temp,0b11111111 ;настройка портов out ddrb,Temp ldi Temp,0b00001111 out ddrd,Temp ldi Temp,4 sts Digit ,Temp ;загрузка начальных сначений ldi Temp,3 sts Digit+1,Temp ldi Temp,2 sts Digit+2,Temp ldi Temp,1 sts Digit+3,Temp ;********************************************************* ;MAIN ;********************************************************* IndicCycle: rcall Display ;цикл индикации rjmp IndicCycle ;********************************************************* Display: ;последовательный вывод на индикацию содержимого ;переменной Digit lds Temp1,Digit ;загружаем 0-ю ячейку ldi Temp,0b00001110 ;активируем 0-й разряд ;индикации out PortD,Temp rcall Decoder ;вызываем 7-сегм. декодер out PortB,Temp1 ;выводим значение в порт rcall Delay1 ;ждем lds Temp1,Digit+1 ;и .т.д ldi Temp,0b00001101 out PortD,Temp rcall Decoder out PortB,Temp1 rcall Delay1 lds Temp1,Digit+2 ldi Temp,0b00001011 out PortD,Temp rcall Decoder out PortB,Temp1 rcall Delay1 lds Temp1,Digit+3 ldi Temp,0b00000111 out PortD,Temp rcall Decoder out PortB,Temp1 rcall Delay1 ret ;********************************************************* Decoder: ;преобразование двоичного числа ;в код 7-сегментного индикатора ldi ZL,Low(DcMatrix*2) ;инициализация массива ldi ZH,High(DcMatrix*2) ldi Temp2,0 ;прибавление переменной add ZL,Temp1 ;к 0-му адресу массива adc ZH,Temp2 lpm ;загрузка значения mov Temp1,r0 ret DcMatrix: ;массив - таблица истинности декодера ; hgfedcba hgfedcba .db 0b01111110,0b00110000 ;0,1 .db 0b01101101,0b01111001 ;2,3 .db 0b00110011,0b01011011 ;4,5 .db 0b01011111,0b01110000 ;6,7 .db 0b01111111,0b01110111 ;8,9 ;********************************************************* Delay1: ;цикл задержки push Temp1 push Temp2 ldi Temp1,0 ldi Temp2,50 d11: dec Temp1 brne d11 dec Temp2 brne d11 pop Temp2 pop Temp1 ret Можете помочь, подсказать, и, главное, объяснить где в коде ошибка? Хочется во всем этом разобраться и идти дальше... |
Автор: | forfrends [ Пт июл 12, 2013 17:02:16 ] | ||
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! | ||
вот, на всякий случай, решил прикрепить проэкт Протеуса и инклуд
|
Автор: | forfrends [ Сб июл 13, 2013 20:31:14 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
помогите разобраться... |
Автор: | C@at [ Сб июл 13, 2013 20:48:16 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Правильно заданный вопрос уже наполовину ответ..., из этого следует forfrends писал(а): то есть если нужно вывести "1" то сегменты, отвечающие за единицу не светятся, зато светятся все остальные, которые не должны светиться. а стало так: .db 0b01111110,0b00110000 ;0,1// негатив сделать так : .db 0b10000001,0b11001111 ;0,1// норма |
Автор: | forfrends [ Сб июл 13, 2013 20:58:31 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Я понимаю что так можно решить проблему, но такой вариант решения не соответствует всему тому что написано в "Обучалке". И, к тому же, я лишь скопировал код, слегка подправив его под свою схему выводов. А это значит что ошибка в самом примере приведенном в статье. Вот и попобуй тут разобраться, где ошибка... Сейчас по-новой все перечитываю, пытаюсь вникнуть... К тому же такой вариан не решает проблему со сдвигом цифр |
Автор: | dr.doc [ Сб июл 13, 2013 21:32:13 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Это не ошибка. Просто перед выводом сегментов на индикацию есть строки ldi Temp,0b00000111 out PortD,Temp Значения в бинарном числе в каждом блоке подключают общие выводы индикаторов. Измените в любом блоке 1 на 0 и получите чудо. |
Автор: | forfrends [ Сб июл 13, 2013 22:11:59 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Исходя из этого кода: ldi Temp,0b11111111 ;настройка портов out ddrb,Temp ldi Temp,0b00001111 out ddrd,Temp все выводы порта b и четыре последних вывода порта d настроены на "вывод" если не ошибаюсь, ldi Temp,0b00000111 out PortD,Temp отвечает за то, какой общий катод (анод) индикатора в данный момент задействован для вывода информации: 0b00000111 - 1-я цифра индикатора 0b00001011 - 2-я цифра 0b00001101 - 3-я цифра 0b00001110 - 4-я цифра то есть под "0" подразумевается что порт настроен на "вход"... Вроде так? Тогда почему все цыфры смещены влево? Я так понимаю, если взять вот такие два кода: ldi Temp,0b11111111 out PortD,Temp ldi Temp,0b00001101 oout PortB,Temp то на индикаторе должна загореться 3-я цифра, отображая "8" и "точку", то есть все сегменты. а в таком варианте должна отображаться "1": ldi Temp,0b00000110 out PortD,Temp ldi Temp,0b00001101 oout PortB,Temp Мне кажется что таблица символов и настройка портов сделаны верно... получается где-то в другом месте ошибка... Если не так что-то понимаю - ткните мордочкой и объясните пожалуйста. |
Автор: | dr.doc [ Вс июл 14, 2013 09:14:47 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Число однотипных блоков равно числу семисегментных индикаторов. Выше Вы все правильно расписали. Для замены порядка отображения чисел нужно изменить само число, кодирующее катод. В качестве примера: ldi Temp,0b00001111 ; Не горит ни чего. ldi Temp,0b00000111 ; Загорелась одна цифра, допустим 3-я. Тогда биту №3 соответствует цифра 3 (по порядку отображения) ldi Temp,0b00001011 ; Загорелась вторая, допустим 1-я. Тогда биту №2 соответствует цифра 1 ldi Temp,0b00001101 ; Ну и так далее ldi Temp,0b00001110 ; После нахождения просто выставляем эти числа в блоках в порядке отображения. А если проще - посмотрите в каком порядке к порту PortD подключены катоды. К примеру PortD,0 - катод второго числа, ну и аналогично. Вот как-то так... |
Автор: | forfrends [ Вс июл 14, 2013 10:21:24 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Да, вот в том то и дело, что к порту PortD0 подключен катод 4-й цифры, к порту PortD1 - 3й цифры, и т.д.... (как по схеме) Это то меня и вводит в ступор. Уже несколько раз проверил и схему и плату. По коду программы, вроде тоже все верно... Ладно, оставлю это все на потом, то есть я по-новой начал все перечитывать, что-то стато проясняться, но и появились другие вопросы: В теме Бегущий огонек v1.0 описывается создание задержки. Цитата: ldi Temp,0 Loop: dec Temp brne Loop Сначала мы инициализировали Temp числом 0. Далее из Temp вычитается 1. Его значение становится -1 (иначе говоря, 255). Далее мы проверяем, не получился ли у нас ноль. Поскольку число 255 не равно нулю, нас снова перекидывают на операцию декремента. Значение Temp уменьшается еще на 1. Теперь оно - 254. 1) Разве РОН (регистр общего назначения) не может содержать отрицательное значение? 2) Почему 0-1=255 (ноль минус один равно 255)? Почему не -1, -2 и т.д.? Это таккая защита? (вспоминаются случаи когда написанные программы на компе "вылетали" из-за переполнения переменной) 3) 256 значений (от 0 до 255) - это размер одного байта? Если нет, то почему именно такое числовое ограничение? И еще вопрос: наиболее подходящий/удобный язык для написания программ это Ассемблер? Или есть другие, более популярные (удобные/лучшие) языки? |
Автор: | a_skr [ Вс июл 14, 2013 10:54:20 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Цитата: 1) Разве РОН (регистр общего назначения) не может содержать отрицательное значение? может. число 0b11111111 - это и 255, и одновременно -1.Цитата: Почему 0-1=255 (ноль минус один равно 255)? Почему не -1, это одно и тоже ![]() Цитата: 256 значений (от 0 до 255) - это размер одного байта? именно так.если работаете со знаком, то в одном байте можете хранить значения от -128 до +127, если без знака, то от 0 до +255. про целые доп. код |
Автор: | forfrends [ Вс июл 14, 2013 11:30:42 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
a_skr, спасибо за разъяснение! Цитата: число 0b11111111 - это и 255, и одновременно -1. как я понял число 0b11111111 - это отрицательное число а число 0b01111111 - это положительное ? и еще хочу уточнить, в школе нас учили что -2-1=-3 (то есть, числа складываем и прибавляем минус) а исходя из этого: Цитата: Поскольку число 255 не равно нулю... Temp уменьшается еще на 1. Теперь оно - 254. получается что в программировании формула выглядит так: -2-1=-1 ? Точнее от имеющегося числа (0b11111111) отнимаем единицу, как от положительного, а разряд 0b11111111 лишь указывает нам на то, что число, в конечном итоге, отрицательно? |
Автор: | a_skr [ Вс июл 14, 2013 11:39:00 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
программирование ни в коем разе не противоречит математике -2: 11111110 -1: 11111111 -2 + -1: 11111110 + 11111111 = 11111101 = -3 |
Автор: | a_skr [ Вс июл 14, 2013 11:43:54 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
P.S. конечно, там еще одна единица слева будет, но в 1 байт она не влезла, а ушла в регистр флагов. -2 + -1: 11111110 + 11111111 = (1)11111101 = -3 |
Автор: | forfrends [ Вс июл 14, 2013 14:10:23 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Ага, понятно. Еще вопрос, как работать с отрицательными значениями, точнее что это за регистр флагов и как с ним работать? Решил поекспериментировать с кодом, чтобы в нем разобраться. Написал это: Спойлер.include "g:\AVR-projects\tutorial\2313def.inc".def Temp=R16 .cseg .org 0 ldi Temp, 0b11111111 ;присвоение константы out DDRB,Temp ;настройка порта ldi Temp,0b00001111 ;присвоение константы out DDRD,Temp ;настройка порта ldi Temp,0b00110000 out Portb,Temp ldi Temp,0b00001110 out Portd,Temp IndicCycle: rjmp IndicCycle Теоретически, должна была светиться 4-я цифра (ldi Temp,0b00001110) и отображать единицу (ldi Temp,0b00110000) Но Протеус выдал то, что и раньше - инверсия, но при этом светились 1,2 и 3-я цифры, а ту, которую выбирали (4-я) нет! ![]() у меня появились некоторые мысли на этот счет, если что - поправьте. Изначально в коде настраиваются порты: Код: ldi Temp, 0b11111111 out DDRB,Temp и Код: ldi Temp, 0b00001111 out DDRD,Temp Я так понимаю что обе части кода говорят о том, какие порты будут задействованы в программе? А не то какие порты настроены на ввод а какие на вывод? Судя то пому что дает протес, то єто так. Какие порты будут на вход, а какие на выход отвечает эта часть программы?: Код: ldi Temp,0b00110000 out Portb,Temp ldi Temp,0b00001110 out Portd,Temp Спасибо всем за помощь - решил проблему с инверсией ![]() Как оказалось - вся проблема была в том, что у меня на схеме стоит индикатор с общим Анодом, а надо было с общим Катодом !! Я сразу не понял в чем дело, потому что в коде используется не включение/отключение порта, а изменение "+" на "-" и наоборот. В схеме и прошивке Цифрового термометра это учтено, и если поставить не тот индикатор (общий вывод другой полярности) то на индикаторе ничего отображаться не будет. Поменял в протеусе индикатор - Заработало! |
Автор: | forfrends [ Вс июл 14, 2013 14:49:19 ] |
Заголовок сообщения: | Re: AVR - пишем, компилируем, прошиваем... НЕ работает! |
Можете подсказать, что нужно даписать в коде, чтобы контроллер работал с индикатором с общим Анодом вместо индикатора с общим Катодом? |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |