Страница 1 из 1

Глючит команда lpm ATmega16

Добавлено: Сб июл 12, 2008 20:19:42
AG
Написал программку на asm в AVRStudio 4.14 для ATMega16.

В proteus'e сие творение моделируется без проблем (кроме отображения русских букв на LCD).

Прошил контроллер, заметил также неправильную работу с русскими буквами.

После коваряний стало ясно, что в регистре R0 после команды lpm в любом случае оказывается 0xFF (0b11111111) (выводил результат на экран).

Проверял адрес считывания в регистре - адрес задан верно.

Написал подпрограмму, которая "считывает" (с помощью lpm) память программы и выводит на экран LCD с небольшими интервалами побайтно... На экране гордо красовались 1111 1111.

Из всего это получается, что lpm загружает не то что нужно....

Помогите, может у кого были такие проблемы

Заранее спасибо.

Добавлено: Сб июл 12, 2008 21:02:26
ARV
будьте любезны: разместите прямо на форуме только небольшой участок кода, где вы работаете с LPM - все "лишнее" откиньте... поверьте - искать в большом коде жалдкие 3 строчки - лишние усилия... а помочь, вроде, хочется... да и можется наверняка :)

Добавлено: Сб июл 12, 2008 21:33:52
AG
Вот к примеру вывод памяти программы на LCD дислей от МЕЛТ, вначале выводится адрес байта программы, затем, то что в нем сидит

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

DbgWritePMem:
	ldi		ZH,0x00
	ldi		ZL,0x00
	Loop_Str:
		sbi		PortA,1
		ldi		Counter,100
		rcall	Delay5ms
		mov		DATA,ZL
		rcall	LCDWriteByteNum
		ldi		Counter,100
		rcall	Delay5ms
		cbi		PortA,1
		ldi		Counter,100
		rcall	Delay5ms
		sbi		PortA,0
		lpm
		mov		DATA,R0
		rcall	LCDWriteByteNum
		inc		ZL
		ldi		Counter,100
		rcall	Delay5ms
		cbi		PortA,0
		cpi		ZL,0x1B
		brne	Loop_Str
	ret
Вот команда вывода одного байта памяти на LCD в двоичном коде.
Привожу на всякий случая, хотя проверял ее с константой все работает нормально.

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

LCDWriteByteNum:
	push	DATA
	ldi		DATA,0xC8
	rcall	LCDWriteCmd
	ldi		Counter,8
	pop		DATA
	Loop_LCDWBN:
		push	DATA
		andi	DATA,0x80
		swap	DATA
		lsr		DATA
		lsr		DATA
		lsr		DATA
		subi	DATA,0xD0
		rcall	LCDWriteData
		pop		DATA
		lsl		DATA
		dec		Counter
		brne	Loop_LCDWBN
	ret

Добавлено: Сб июл 12, 2008 22:03:56
ARV
во-первых: вы уверены, что все предыдущие команде LPM строки не портят указатель Z?
во-вторых: я вообще не вижу загрузки в указатель Z какого-то осмысленного значения. обычно в программе должно быть нечто типа

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

str:   .db   'кукареку',0
а потом где-то еще что-то типа

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

ldi ZL, low(str)
ldi ZH, high(str)
не наблюдаю такого...
в-третьих: адресация внутри сегмента кода у AVR идет по словам, т.е. по 2 байта сразу, а адресация LPM - побайтная. поэтому в вышеупомянутом примере правильно было бы писать (если б вы так написали)

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

ldi ZL, low(str*2)
ldi ZH, high(str*2)

Добавлено: Сб июл 12, 2008 23:08:55
AG
1) Полностью уверен.
Вот код процедуры записи на экран LCD (входит в процедуру записи байта на экран в двоичном формате, которую приводил выше), как видно, в ней ZL нигде не участвует

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

LCDWriteData:
	rcall	LCDWait
	sbi		LCDContPort,A0
	rcall	LCDWriteByte
	ret
LCDWriteByte:
	cbi		LCDContPort,RW
	out		LCDDataPort,DATA nop nop nop nop 
	sbi		LCDContPort,E nop nop nop nop
	cbi		LCDContPort,E nop nop nop nop
	ret	
2) Осмысленными значения должны быть комманды в двоичной форме
Процедура DbgWritePMem: процедура считывает байт памяти и выводит его на экран LCD. (ВСЕ ЗАДЕРЖКИ, для того чтобы посмотреть байт находящийся в памяти программы удалены, оставил только все самое необходимое), я написал такую процедуру только для того чтобы ПРОВЕРИТЬ работу lpm:

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

DbgWritePMem:
//Устанавливаем на начало памяти программы указатель:
   ldi      ZH,0x00
   ldi      ZL,0x00 
 Loop_Str:
//Выводим адрес байта
      mov      DATA,ZL
      rcall   LCDWriteByteNum
//Загружаем в регистр R0 содержимое байта
      lpm
//Выводим байт хранящийся в памяти
      mov      DATA,R0
      rcall   LCDWriteByteNum
//Увеличиваем значение указателя на единичку (переходим на следующий байт)
      inc      ZL
//Если ZL не равен 0x1B, то возвращаемся в начало цикла
      cpi      ZL,0x1B
      brne   Loop_Str
   ret
То что действительно должно храниться в памяти программы проверял в протеусе, а также сравнил протеус с .hex файлом.
Однако на LCD были только 11111111

3) Я знаю про, то что команда занимает одно слово, а не байт, но в любом случае, если бы я попадал не на то значение в памяти, врядли такое может быть, что lpm ВСЕГДА возвращала 0xFF или 0b11111111.

Добавлено: Сб июл 12, 2008 23:29:58
ARV
вообще-то LPM работает, как часы - сами понимаете :) а вот что у вас не так - непонятно. выходит,

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

      mov      DATA,ZL 
      rcall   LCDWriteByteNum 
выводит 0, а следующий после LPM вывод - уже все единички?

Добавлено: Вс июл 13, 2008 00:23:53
AG
Я понимаю, что lpm обязан работать как часы :)

Я извиняюсь, но я неправильно выразился про все 1.

На LCD вначале выводится адрес байта, то есть вначале:
0000 0000
Потом (должен быть вывод байта хранящегося в памяти программы), однако на экране:
1111 1111

Далее
0000 0001
За ним
1111 1111
И т.д.
....Может, что с чипом случилось.... но вроде я его не сильно не мучил...

И еще, вначале в программе была записана команда lpm следующим образом:
lpm DATA,Z (то есть сразу загрузить в DATA по адресу Z из памяти программы)
Когда я понял, что проблемы начинаются имено после lpm.
Заменил следующим образом:
lpm
mov DATA,R0
Я даже вначале обадывался - все заработало, но убрав команды которые использовал для поиска неисправности (типа включения светодиода) и заново перепрошив контроллер - все сново перестало работать. Обратно поменяв на lpm DATA,Z результато не дало...

Прошиваю STK200 с помощью программы AVReal.

Возможны такие глюки из не правильно прошитых фьюзов?

Вот содержание батника:
E:\AVReal\avreal32.exe +mega16 -%% -p1 -as -o0 -ew G:\Projects\AVRStudio\LCD-Controller\LCD-Controller.hex -n
pause=null

Извините, что сразу не привел все "историю болезни", думал может "вылечат"....

Добавлено: Вс июл 13, 2008 13:35:29
mrFox
если хочешь проверить - возьми WinAVR
и воспользуйся например strcpy_P, strncpy_P
они выводят строку в буфер и выведи на дисплей
сразу станет ясно, что глючит МК или руки

выриант 2 - покупаешь новую мегу ...

PS
и сделай полную таблицу прерываний
а то ты выставляешь бит TWIE
и если включишь прерывание то :)))

Добавлено: Вс июл 13, 2008 13:57:30
AG
Я тоже думаю съездить купить новую мегу, и попробую небольшой отрезок кода на CAVR написать и посмотреть, что будет, но это позже.

Что интересно... с утра включил это чудо устройство... не чего не менял в коде=)... прошил... и все заработало... чудеса!

А вообще мега могла начать глючить от того, что к примеру, порт на котором установлен высокий уровень замкнуть на землю?

PS: A TWEI забыл убрать ), хотел в начале делать с прерываниями.

Добавлено: Пн июл 14, 2008 00:32:07
mrFox
AG
А вообще мега могла начать глючить от того, что к примеру, порт на котором установлен высокий уровень замкнуть на землю?

врядли - у меня в такой ситуации mega32 пробыла более 5 минут без каких-либо последствий - в таком режиме ножка скорее всего будет стабилизатором тока
а вот статикой mega32 убилась - слегка щелкнуло и усе :(
а FT232 оказалось не любит переплюсовки питания :?