Atmega8, подключение семисегментного индикатора

Обсуждаем контроллеры компании Atmel.
Ответить
Efiop
Родился
Сообщения: 4
Зарегистрирован: Вт окт 28, 2014 17:10:53

Atmega8, подключение семисегментного индикатора

Сообщение Efiop »

Доброго времени суток, уважаемые форумчане! Начал изучение основ программирования микропроцессоров, столкнулся с проблемой. Написал код на ассемблере, смоделировал схему в Proteus, протестировал, все работает. Собрал схему в живую, прошил МК, фьюзы использовал по умолчанию. По программе при подключении питания загораются определенные диоды семисегмента, в моем случае цифра три. После подачи питания на собранную схему, загорается весь семисегмент, и не реагирует на нажатия кнопок.
Семисегмент с общим анодом, порядок подключения не спутан. Прикладываю схемку и код. Надеюсь на вашу помощь. Заранее спасибо!
P.S. Код может быть написан и криво, но я только учусь :)
Схема в Proteus
СпойлерИзображение
Код
Спойлер

Код: Выделить всё

.include "m8def.inc" 
.def temp = r16 		;задаем символические имена регистрам
.def priznak1 = r17
.def allint = r19
.def vivod=r20


.CSEG			;сегмент кода программы
rjmp RESET 		;переход на начало программы
.org $0b00000000	;адрес начала программы
.org INT0addr		;адрес прерывания по нажатию первой кнопки
rjmp EXT_INT0 		;переход на подпрограмму обработки прерывания
.org INT1addr		;адрес прерывания по нажатию первой кнопки
rjmp EXT_INT1 		;переход на подпрограмму обработки прерывания
.ORG   INT_VECTORS_SIZE

RESET: 
ldi temp, high(RAMEND) ;инициализация стека
out SPH, temp 
ldi temp, low(RAMEND)  
out SPL, temp
ldi priznak1,0b00000000

ldi allint,0b11000000
ldi temp, 0b10110000 
ldi priznak1, 0b00000011
out PORTB, temp
ldi vivod, 0b11111111
out DDRB, vivod ;конфигурирование порта B как выходного

cbi DDRD, DDD2	;конфигурирование порта D как входного
sbi PIND,PD2
cbi DDRD, DDD3 
sbi PIND,PD3

sei 			;общее разрешение прерываний

ldi temp,  ((1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) )
out MCUCR, temp
out GIMSK, allint	;разрешение прерываний по нажатию клавиш



MAIN: 			;главный цикл

rjmp MAIN 
EXT_INT0: 			;обработка прерываний по нажатию первой кнопки

cpi priznak1, 0b00000011
breq yes2
rjmp no2

yes2:
ldi priznak1,0b00000101 ;пятерка
ldi temp, 0b10010010
rjmp Exit
no2:
cpi priznak1,0b00000101
breq yes3
rjmp no3

yes3:
ldi priznak1, 0b00000111 ;семерка
ldi temp, 0b11111000
rjmp Exit
no3:
cpi priznak1, 0b00000111
breq yes4
rjmp no4

yes4:
ldi priznak1,0b00001001 ;девятка
ldi temp, 0b10010000
rjmp Exit
no4:
cpi priznak1,0b00001001
breq yes5
rjmp no5

yes5:
ldi priznak1,0b00000001 ;еденица
ldi temp,0b11111001
rjmp Exit
no5:
cpi priznak1,0b00000001
breq yes6
rjmp no6

yes6:					 
ldi priznak1, 0b00000011 ;тройка
ldi temp,0b10110000 
rjmp Exit
no6:
cpi priznak1,0b00000011
breq yes2
rjmp no7

no7:
cpi priznak1, 0b00000100 ;шестерка
breq yes8
rjmp no8
yes8:
ldi priznak1, 0b00000110
ldi temp,0b10000010
rjmp Exit

no8:
cpi priznak1, 0b00000110 ;восьмерка
breq yes9
rjmp no9
yes9:
ldi priznak1, 0b00001000
ldi temp,0b10000000
rjmp Exit

no9:
cpi priznak1, 0b00000000 ;двойка
breq yes10
rjmp no10
yes10:
ldi priznak1, 0b00000010
ldi temp,0b10100100
rjmp Exit

no10:
cpi priznak1, 0b00000010 ;четверка
breq yes
rjmp no25
yes:
ldi priznak1, 0b00000100
ldi temp,0b10011001
rjmp Exit

no25:
cpi priznak1, 0b00010000 ;двойка
breq yes25
rjmp no26
yes25:
ldi priznak1, 0b00000010
ldi temp,0b10100100
rjmp Exit

no26:
cpi priznak1, 0b00001000 ;ноль
breq yes26
yes26:
ldi priznak1, 0b00010000
ldi temp,0b11000000
rjmp Exit



EXT_INT1:				 ;обработка прерываний по нажатию второй кнопки
cpi priznak1, 0b00000000 ;ноль
breq yes19
rjmp no
no:
cpi priznak1, 0b00010000
breq yes11
rjmp no11

yes11:
ldi priznak1, 0b00001001 ;девятка
ldi temp,0b10010000
rjmp Exit
no11:
cpi priznak1, 0b00001001
breq yes12
rjmp no12

yes12:
ldi priznak1, 0b00001000 ;восьмерка           
ldi temp,0b10000000
rjmp Exit
no12:
cpi priznak1, 0b00001000
breq yes13
rjmp no13

yes13:
ldi priznak1, 0b00000111 ;семерка
ldi temp,0b11111000
rjmp Exit
no13:
cpi priznak1, 0b00000111
breq yes14
rjmp no14

yes14:
ldi priznak1, 0b00000110 ;шестерка
ldi temp,0b10000010
rjmp Exit
no14:
cpi priznak1, 0b00000110
breq yes15
rjmp no15

yes15:
ldi priznak1, 0b00000101 ;пятерка
ldi temp, 0b10010010
rjmp Exit
no15:
cpi priznak1, 0b00000101
breq yes16
rjmp no16

yes16:
ldi priznak1, 0b00000100 ;четверка
ldi temp, 0b10011001
rjmp Exit
no16:
cpi priznak1, 0b00000100
breq yes17
rjmp no17

yes17:
ldi priznak1, 0b00000011 ;тройка
ldi temp,0b10110000
rjmp Exit
no17:
cpi priznak1, 0b00000011
breq yes18
rjmp no18

yes18:
ldi priznak1, 0b00000010 ;двойка
ldi temp, 0b10100100
rjmp Exit
no18:
cpi priznak1, 0b00000010
breq yes19
rjmp no19

yes19:
ldi priznak1, 0b00000001 ;еденица
ldi temp,0b11111001
rjmp Exit
no19:
cpi priznak1, 0b00000001
breq yes20

yes20:
ldi priznak1, 0b00010000 ;еденица
ldi temp,0b11000000
rjmp Exit


Exit:
out PORTB, temp		;вывод значения на порт B
reti				;возвращение в программу
Реклама
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Atmega8, подключение семисегментного индикатора

Сообщение COKPOWEHEU »

Коды цифр лучше вынести в ПЗУ и загружать оттуда командой LPM:

Код: Выделить всё

...
ldi r16,5 ;допустим, надо вывести число '5'
rcall OUT_NUM ;вызов процедуры. Если вызывается издалека - call
out PORTB,r16 ;вывод ее результата в порт
...
OUT_NUM: ;процедура перевода числа в семисегментрую форму
 push ZH ;мало ли где эти регистры используются, лучше сохраним
 push ZL
 ldi ZH,high(NUM_CODES) ;адрес начала таблицы символов - старший байт
 ldi ZL,low(NUM_CODES) ;и младший. Сейчас, регистр Z указывает на символ '0'
 add ZL,r16 ;прибавляем к нему интересующий нас номер символа (он хранится в r16)
 clr r16 ;так как адрес области памяти двухбайтный, может понадобиться изменить еще и ZH. Для этого обнуляем r16
 adc ZH,r16 ;и складываем ZH с нулем, с учетом переноса
 lpm r16,Z ;собственно, LPM
 pop ZL ;восстанавливаем сохраненные ZL и ZH
 pop ZH
ret ;возврат из процедуры
...
NUM_CODES: //коды символов - '0','1','2',... 
.db 0b11000000,0b11111001,0b10100100,...
После подачи питания на собранную схему, загорается весь семисегмент
А если попробовать зажигать числа в цикле, меняя их, скажем, раз в секунду. Задержку можно и программную поставить. Просто чтобы проверить подключение индикатора. Отдельно можно проверить работу кнопок.
Реклама
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Atmega8, подключение семисегментного индикатора

Сообщение akl »

Удалил. :oops:
Последний раз редактировалось akl Ср окт 29, 2014 14:18:59, всего редактировалось 1 раз.
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Atmega8, подключение семисегментного индикатора

Сообщение Rtmip »

akl писал(а):У mega8 регистр разрешения прерываний INT0, INT1 называется GICR. Жаль, что проктоус об этом не знает.
Все он знает, ибо не совсем уж дураки ваяли, из "m8def.inc":
; ***** EXTERNAL_INTERRUPT ***********
; GICR - General Interrupt Control Register
.equ GIMSK = GICR ; For compatibility...
Причина не работы в железе, случайно, не может быть в "прошитом" WDTON, или просто спаяли плохо?
Реклама
Эиком - электронные компоненты и радиодетали
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Atmega8, подключение семисегментного индикатора

Сообщение akl »

Виноват, удалил.
Реклама
Efiop
Родился
Сообщения: 4
Зарегистрирован: Вт окт 28, 2014 17:10:53

Re: Atmega8, подключение семисегментного индикатора

Сообщение Efiop »

Rtmip писал(а):
akl писал(а):У mega8 регистр разрешения прерываний INT0, INT1 называется GICR. Жаль, что проктоус об этом не знает.
Все он знает, ибо не совсем уж дураки ваяли, из "m8def.inc":
; ***** EXTERNAL_INTERRUPT ***********
; GICR - General Interrupt Control Register
.equ GIMSK = GICR ; For compatibility...
Причина не работы в железе, случайно, не может быть в "прошитом" WDTON, или просто спаяли плохо?
Посмотрю по поводу WDTON, спаянно вроде нормально все контакты позванивал. А еще вопрос, на семисегментном индикаторе 3 общих анода, плюс подается только на 1 или на все нужно? Смотрел на генераторе, горят все от одного, зачем нужны еще 2 не могу понять.
Реклама
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Atmega8, подключение семисегментного индикатора

Сообщение COKPOWEHEU »

Например, для удобства разводки платы. Может быть удобнее тянуть общий в один угол, а может - в другой. Тут достаточно проверить, действительно ли горит при любом "общем".
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: Atmega8, подключение семисегментного индикатора

Сообщение vdavid »

Попробуйте для начала перед sei записать вот это:
MAIN: rjmp MAIN
И убедитесь, что таки отображается (или нет) "0".
sanya839
Родился
Сообщения: 6
Зарегистрирован: Вт окт 21, 2014 15:09:10

Re: Atmega8, подключение семисегментного индикатора

Сообщение sanya839 »

Оооо, братья славяне как кнопки подключаются? Я так понял по схеме из первого поста что кнопка один вывод на Int0 а второй вывод на землю? А разве он должен идти не на VCC? И нужен ли там резистор?
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Atmega8, подключение семисегментного индикатора

Сообщение Rtmip »

sanya839 писал(а):...кнопка один вывод на Int0 а второй вывод на землю? А разве он должен идти не на VCC? И нужен ли там резистор?
Вот так инициализировано:
cbi DDRD, DDD2 ;конфигурирование порта D как входного
sbi PIND,PD2
cbi DDRD, DDD3
sbi PIND,PD3
Что в этом случае даст подключение на VCC? Извините, не понял, про какой "там" резистор речь, который не нужен?
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Atmega8, подключение семисегментного индикатора

Сообщение COKPOWEHEU »

С таким конфигурированием без разницы, на землю коммутировать или на питание, работать не будет. Чтобы заработало, надо изучить, что такое "подтягивающий внутренний резистор", который подключается установкой лог.1 в PORTx при настройке порта на вход DDRx=0.
А разве он должен идти не на VCC? И нужен ли там резистор?
Вообще, нужен. Между входом контроллера и питанием. Но в любительских условиях его ставят редко - внутренней подтяжки хватает. А когда не хватает - начинают писать на форум.
Efiop
Родился
Сообщения: 4
Зарегистрирован: Вт окт 28, 2014 17:10:53

Re: Atmega8, подключение семисегментного индикатора

Сообщение Efiop »

COKPOWEHEU писал(а):С таким конфигурированием без разницы, на землю коммутировать или на питание, работать не будет. Чтобы заработало, надо изучить, что такое "подтягивающий внутренний резистор", который подключается установкой лог.1 в PORTx при настройке порта на вход DDRx=0.
А разве он должен идти не на VCC? И нужен ли там резистор?
Вообще, нужен. Между входом контроллера и питанием. Но в любительских условиях его ставят редко - внутренней подтяжки хватает. А когда не хватает - начинают писать на форум.
Хм, тогда, чтобы заработал подтягивающий, порт D должен быть инициализирован так?

Код: Выделить всё

cbi DDRD, DDD2
sbi PORTD, PD2

cbi DDRD, DDD3 
sbi PORTD, PD3
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Atmega8, подключение семисегментного индикатора

Сообщение Rtmip »

COKPOWEHEU писал(а):С таким конфигурированием без разницы, на землю коммутировать или на питание, работать не будет. Чтобы заработало, надо изучить, что такое "подтягивающий внутренний резистор", который подключается установкой лог.1 в PORTx при настройке порта на вход DDRx=0.
А разве он должен идти не на VCC? И нужен ли там резистор?
Вообще, нужен. Между входом контроллера и питанием. Но в любительских условиях его ставят редко - внутренней подтяжки хватает. А когда не хватает - начинают писать на форум.
Долго и вдумчиво читал, но так и не понял, кому и на какой пост Вы отвечаете! :))
Конфигурирование автор темы правильно сделал, что в нем не так? А вот по поводу последнего предложения: "А когда не хватает - начинают писать на форум ",
Вы попали в точку! Стало интересно, собрал на макетке схему автора и залил его код "как есть". Результат: если питать схему от трансформаторного БП и подальше
от источников помех, то прекрасно видно, как кнопки "нажимаются сами собой" цифры быстро сменяют друг друга. Если питать от импульсного БП или от компа,
или рядом с компом, то просто горит "8" и создается впечатление, что ничего не работает! Установка внешней подтяжки решает все проблемы.
Вывод: без внешней подтяжки помехи очень быстро нажимают на кнопки, вместо человека.
Efiop писал(а):Хм, тогда, чтобы заработал подтягивающий, порт D должен быть инициализирован так?
да так и для верности поставьте резисторы от кнопки к плюсу(от 4.7к до 10к) и "придумайте" в программе антидребезг.
Последний раз редактировалось Rtmip Сб ноя 01, 2014 00:12:18, всего редактировалось 1 раз.
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: Atmega8, подключение семисегментного индикатора

Сообщение vdavid »

Rtmip писал(а):он уже так у Вас и инициализирован.
Первоначально он таки неправильно был инициализирован. PORTD и PIND совсем не одно и то же.
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Atmega8, подключение семисегментного индикатора

Сообщение Rtmip »

Совершенно верно, спасибо, исправил сообщение выше :facepalm: . Проверил на макетке схему автора, помехи почти не мешают.
Вот интересно, почему протеус это проглотил и выставил на порту "1"? Вроде у меги8 нет такой "фишки":
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
В железе на Atmega8А не работает :(
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Atmega8, подключение семисегментного индикатора

Сообщение COKPOWEHEU »

Efiop писал(а): Хм, тогда, чтобы заработал подтягивающий, порт D должен быть инициализирован так?

Код: Выделить всё

cbi DDRD, DDD2
sbi PORTD, PD2

cbi DDRD, DDD3 
sbi PORTD, PD3
А что мешает взять и проверить? Вроде похоже на правду.
Конфигурирование автор темы правильно сделал, что в нем не так?
Присвоения PORTD я у него не увидел, как и резисторов на схеме.
да так и для верности поставьте резисторы от кнопки к плюсу(от 4.7к до 10к) и "придумайте" в программе антидребезг.
Для тестовых схем это все же не обязательно, на то и тестовые. А вот в конечном устройстве все это делать надо.
Efiop
Родился
Сообщения: 4
Зарегистрирован: Вт окт 28, 2014 17:10:53

Re: Atmega8, подключение семисегментного индикатора

Сообщение Efiop »

Забыл ответить, всем большое спасибо, все заработало!
Ответить

Вернуться в «AVR»