Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Avr90s8515
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Prevan
Доброго времени суток!
Возник вопрос, связанный с реализацией на МК 8515 программы, которая через порт А выполняет чтение данных с буфера (например число 11110000), а затем производит запись в регистр этого числа. В схеме используется дешифратор адреса на базе микросхемы 74ALS155, который осуществляет выбор через ножки МК (PС6 и PС7) буфера или регистра.
Суть микросхемы заключатеся в том, чтобы считать значения с задатчиков (число 11110000) и выдать их на светодиоды (первые четыре включены, остальные выключены).
При запуске в протеусе сама схема, кроме МК работает правильно. МК осуществляет управление дешифраторам неправильно (ножки МК PС6 и PС7 - выбор микросхемы, ножки PD6 и PD7 - стробирующие сигналы дешифратора).

Код программы:
Код
;************************************************* **********************
; Программ один раз в секунду считывает данные с входов и выводит их
;без изменений на выходы.
;************************************************* **********************
.include "c:\8515def.inc"; Подключение внешней библиотеки с описанием
; символических имен и определением адресов
; регистров микроконтроллера
.cseg
.org 0
rjmp init; Вектор прерывания по включению питания,
.org $0d;

.def inl = r3; Данные получаемые с входов
.def inh = r4;
.def outl = r5; Данные на выходы
.def outh = r6;
.def temp = r16; Временные регистры
.def temp1 = r17;
.def temp2 = r18;
; имен портов и подпрограммами
;****** Инициализация контроллера ****************************************
; выполняется при включении питания, сбросу RESET, или от
; сторожевого таймера
;************************************************* ************************
;****** Чтение данных *****************************************
read_in:
clr zl; Устанавливаем адрес первого буфера
ldi zh, $80;
ld inh, z; Читаем содержимое первого буфера
ldi zh, $40; Устанавливаем адрес второго буфера
ld inl, z; Читаем содержимое второго буфера
ret



;****** Запись данных ****************************************
write_out:
clr zl; Устанавливаем адрес первого регистра
ldi zh, $80;
st z, outh; Записываем значения в первый регистр
ldi zh, $40; Устанавливаем адрес второго регистра
st z, outl; Запмисываем значения во второй регистр
ret
;****** Формирование задержки 1с **************************************
delay1:
ldi temp2, 25;
d0: ser temp1;
d1: ldi temp, 209;
d2: dec temp;
brne d2;
dec temp1;
brne d1;
dec temp2;
brne d0;
ret;
init:
;****** Инициализация МК **********************************
ldi temp, low(RAMEND); Инициализация указателя стека
out SPL, temp; в конце внутреннего ОЗУ
ldi temp, high(RAMEND);
out SPH, temp;
ldi temp, (1<<SRE); Разрешение работы с внешним ОЗУ
out mcucr, temp;
;****** Основная программа ***********************************************
main:
rcall read_in; Вызов подпрограммы чтения данных
mov outh, inh;
mov outl, inl;
rcall write_out; Вызов подпрограммы записи данных
rcall delay1; Вызов подпрограммы формирования задержки 1с
rjmp main;
domowoj
А зачем так много переключателей, зачем и к питанию и на землю,
просто ставишь резисторы на + и коммутируешь (или не коммутируешь) вход на землю.
У процессора три почти свободных порта, зачем эта городьба чтением???
И с выводом такие сложности.
Для уменьшения кол-ва успользуемых выводов МК
можно было использовать регистры с последовательным входом и параллельным выходом
ILYAUL
Цитата(Prevan @ Apr 7 2010, 15:53) *
Доброго времени суток! Код программы:

Я вижу , что Вы прочитали , что-то из памяти SRAM , поменяли регистры командой mov (не понятно зачем) и записали обратно по тем же адресам в память. ( выделено) И частоту процессора , плиз в студию.
Может , конечно к регистрам портов ввода вывода в данной микросхеме надо обращаться только как к SRAM ? счас гляну DS

Нет на месте , в области ввода вывода . Поэтому команды обычно IN и OUT
ae_
2 Prevan:
на схеме перепутаны сигналы чтения и записи первого буфера, надо поменять местами сигналы идущие к выводам U9(11) <-> U8(6)
Prevan
Проблему с МК решил путём подключения HEX исходника вместо asm. Исправил переключатели. Частота процессора 1 МГц. Использование регистра с последовательным входом, как мне показалось, усложнит саму схему.

Цитата(ae_ @ Apr 8 2010, 08:35) *
2 Prevan:
на схеме перепутаны сигналы чтения и записи первого буфера, надо поменять местами сигналы идущие к выводам U9(11) <-> U8(6)

После того, как поменял местами эти сигналы, схема заработала правильно! Всем большое СПАСИБО cool.gif
777777
Микроконтроллеры придуманы для того, чтобы не ставить мелкие микросхемы. Зачем, например, нужна микросхема U9 если на нее заходит 4 сигнала и выходит 4? Да и без U4-U7 можно было обойтись.
IgorKossak
В схеме можно оставить только переключатели (матрицей 4 на 4, т. е. всего 8 выводов контроллера), микроконтроллер и светодиоды (с токоограничивающими резисторами) снабдив группы светодиодов двумя ключами для динамической индикации (в простейшем случае ещё 10 выводов).
Ну а если реализовать нужно только описанный алгоритм, то и микроконтроллер не нужен. rolleyes.gif
Prevan
Цитата(777777 @ Apr 8 2010, 11:30) *
Микроконтроллеры придуманы для того, чтобы не ставить мелкие микросхемы. Зачем, например, нужна микросхема U9 если на нее заходит 4 сигнала и выходит 4? Да и без U4-U7 можно было обойтись.

В перспективе планируется расширение данной схемы. Я решил её собирать по частям (модулями), чтобы потом соединить их все вместе в одну схему. Насчёт U9 полностью согласен - можно было напрямую провода провести, а как можно без U4-U7 соединить в одну шину две группы диодов и задатчиков к ним, чтобы сигналы не налагались один на другой?
ILYAUL
Цитата(Prevan @ Apr 7 2010, 15:53) *
Суть микросхемы заключатеся в том, чтобы считать значения с задатчиков (число 11110000) и выдать их на светодиоды (первые четыре включены, остальные выключены).

У данной микросхемы аж три порта ввода вывода. Один порт считывает , один выдает на светодиоды. Лишние здесь все микросхемы микросхемы
Или сформулируйте , что Вы собственно хотите сделать, но если только то ,что Вы написали выше, то микроконтроллер в данной схеме -нонсенс
Prevan
Цитата(ILYAUL @ Apr 8 2010, 20:55) *
У данной микросхемы аж три порта ввода вывода. Один порт считывает , один выдает на светодиоды. Лишние здесь все микросхемы микросхемы
Или сформулируйте , что Вы собственно хотите сделать, но если только то ,что Вы написали выше, то микроконтроллер в данной схеме -нонсенс

"Суть микросхемы заключатеся в том, чтобы считать значения с задатчиков (число 11110000) и выдать их на светодиоды (первые четыре включены, остальные выключены)." - это только часть общей схемы. Полная схема задействует почти все выводы микроконтроллера и служит как раз для демонстрации работы с микроконтроллером. Задатчики и светодиоды - пример работы МК с портами ввода-вывода.
Prevan
А не знаете, можно ли код составить, не используя команды работы с внешней памятью?
ILYAUL
Цитата(Prevan @ Apr 12 2010, 18:28) *
А не знаете, можно ли код составить, не используя команды работы с внешней памятью?

Какой код и для чего? Вы не стесняйтесь в словах , тогда Вам помогут
ae_
Цитата(Prevan @ Apr 12 2010, 22:28) *
А не знаете, можно ли код составить, не используя команды работы с внешней памятью?

Конечно можно:
- Запретить использование External SRAM - обнулить бит SRE регистра MCUCR
- самому конфигурировать каждый раз направление DDRA на input перед чтением данных с задатчиков,
и DDRA на output перед записью во внешние регистры
- самому выставлять старшую половину адреса на PORTC (PC6,PC7) для выбора буфера 1 или 2
- самому управлять сигналами PD6,PD7 (!WR, !RD) для чтения и записи из/в задатчиков/регистры
- для чтения:
in inh, PINA
для записи:
out PORTA, outh

Если убрать дешифратор адреса и доп.инверторы, то можно подключить выводы записи регистров и выводы чтения задатчиков напрямую к контроллеру, будут задействованы те же 4 вывода, но управлять станет удобнее.
Prevan
Ещё раз здравствуйте! Спасибо всем за помощь. Возник вопрос, связанный с программной частью МК, которая должна выводить бегущую строку на диплей. При запуске питание на микроконтроллер и на дисплей подаётся удачно, но требуемой задачи схема, приведённая ниже не выполняет (попросту говоря, дисплей вообще молчит).

CODE
.include "8515def.inc" ; Подключение внешней библиотеки с описанием
; символических имен и определением адресов
; регистров микроконтроллера
.cseg ; CODE segment
.org 0 ;
rjmp init ; Вектор прерывания по включению питания,
; сбросу RESET или от сторожевого таймера
.org $0d ;
.include "MyLib.inc" ; Подключение файла с описанием символических
; имен портов и подпрограммами
;****** Инициализация контроллера ****************************************
;** выполняется при включении питания, сбросу RESET, или от **
;** сторожевого таймера **
;*************************************************************************
init:
ldi temp, low(RAMEND) ; Инициализация указателя стека
out SPL, temp ; в конце внутреннего ОЗУ
ldi temp, high(RAMEND);
out SPH, temp ;

rcall Config_Port ; Вызов подпрограммы конфигурирования портов
rcall Init_lcd ; Вызов подпрограммы инициализации ЖКИ
;****** Вывод в DDRAM постоянного текста*******************
rcall wait_busy ;
ldi zl,low(text0*2) ; Установить указатель Z на начало буфера text0
ldi zh,high(text0*2);
ldi temp2, 30 ; Установить счетчик программируемых ячеек DDRAM
ddram:
lpm ; Извлечь из flash-памяти байт данных
mov dat_lcd, r0 ;
rcall lcd_dat ; Записать его в DDRAM
rcall wait_busy ;
ld r0, z+ ; Увеличить на 1 указатель Z адреса flash-памяти
dec temp2 ; Если еще не все ячейки запрограммированы
brne ddram ; вернуться назад
;*************************************************************************
;****** Основная программа ***********************************************
main:
ldi temp, 2 ; Установить дисплей относительно буфера
rcall lcd_dat ; DDRAM в начальную позицию
ldi r24,5 ; остановка
stop1:
rcall del200
dec r24
brne stop
ldi r24, 10 ; установка счетчика символов
shift:
ldi dat_lcd,$18 ; сдвиг дисплея на один символ
rcall lcd_com
rcall del200 ; задержка ~1/5 с при кварце 4 МГц
dec r24
brne shift
ldi r24,5 ; остановка после вывода каждой строки
stop:
rcall del200
dec r24
brne stop
rjmp main ; повторить сначала
;***********************************************************************
;****** Инициализация ЖКИ **********************************************
init_lcd:
ldi dat_lcd, 0b00001000 ; включить дисплей, выключить курсор
rcall lcd_com ;
rcall del40 ;
ldi dat_lcd, 0b00110000 ; 8-битный интерфейс, 1-строка, шрифт-5х8 точек
rcall lcd_com ;
rcall del40 ;
ldi dat_lcd, 0b00000110 ; Направление сдвига курсора вправо,
rcall lcd_com ; запретить сдвиг дисплея вместе с курсором
rcall del40 ;
ldi dat_lcd, 0b00000001 ; Очистить дисплей и установить курсор в
rcall lcd_com ; начальную позицию
rcall del40 ;
ret
;****** Запись команды в ЖКИ *******************************************
lcd_com:
in temp, ddrc ; Чтение состояния выводов порта С
andi temp, 0b11001111; Сброс RS и R/W (Выводы PC4, PC5)
out ddrc, temp ;
sbi portb, LCD_E ; Установка бита 0 порта B(сигнал E=1).
out porta, dat_lcd ; Вывод команды на шину данных LCD
cbi portb, LCD_E ; Cброс бита 0 порта B(сигнал E=0)
ret
;****** Запись данных в ЖКИ ********************************************
lcd_dat:
cbi ddrc, LCD_RW ; Сброс R/W
sbi ddrc, LCD_RS ; Установка RS
sbi portb, LCD_E ; Установка бита 0 порта B(сигнал E=1).
out porta, dat_lcd ; Вывод ASCII символа на шину данных LCD
cbi portb, LCD_E ; Cброс бита 0 порта B(сигнал E=0)
ret
;****** Подпрограмма чтения BUSY флага и счетчика адреса ЖКИ ***********
read_busy:
clr temp ; Линии порта A как входы
out ddra, temp ;
out porta, temp ;
sbi ddrc, LCD_RW ; Установка R/W
cbi ddrc, LCD_RS ; Сброс RS
sbi portb, LCD_E ; Установка бита 0 порта B (сигнал E=1).
nop ; Формирование задержки 1 мкс
nop ;
nop ;
nop ;
in dat_lcd, pina ; Чтение данных из ЖКИ
cbi portb, LCD_E ; Cброс бита 0 порта B (сигнал E=0)
ser temp ; Линии порта A как выход
out ddra, temp ;
ret
;****** Подпрограмма ожидания сброса BUSY флага ЖКИ ********************
wait_busy: ;
rcall read_busy ;
sbrc dat_lcd, busy ;
rjmp wait_busy ;
ret
;****** Подпрограмма формирования задержки ~40мкс **********************
del40:
ldi temp, 53
d3: dec temp
brne d3
ret
;****** Подпрограмма формирования задержки *****************************
del200:
ldi temp2, 5
d0: ser temp1
d1: ldi temp, 209
d2: dec temp
brne d2
dec temp1
brne d1
dec temp2
brne d0
ret
;****** Во flash - памяти после программы размещаем постоянные данные **
.org $200
text0: .DB 168,112,111,180,112, 97,188,188,97 ;Программа
domowoj
Выдерживайте все времянки , рекомендованные в ДШ
и проблем не будет
ILYAUL
Цитата(Prevan @ Apr 20 2010, 20:05) *
........., дисплей вообще молчит).


Вы упустили самую главную часть , инициализация LCD. Что это такое и как её сделать Вы найдёте в DS на применёный в Вашем дисплее контролере. Т.к. Вы его не указали , помочь пока нечем
То , что Вы назвали
;****** Инициализация ЖКИ ********************************************** таковой не является
Prevan
Здравствуйте! Подкорректировал код с учётом задержек (руководствовался ДШ и примерами схожих программ). Программа компилируется и при запуске видно, как перебегают сигналы порта А, подключенного к ЖКИ, но дисплей по-прежнему ничего не отображает. По логике вещей, дело в последовательности установления битов RW, RS и Е, но просмотренный мною на несколько раз код явных ошибок не таит. Буду рад прочесть идеи, советы по направлению программы в рабочее русло...
CODE

.include "8515def.inc" ; Подключение внешней библиотеки с описанием
; символических имен и определением адресов
; регистров микроконтроллера
.cseg ; CODE segment
.org 0 ;
rjmp init ; Вектор прерывания по включению питания,
; сбросу RESET или от сторожевого таймера
.org $0d ;
.include "MyLib.inc" ; Подключение файла с описанием символических
; имен портов и подпрограммами
.def Dat_LCD= r20 ; Данные/команды передаваемые на LCD

;****** Инициализация контроллера ****************************************
;** выполняется при включении питания, сбросу RESET, или от
;** сторожевого таймера
;*************************************************************************
init:
ldi temp, low(RAMEND) ; Инициализация указателя стека
out SPL, temp ; в конце внутреннего ОЗУ
ldi temp, high(RAMEND) ;
out SPH, temp ;
rcall Config_Port ; Вызов подпрограммы конфигурирования портов
rcall Init_lcd ; Вызов подпрограммы инициализации ЖКИ

;****** Подпрограмма чтения BUSY флага и счетчика адреса ЖКИ ***********
read_busy:
clr temp ; Линии порта A как входы
out ddra, temp ;
out porta, temp ;
sbi ddrc, LCD_RW ; Установка R/W
cbi ddrc, LCD_RS ; Сброс RS
sbi portb, LCD_E ; Установка бита 0 порта B (сигнал E=1).
nop ; Формирование задержки 1 мкс
nop ;
nop ;
nop ;
in dat_lcd, pina ; Чтение данных из ЖКИ
cbi portb, LCD_E ; Cброс бита 0 порта B (сигнал E=0)
ser temp ; Линии порта A как выход
out ddra, temp ;
ret

;****** Подпрограмма ожидания сброса BUSY флага ЖКИ ********************
wait_busy: ;
rcall read_busy ;
sbrc dat_lcd, busy ;
rjmp wait_busy ;
ret

;****** Вывод в DDRAM постоянного текста*******************
rcall wait_busy ;
ldi zl,low(text0*2) ; Установить указатель Z на начало буфера text0
ldi zh,high(text0*2);
ldi temp2, 30 ; Установить счетчик программируемых ячеек DDRAM
ddram:
lpm ; Извлечь из flash-памяти байт данных
mov dat_lcd, r0 ;
rcall lcd_dat ; Записать его в DDRAM
rcall wait_busy ;
ld r0, z+ ; Увеличить на 1 указатель Z адреса flash-памяти
dec temp2 ; Если еще не все ячейки запрограммированы
brne ddram ; вернуться назад


;****** Основная программа ***********************************************
main:
ldi temp, 2 ; Установить дисплей относительно буфера
rcall lcd_dat ; DDRAM в начальную позицию
ldi r24,5 ; остановка
stop1:
rcall del200
dec r24
brne stop
ldi r24, 10 ; установка счетчика символов
shift:
ldi dat_lcd,$18 ; сдвиг дисплея на один символ
rcall lcd_com
rcall del200 ; задержка ~1/5 с при кварце 4 МГц
dec r24
brne shift
ldi r24,5 ; остановка после вывода каждой строки
stop:
rcall del200
dec r24
brne stop
rjmp main ; повторить сначала

;****** Инициализация ЖКИ **********************************************
INIT_LCD: ;ПОДПРОГРАММА ИНИЦИАЛИЗАЦИИ ЖКИ
rcall DEL_5MS ;Задержка 15 мс
rcall DEL_5MS ;
rcall DEL_5MS ;
ldi Dat_LCD,$38 ;ЖКИ 8 бит,2 строки, 5х7 точек
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_5MS ;Задержка 5.4 нс
ldi Dat_LCD,$38 ;ЖКИ 8 бит,2 строки, 5х7 точек
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_100us ;Задержка 100 мкс
ldi Dat_LCD,$38 ;ЖКИ 8 бит,2 строки, 5х7 точек
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_100us ;Задержка 100 мкс
ldi Dat_LCD,$38 ;ЖКИ 8 бит,2 строки, 5х7 точек
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_100us ;Задержка 100 мкс
ldi Dat_LCD,$04 ;Выключить ЖКИ
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_100us ;Задержка 100 мкс
ldi Dat_LCD,$01 ;Очистить ЖКИ,и устан. курсор в начало
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_5MS ;Задержка 5.4 мс
ldi Dat_LCD,$0c ;вкл. дисплей, выкл. кусор,мерцание выкл.
rcall lcd_dat ;Запись управляющего слова в ЖКИ
rcall DEL_100us ;задержка 100 мкс;
ret

;****** Запись команды в ЖКИ *******************************************
lcd_com:
in temp, ddrc ; Чтение состояния выводов порта С
andi temp, 0b11001111 ; Сброс RS и R/W (Выводы PC4, PC5)
out ddrc, temp ;
sbi portb, LCD_E ; Установка бита 0 порта B(сигнал E=1).
out porta, dat_lcd ; Вывод команды на шину данных LCD
cbi portb, LCD_E ; Cброс бита 0 порта B(сигнал E=0)
ret

;****** Запись данных в ЖКИ ********************************************
lcd_dat:
cbi ddrc, LCD_RW ; Сброс R/W
sbi ddrc, LCD_RS ; установка RS ????????????????????????
sbi portb, LCD_E ; Установка бита 0 порта B(сигнал E=1).
out porta, dat_lcd ; Вывод ASCII символа на шину данных LCD
cbi portb, LCD_E ; Cброс бита 0 порта B(сигнал E=0)
ret
;****** Подпрограмма формирования задержки *****************************
DEL_5MS: ;ЗАДЕРЖКА 5 МС
ldi R25,27
d: ldi R24,255
d1: dec R24
brne d1
dec R25
brne d
ret

;****** Подпрограмма формирования задержки *****************************
DEL_100us: ;ЗАДЕРЖКА 100 МКС
ldi R25,125
d2: dec R25
brne d2
ret

;****** Подпрограмма формирования задержки *****************************
del200:
ldi temp2, 5
d3: ser temp1
d4: ldi temp, 209
d5: dec temp
brne d5
dec temp1
brne d4
dec temp2
brne d3
ret

;****** Во flash - памяти после программы размещаем постоянные данные **
.org $200
text0: .DB 168,112,111,180,112, 97,188,188,97 ;Программа
ILYAUL
Цитата(Prevan @ May 5 2010, 20:52) *
Здравствуйте! Подкорректировал код с учётом задержек (руководствовался ДШ и примерами схожих программ). Программа компилируется и при запуске видно, как перебегают сигналы порта А, подключенного к ЖКИ, но дисплей по-прежнему ничего не отображает. По логике вещей, дело в последовательности установления битов RW, RS и Е, но просмотренный мною на несколько раз код явных ошибок не таит. Буду рад прочесть идеи, советы по направлению программы в рабочее русло...


1. Файл Mylib.inc и плиз в архиве , а не кодом
2. Какой LCD?
Prevan
LCD LM016L (HD44780)
akl
Здравствуйте. Непонятно чему верить- схеме, коду или комментариям к нему. Например, сигнал LCD_E отправляется в portb,3, а он настроен на вход. А управление линиями LCD_RS LCD_RW обращением к ddrc, это что-то. Посмотрите, для примера, эту веточку.
http://electronix.ru/forum/index.php?showt...mp;#entry692654
Prevan
Нашёл в интернете примеры инициализации и функций. Дисплей загорается и выводит строчки на экран. Чтобы сделать бегущую строку я после вывода каждого символа вызываю функцию задержки, а в конце главной программы main ставлю строчку "rjmp main". После запуска прогамма зависает. Не могу понять в каком месте программа зацикливается:
CODE

;------------------------------------------------------------------------------------------

; подключаем файл
.include "8515def.inc"

.equ LCDRS = 5
.equ LCDWR = 4
.equ LCDCLK = 3
.def temp1 = r17 ; Временные регистры
.def temp2 = r18 ;
;------------------------------------------------------------------------------------------

reset:
ldi r16,high(RAMEND); инициализация указателя стека
out SPH, r16 ;
ldi r16,low(RAMEND) ;
out SPL, r16 ;
ser r16 ;
out DDRC, r16 ; устанавливает порт С на выход
ldi r16, 0x30 ; устанавливает сигналы RS и RW
out DDRC, r16 ; в LCD
ldi r16, 0x08 ; устанавливает сигнал E
out DDRD, r16 ; в LCD
rcall lcd_init ; вызывает инициализацию дисплея


;------------------------------------------------------------------------------------------

lcd_init:
rcall DEL_5MS ;Задержка 15 мс
rcall DEL_5MS ;
rcall DEL_5MS ;
ldi r16, 0x38 ; определяет 8 разр. шину данных, 5х7 точек, 2 строки
rcall lcd_cmd ;
rcall DEL_5MS ;Задержка 5.4 нс
ldi r16, 0x0C ; включить дисплей, показать курсор
rcall lcd_cmd ;
rcall DEL_5MS ;Задержка 5.4 нс
ldi r16, 0x01 ; очистить дисплей, курсор в начальную позицию
rcall lcd_cmd ;
rcall DEL_5MS ;Задержка 5.4 нс
ldi r16, 0x06 ; направление сдвига курсора вправо
rcall lcd_cmd ;
rcall DEL_100us ;Задержка 100 мкс
ret

;------------------------------------------------------------------------------------------

lcd_prt:
sbi PORTD, LCDCLK; устанавливает строб E
sbi PORTC, LCDRS ; устанавливает RS=1 (передаются данные)
out PORTA, r16 ; записывает данные в порт А
cbi PORTD, LCDCLK; сбрасывает строб Е
rjmp lcd_wait ; вызывает подпрограмму чтения BUSY флага LCD
ret

;------------------------------------------------------------------------------------------

lcd_cmd:
sbi PORTD, LCDCLK; устанавливает строб E
cbi PORTC, LCDRS ; устанавливает RS=0 (передаются команды)
out PORTA, r16 ; записывает команды в порт А
cbi PORTD, LCDCLK; сбрасывает строб Е
rjmp lcd_wait ; вызывает подпрограмму чтения BUSY флага LCD
ret

;------------------------------------------------------------------------------------------

lcd_wait:
cbi PORTC, LCDRS ; устанавливает RS=0 (передаются команды)
sbi PORTC, LCDWR ; устанавливает RW (чтение)
sbi PORTD, LCDCLK; устанавливает строб E
clr r16 ;
out DDRA, r16 ; устанавливает порт данных на вход
out PINA, r16 ; очищает данные PINA
in r16, PINA ; записывает адрес BUSY флага
cbi PORTD, LCDCLK; сбрасывает строб Е
push r16
ser r16 ;
out DDRA, r16 ; установить порт А на вывод
cbi PORTC, LCDWR ; сбросить RW снова
pop r16
sbrc r16, 7 ; если BUSY флаг пуст - вернуться (LCD не готов)
rjmp lcd_wait ; если нет - ждать готовности LCD
ret

;****** Подпрограмма формирования задержки *****************************
DEL_5MS: ;ЗАДЕРЖКА 5 МС
ldi R25,27
d: ldi R24,255
d1: dec R24
brne d1
dec R25
brne d
ret

;****** Подпрограмма формирования задержки *****************************
DEL_100us: ;ЗАДЕРЖКА 100 МКС
ldi R25,125
d2: dec R25
brne d2
ret

;****** Подпрограмма формирования задержки *****************************
del200:
ldi temp2, 5
d3: ser temp1
d4: ldi R16, 209
d5: dec R16
brne d5
dec temp1
brne d4
dec temp2
brne d3
ret
;------------------------------------------------------------------------------------------

main:
ldi r16, 0x00|0x80 ; помещает курсор в 1ю строку, первый символ
rcall lcd_cmd ; String1
ldi r16, 'S'
rcall lcd_prt
rcall del200
ldi r16, 't'
rcall lcd_prt
rcall del200
ldi r16, 'r'
rcall lcd_prt
rcall del200
ldi r16, 'i'
rcall lcd_prt
rcall del200
ldi r16, 'n'
rcall lcd_prt
rcall del200
ldi r16, 'g'
rcall lcd_prt
rcall del200
ldi r16, '1'
rcall lcd_prt



ldi r16, 0x40|0x80 ; помещает курсор во 2ю строку, второй символ
rcall lcd_cmd ; String2
ldi r16, 'S'
rcall lcd_prt
rcall del200
ldi r16, 't'
rcall lcd_prt
rcall del200
ldi r16, 'r'
rcall lcd_prt
rcall del200
ldi r16, 'i'
rcall lcd_prt
rcall del200
ldi r16, 'n'
rcall lcd_prt
rcall del200
ldi r16, 'g'
rcall lcd_prt
rcall del200
ldi r16, '2'
rcall lcd_prt
rjmp main

akl
"...Дисплей загорается и выводит строчки на экран..."
Странно. Жаль, что Вы не ходили по ссылке.
Нажмите для просмотра прикрепленного файла
Prevan
akl, я скачивал пример по этой ссылке, пробовал собрать к нему схему в протеусе, чтобы запустить и потом переделать в свою работу. Пример сразу не запустился. Так как только начинаю программировать для AVR, с ошибками не смог разобраться.

Сейчас пробую сделать программу, которая при нажатии на кнопку матричной клавиатуры выводит её код на LCD дисплей. В книге нашёл похожий пример. Собранная по примеру из книги схема запускается, работает согласно задуманному алгоритму, но у нее есть недостаток, заключающийся в том, что у меня по-другому подключены порты:
Пример: У меня:
PС(0..7) PA(0..7)
PD0 PD4
PD1 PD5
PD(4..7) PC(0..3)
PA5 PC5
PA6 PC4
PA7 PD3

Пример:
CODE

;******************************************************
.include "8515def.inc" ;файл определений AT90S8515
.def temp=r16 ;временная переменная
.def cols=r18 ;номер сканируемого ряда
;клавиатуры
.def rots=r21 ;номер строки клавиатуры
.def key=r19 ;номер кнопки
.def scancod=r20 ;сканирующий код
.def lcd=r22 ;регистр LCD (ЖК-дисплея)
.def count_lcd=r23 ;счетчик выводимых символов
;на LCD
;Разряды порта РА для управления LCD
.equ rs=5 ; (RS=1) - данные, (RS=0) - команды
.equ rw=6 ; (RW=1) - чтение LCD, (RW=0) - запись в LCD
.equ e=7 ;строб сигналов на шине команды/данные

.org $000
rjmp init
.org $007
rjmp scankeys ;обработка клавиатуры

;Инициализация
init:
ldi temp,low(RAMEND) ;Инициализация
out spl,temp ;указателя стека
ldi temp,high(RAMEND)
out sph,temp
;Инициализация портов
ser temp
out DDRA,temp ;порт РА на вывод
out DDRC,temp ;порт РC на вывод
ldi temp,$0F ;линии порта PD0-PD3 на вывод,
out DDRD,temp ;PD4-PD7 на ввод
ldi temp,$F0
out PORTD,temp
;Инициализация таймера 0
ldi temp,$05
out TCCR0,temp ;коэффициент деления 1024
ldi temp, (1<<TOIE0)
out TIMSK, temp ;разрешение прерываний от таймера
;Инициализация ЖК-дисплея
rcall delay2ms
ldi lcd,$38 ;8-битовый режим вывода,
rcall lcdcom ;2 строки, шрифт 5х7
ldi lcd,$06
;Направление сдвига курсора вправо, без сдвига дисплея
rcall lcdcom
ldi lcd,$0C ;включить дисплей
rcall lcdcom ;погасить курсор
ldi lcd,$01
;Очистить дисплей и установить курсор в нулевую позицию
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти для вывода верхней
;строки дисплея
ldi lcd,$80
rcall lcdcom
ldi count_lcd,12 ;вывод на верхнюю строку дисплея
ldi zl,low(str_0*2)
ldi zh,high(str_0*2)
out0: lpm
adiw zl,1
mov lcd,r0
rcall lcddat
dec count_lcd
brne out0
;Установка адреса буферной памяти для вывода нижней строки
;дисплея
ldi lcd,$C0
rcall lcdcom
ldi count_lcd,17
sei ;разрешение прерываний
loop: rjmp loop

;Подпрограмма обработки клавиатуры
scankeys:
clr key
clr scancod
ldi cols,2
sec
scan: rol scancod ;формирование очередного скан-кода
out PORTD,scancod ;вывод на клавиатуру
clc
ldi rots,4
in temp,PIND ;ввод состояния клавиатуры
mm: rol temp
brcc nn ;проверка замыкания кнопки
rjmp press ;переход при замыкании (С=0)
nn: inc key ;увеличение номера кнопки
dec rots ;уменьшение номера строки
brne mm
dec cols ;уменьшение номера ряда
brne scan
press: cpi key,8
breq f1 ;выход при отсутствии замыканий
rcall lcd_str_1 ;вывод на дисплей
f1: reti

;Подпрограмма вывода значения клавиши на нижнюю строку
; дисплея
lcd_str_1:
dec count_lcd
brne met
;При достижении конца строки обновить счетчик вывода на
;дисплей, очистить дисплей и установить курсор в нулевую позицию
ldi count_lcd,16
ldi lcd,$01
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти на начало нижней строки
ldi lcd,$C0
rcall lcdcom
;Определение символа клавиши по ее номеру и вывод на
;дисплей
met: ldi zl,low(str_1*2)
ldi zh,high(str_1*2)
add zl,key
brcc me2
inc zh
me2: lpm
mov lcd,r0
rcall lcddat
ret

;Подпрограмма вывода на дисплей байта команды
lcdcom:
out PORTC,lcd ;вывод команды
ldi temp,0x80 ;установка режима записи команд
out PORTA,temp
cbi PORTA,e ;фронт 1/0 строба
rcall delay40us
ret

;Подпрограмма вывода на дисплей байта данных
lcddat:
out PORTC,lcd ;вывод символа
ldi temp,0xA0 ;установка режима записи данных
out PORTA,temp
cbi PORTA,e ;фронт 1/0 строба
rcall delay40us
ret

delay40us: ;задержака 40 мкс при Fclk - 3,69 МГц
ldi r18,48
d0:dec r18
brne d0
ret

delay2ms: ;задержка 2 мс
ldi r17,48
d1:rcall delay40us
dec r17
brne d1
ret

;Текст сообщения для верхней строки дисплея
str_0: .db 'K','E','Y','P','A','D',' ','+',' ','L','C','D'
;Обозначения клавиш, выводимые на нижнюю строку дисплй
str_1: .db '/','x','-','+','9','6','3','=','8','5','2','0','7','4','1','*'


У меня:
CODE

;******************************************************
.include "8515def.inc" ;файл определений AT90S8515
.def temp=r16 ;временная переменная
.def cols=r18 ;номер сканируемого ряда
;клавиатуры
.def rots=r21 ;номер строки клавиатуры
.def key=r19 ;номер кнопки
.def scancod=r20 ;сканирующий код
.def lcd=r22 ;регистр LCD (ЖК-дисплея)
.def count_lcd=r23 ;счетчик выводимых символов
;на LCD
;Разряды порта РА для управления LCD
.equ rs=5 ; (RS=1) - данные, (RS=0) - команды
.equ rw=4 ; (RW=1) - чтение LCD, (RW=0) - запись в LCD
.equ e=3 ;строб сигналов на шине команды/данные

.org $000
rjmp init
.org $007
rjmp scankeys ;обработка клавиатуры

;Инициализация
init:
ldi temp,low(RAMEND) ;Инициализация
out spl,temp ;указателя стека
ldi temp,high(RAMEND)
out sph,temp
;Инициализация портов
ser temp
out DDRA,temp ;порт РА на вывод

out DDRC,0b00110000 ; конфигурируем биты 4, 5 порта C на вывод.
out DDRD,e ; конфигурируем биты e порта D на вывод.

ldi temp,$30 ;линии порта PD4-PD5 на вывод,
out DDRD,temp
ldi temp,$F0 ;PC4-PC7 на ввод
out PORTC,temp

;Инициализация таймера 0
ldi temp,$05
out TCCR0,temp ;коэффициент деления 1024
ldi temp, (1<<TOIE0)
out TIMSK, temp ;разрешение прерываний от таймера
;Инициализация ЖК-дисплея
rcall delay2ms
ldi lcd,$38 ;8-битовый режим вывода,
rcall lcdcom ;2 строки, шрифт 5х7
ldi lcd,$06
;Направление сдвига курсора вправо, без сдвига дисплея
rcall lcdcom
ldi lcd,$0C ;включить дисплей
rcall lcdcom ;погасить курсор
ldi lcd,$01
;Очистить дисплей и установить курсор в нулевую позицию
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти для вывода верхней
;строки дисплея
ldi lcd,$80
rcall lcdcom
ldi count_lcd,12 ;вывод на верхнюю строку дисплея
ldi zl,low(str_0*2)
ldi zh,high(str_0*2)
out0: lpm
adiw zl,1
mov lcd,r0
rcall lcddat
dec count_lcd
brne out0
;Установка адреса буферной памяти для вывода нижней строки
;дисплея
ldi lcd,$C0
rcall lcdcom
ldi count_lcd,17
sei ;разрешение прерываний
loop: rjmp loop

;Подпрограмма обработки клавиатуры
scankeys:
clr key
clr scancod
ldi cols,2
sec
scan: rol scancod ;формирование очередного скан-кода
out PORTD,scancod ;вывод на клавиатуру
clc
ldi rots,4
in temp,PINC ;ввод состояния клавиатуры
mm: rol temp
brcc nn ;проверка замыкания кнопки
rjmp press ;переход при замыкании (С=0)
nn: inc key ;увеличение номера кнопки
dec rots ;уменьшение номера строки
brne mm
dec cols ;уменьшение номера ряда
brne scan
press: cpi key,8
breq f1 ;выход при отсутствии замыканий
rcall lcd_str_1 ;вывод на дисплей
f1: reti

;Подпрограмма вывода значения клавиши на нижнюю строку
; дисплея
lcd_str_1:
dec count_lcd
brne met
;При достижении конца строки обновить счетчик вывода на
;дисплей, очистить дисплей и установить курсор в нулевую позицию
ldi count_lcd,16
ldi lcd,$01
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти на начало нижней строки
ldi lcd,$C0
rcall lcdcom
;Определение символа клавиши по ее номеру и вывод на
;дисплей
met: ldi zl,low(str_1*2)
ldi zh,high(str_1*2)
add zl,key
brcc me2
inc zh
me2: lpm
mov lcd,r0
rcall lcddat
ret

;Подпрограмма вывода на дисплей байта команды
lcdcom:
out PORTA,lcd ;вывод команды
ldi temp,0x04 ;установка режима записи команд
out PORTD,temp
cbi PORTD,e ;фронт 1/0 строба
rcall delay40us
ret

;Подпрограмма вывода на дисплей байта данных
lcddat:
out PORTA,lcd ;вывод символа

ldi temp,0x20 ;установка режима записи данных
out PORTC,temp
ldi temp,0x04 ;установка режима записи данных
out PORTD,temp

cbi PORTD,e ;фронт 1/0 строба
rcall delay40us
ret

delay40us: ;задержака 40 мкс при Fclk - 3,69 МГц
ldi r18,48
d0:dec r18
brne d0
ret

delay2ms: ;задержка 2 мс
ldi r17,48
d1:rcall delay40us
dec r17
brne d1
ret

;Текст сообщения для верхней строки дисплея
str_0: .db 'K','E','Y','P','A','D',' ','+',' ','L','C','D'
;Обозначения клавиш, выводимые на нижнюю строку дисплй
str_1: .db '/','x','-','+','9','6','3','=','8','5','2','0','7','4','1','*'


моя программа запускается, ошибок не выдаёт, но и не работает.
ILYAUL
Код
out DDRD,e          ; конфигурируем биты e порта D на вывод.
ldi temp,$30        ;линии порта PD4-PD5 на вывод,
out DDRD,temp

Объясните зачем это - сначала 3 и тут же 48. Так надо?
Prevan
Цитата(ILYAUL @ Jun 4 2010, 03:40) *
Код
out DDRD,e         ; конфигурируем биты e порта D на вывод.
ldi temp,$30    ;линии порта PD4-PD5 на вывод,
out DDRD,temp

Объясните зачем это - сначала 3 и тут же 48. Так надо?

Ну да, тут можно было сразу задать:
ldi temp,$38 ;линии порта PD4-PD5 на вывод (0011 1000),
out DDRD,temp
но мне кажется проблема не в этом
ILYAUL
Цитата(Prevan @ Jun 4 2010, 03:48) *
но мне кажется проблема не в этом

{e } у Вас равен 3 , в какой бы системе это не было , но 3 всегда 3 т.е 0000 0011 , а сие значит что на "выход" вы установили PD0 & PD1, но Вам это "показалась" мало и Вы переконфигурировали порт DDRD на 48 или $30 или 0011 0000 т.е теперь выход стал PD4 PD5 , а PD0 и PD1 стали входами. Зачем Вы конфигурировали первое. А в итоге Вы пишите, что надо оказывается
Цитата
ldi temp,$38 ;линии порта PD4-PD5 на вывод (0011 1000),

Зачем PD3 выход?
Prevan
Цитата(ILYAUL @ Jun 5 2010, 04:17) *
{e } у Вас равен 3 , в какой бы системе это не было , но 3 всегда 3 т.е 0000 0011 , а сие значит что на "выход" вы установили PD0 & PD1, но Вам это "показалась" мало и Вы переконфигурировали порт DDRD на 48 или $30 или 0011 0000 т.е теперь выход стал PD4 PD5 , а PD0 и PD1 стали входами. Зачем Вы конфигурировали первое. А в итоге Вы пишите, что надо оказывается
Зачем PD3 выход?


С замечанием согласен по поводу конфигураций DDRD. Только {e } = 3 я так понял это просто присваивается имя четвертой ножке порта. И если я пишу к примеру:
sbi DDRD,e ; установить бит 3 порта D в «1»

Программу с матричной клавиатурой подкорректировал согласно замечаниям, получил:
CODE


;******************************************************
.include "8515def.inc" ;файл определений AT90S8515
.def temp=r16 ;временная переменная
.def cols=r18 ;номер сканируемого ряда
;клавиатуры
.def rots=r21 ;номер строки клавиатуры
.def key=r19 ;номер кнопки
.def scancod=r20 ;сканирующий код
.def lcd=r22 ;регистр LCD (ЖК-дисплея)
.def count_lcd=r23 ;счетчик выводимых символов
;на LCD
.equ rs=5 ; (RS=1) - данные, (RS=0) - команды
.equ rw=4 ; (RW=1) - чтение LCD, (RW=0) - запись в LCD
.equ e=3 ;строб сигналов на шине команды/данные

.org $000
rjmp init
.org $007
rjmp scankeys ;обработка клавиатуры

;Инициализация
init:
ldi temp,low(RAMEND) ;Инициализация
out spl,temp ;указателя стека
ldi temp,high(RAMEND)
out sph,temp
;Инициализация портов
ser temp
out DDRA,temp ;порт РА на вывод
ldi temp,$30
out DDRC,temp ; конфигурируем биты 4, 5 порта C на

вывод.
ldi temp,$38 ;линии порта PD4-PD5 на вывод,
out DDRD,temp
ldi temp,$0F ;PC0-PC3 на ввод
out PORTC,temp

;Инициализация таймера 0
ldi temp,$05
out TCCR0,temp ;коэффициент деления 1024
ldi temp, (1<<TOIE0)
out TIMSK, temp ;разрешение прерываний от таймера
;Инициализация ЖК-дисплея
rcall delay2ms
ldi lcd,$38 ;8-битовый режим вывода,
rcall lcdcom ;2 строки, шрифт 5х7
ldi lcd,$06
;Направление сдвига курсора вправо, без сдвига дисплея
rcall lcdcom
ldi lcd,$0C ;включить дисплей
rcall lcdcom ;погасить курсор
ldi lcd,$01
;Очистить дисплей и установить курсор в нулевую позицию
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти для вывода верхней
;строки дисплея
ldi lcd,$80
rcall lcdcom
ldi count_lcd,12 ;вывод на верхнюю строку дисплея
ldi zl,low(str_0*2)
ldi zh,high(str_0*2)
out0: lpm
adiw zl,1
mov lcd,r0
rcall lcddat
dec count_lcd
brne out0
;Установка адреса буферной памяти для вывода нижней строки
;дисплея
ldi lcd,$C0
rcall lcdcom
ldi count_lcd,17
sei ;разрешение прерываний
loop: rjmp loop

;Подпрограмма обработки клавиатуры
scankeys:
clr key
clr scancod
ldi cols,2
sec
scan: rol scancod ;формирование очередного скан-кода
out PORTD,scancod ;вывод на клавиатуру
clc
ldi rots,4
in temp,PINC ;ввод состояния клавиатуры
mm: rol temp
brcc nn ;проверка замыкания кнопки
rjmp press ;переход при замыкании (С=0)
nn: inc key ;увеличение номера кнопки
dec rots ;уменьшение номера строки
brne mm
dec cols ;уменьшение номера ряда
brne scan
press: cpi key,8
breq f1 ;выход при отсутствии замыканий
rcall lcd_str_1 ;вывод на дисплей
f1: reti

;Подпрограмма вывода значения клавиши на нижнюю строку
; дисплея
lcd_str_1:
dec count_lcd
brne met
;При достижении конца строки обновить счетчик вывода на
;дисплей, очистить дисплей и установить курсор в нулевую позицию
ldi count_lcd,16
ldi lcd,$01
rcall lcdcom
rcall delay2ms
;Установка адреса буферной памяти на начало нижней строки
ldi lcd,$C0
rcall lcdcom
;Определение символа клавиши по ее номеру и вывод на
;дисплей
met: ldi zl,low(str_1*2)
ldi zh,high(str_1*2)
add zl,key
brcc me2
inc zh
me2: lpm
mov lcd,r0
rcall lcddat
ret

;Подпрограмма вывода на дисплей байта команды
lcdcom:
out PORTA,lcd ;вывод команды
ldi temp,0x08 ;установка режима записи команд
out PORTD,temp
cbi PORTD,e ;фронт 1/0 строба
rcall delay40us
ret

;Подпрограмма вывода на дисплей байта данных
lcddat:
out PORTA,lcd ;вывод символа

ldi temp,0x20 ;установка режима записи данных
out PORTC,temp
ldi temp,0x08 ;установка режима записи данных
out PORTD,temp

cbi PORTD,e ;фронт 1/0 строба
rcall delay40us
ret

delay40us: ;задержака 40 мкс при Fclk - 3,69 МГц
ldi r18,48
d0:dec r18
brne d0
ret

delay2ms: ;задержка 2 мс
ldi r17,48
d1:rcall delay40us
dec r17
brne d1
ret

;Текст сообщения для верхней строки дисплея
str_0: .db 'K','E','Y','P','A','D',' ','+',' ','L','C','D'
;Обозначения клавиш, выводимые на нижнюю строку дисплй
str_1: .db '/','x','-','+','9','6','3','=','8','5','2','0','7','4','1','*'


При запуске программа ошибок не выдает, но на дисплей сразу без нажатия на любую кнопку клавиатуры выводит первую строку и ещё несколько символов, которые заполняют первую строку до конца (и продолжила бы заполнять, если бы дисплей был больше). На нажатия кнопок программа никак не реагирует.
ILYAUL
Можно всё таки вкладывать код в архиве так сложно его считывать
Prevan
Цитата(ILYAUL @ Jun 6 2010, 20:46) *
Можно всё таки вкладывать код в архиве так сложно его считывать
Prevan
Ещё раз здравствуйте! По-прежнему пытаю микроконтроллер, а именно SPI интерфейс. Пытаюсь считать данные с АЦП и передать их на ЦАП. Не знаю как запустить регулятор напряжения.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.