|
Прошу помощи |
|
|
|
Feb 13 2007, 13:23
|
Группа: Новичок
Сообщений: 2
Регистрация: 13-02-07
Пользователь №: 25 298

|
Уважаемые форумчане, объясните, пожалуйста, "чайнику" в чем прикол (или прокол?). Программка простая, как два пальца, по идее должна вывести в порт RS232 удвоенное количество байтов от числа, находящегося в счетчике (регистр Z). Реально же выводится 4608, т.е. четвертая часть. Где я допустил ошибку? Пробовал также на Mega8 - результат тот же.
.include "2333def.inc" .def Tmp =r16 .cseg .org 0 reset: clr Tmp out UBRRH,Tmp ldi Tmp,$19 out UBRRL,Tmp ;Настройка скорости СОМ-порта
clr Tmp out UCSRA,Tmp ldi Tmp,$18 out UCSRB,Tmp ;Настройка UART
in Tmp,WDTCR ori Tmp,$18 out WDTCR,Tmp clr Tmp out WDTCR,Tmp ;Отключение WDT
ldi Tmp,$20 out DDRC,Tmp ;Определение линии порта С как выход cbi PortC,5 ;Включить светодиод ldi ZL,Low(9216) ldi ZH,high(9216) ;Загрузка счетчика байтов Loop: subi ZL,1 sbci ZH,0 ;Декремент счетчика Wait1: sbis UCSRA,UDRE ;Ожидание готовности UART rjmp Wait1 out UDR,ZH ;Вывод старшего байта счетчика Wait2: sbis UCSRA,UDRE ;Ожидание готовности UART rjmp Wait2 out UDR,ZL ;Вывод младшего байта cpi ZL,0 ldi Tmp,0 cpc ZH,Tmp ;Проверка счетчика на 0 brne Loop ;Не 0 - возврат sbi PortC,5 ;Иначе - выключить светодиод и Cycle: rjmp Cycle ;зациклить программу
|
|
|
|
|
 |
Ответов
|
Feb 13 2007, 15:43
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Maks448 @ Feb 13 2007, 10:23)  Уважаемые форумчане, объясните, пожалуйста, "чайнику" в чем прикол (или прокол?). Программка простая, как два пальца, по идее должна вывести в порт RS232 удвоенное количество байтов от числа, находящегося в счетчике (регистр Z). Реально же выводится 4608, т.е. четвертая часть. Где я допустил ошибку? Пробовал также на Mega8 - результат тот же. 1) У вас есть одна логическая неувязочка вот здесь
Код cpi ZL,0 ldi tmp,0 cpc ZH,tmp ;Проверка счетчика на 0 brne loop ;Не 0 - возврат
Команда "cpi ZL,0" никогда не установит бит переноса. Что вы тогда проверяете командой "cpc ZH,tmp"? Только наличие 0 в ZH, но ведь в младшем регистре ZL еще останется 0xFF значений. Как-то некозяво выходит. Т.е. должно передаваться 2*Z-0xFF байт, а не удвоенное значение. 2) Логичнее было бы поставить команду "brne loop" после команды "cpi ZL,0".
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 13 2007, 16:07
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(=GM= @ Feb 13 2007, 15:43)  Команда "cpi ZL,0" никогда не установит бит переноса. Что вы тогда проверяете командой "cpc ZH,tmp"? Только наличие 0 в ZH, но ведь в младшем регистре ZL еще останется 0xFF значений. Тормозим ? Команда cpi zl,0 управляет не только C, но и Z, а команда cpc использует значение Z до команды. Тут все правильно, хотя не самое компактное решение для проверки на 0.
|
|
|
|
|
Feb 13 2007, 18:22
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(rx3apf @ Feb 13 2007, 13:07)  Цитата(=GM= @ Feb 13 2007, 15:43)  Команда "cpi ZL,0" никогда не установит бит переноса. Что вы тогда проверяете командой "cpc ZH,tmp"? Только наличие 0 в ZH, но ведь в младшем регистре ZL еще останется 0xFF значений.
Тормозим? По-моему, это вы поспешили..и меня немного посмешили(:-) Цитата(rx3apf @ Feb 13 2007, 13:07)  Команда cpi zl,0 управляет не только C, но и Z, а команда cpc использует значение Z до команды. Тут все правильно, хотя не самое компактное решение для проверки на 0. 1) Команда "cpi zl,0" в программе автора топика просто-напросто не нужна, т.к. результаты проверки нигде не используются. 2) К тому же, команда "cpi zl,0" НИКОГДА не установит бит переноса, который автор пытается использовать далее в команде "cpc ZH,tmp". 3) "...а команда cpc использует значение Z до команды". Сами-то поняли, что сказали(:=)? Это НЕПРАВИЛЬНАЯ проверка на 0. 4) Вот вам простой пример. На начало цикла Loop пришли к моменту, когда zh=1, zl=0x00. Вычитаем 1, получаем zh=0, zl=0xFF, передаем два байта, с Су=0 доходим до команды "cpc ZH,tmp", проверяем zh на равенство 0, да, zh=0, значит не возвращаемся на метку Loop, завершаем цикл. ПОЗВОЛЬТЕ, НО zl=0xFF, т.е. ОСТАЛОСЬ ПЕРЕДАТЬ 255 БАЙТ. Однако, цикл ОШИБОЧНО завершен. 5) Для проверки двухбайтного счетчика на 0 должна быть примерно такая конструкция
Код cpi zh,0 ;старший байт счетчика=0? brne loop ;нет cpi zl,0 ;младший байт счетчика=0? brne loop ;нет
Хотя можно написать и попроще, скажем так
Код sbiw zl,1 ;счетчик=0? brne loop ;нет,
совместив декремент и проверку на 0
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 13 2007, 19:20
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(=GM= @ Feb 13 2007, 18:22)  По-моему, это вы поспешили..и меня немного посмешили(:-) "Над кем смеетесь ? Над собой смеетесь !" © классик. Цитата(=GM= @ Feb 13 2007, 18:22)  1) Команда "cpi zl,0" в программе автора топика просто-напросто не нужна, т.к. результаты проверки нигде не используются. В самом деле ? Цитата(=GM= @ Feb 13 2007, 18:22)  2) К тому же, команда "cpi zl,0" НИКОГДА не установит бит переноса, который автор пытается использовать далее в команде "cpc ZH,tmp". А нам очень нужен этот бит переноса ? Для команды breq ? Цитата(=GM= @ Feb 13 2007, 18:22)  3) "...а команда cpc использует значение Z до команды". Сами-то поняли, что сказали(:=)? Это НЕПРАВИЛЬНАЯ проверка на 0. Это вполне правильная по сути, хоть и не самая рациональная, проверка на 0. В предложении, пожалуй, надо было добавить "использует предыдущее значение Z". Или просто процитирую даташит: R7 •R6• R5• R4 •R3 •R2 •R1• R0 •Z Previous value remains unchanged when the result is zero; cleared otherwise. При копировании, правда, потерян символ надчеркивания (инверсия). Цитата(=GM= @ Feb 13 2007, 18:22)  4) Вот вам простой пример. На начало цикла Loop пришли к моменту, когда zh=1, zl=0x00. Вычитаем 1, получаем zh=0, zl=0xFF, передаем два байта, с Су=0 доходим до команды "cpc ZH,tmp", проверяем zh на равенство 0, да, zh=0, значит не возвращаемся на метку Loop, завершаем цикл. ПОЗВОЛЬТЕ, НО zl=0xFF, т.е. ОСТАЛОСЬ ПЕРЕДАТЬ 255 БАЙТ. Однако, цикл ОШИБОЧНО завершен. Настоятельно рекомендую ознакомиться с описанием системы команд AVR, дабы не упорствовать в своих заблуждениях, не смущать новичков и не смешить понимающих. Цитата(=GM= @ Feb 13 2007, 18:22)  5) Для проверки двухбайтного счетчика на 0 должна быть примерно такая конструкция
Код cpi zh,0 ;старший байт счетчика=0? brne loop ;нет cpi zl,0 ;младший байт счетчика=0? brne loop ;нет
Крайне нерационально. Как надо - я написал в одном из первых писем в этой ветке.
Сообщение отредактировал rx3apf - Feb 13 2007, 19:23
|
|
|
|
Сообщений в этой теме
Maks448 Прошу помощи Feb 13 2007, 13:23 IgorKossak Банальный вопрос - в AVRStudio пробовали просимули... Feb 13 2007, 13:33 Leen Во-первых: а как это 9216/4=4608? Калькулятор и ур... Feb 13 2007, 14:16 rx3apf Цитата(Maks448 @ Feb 13 2007, 13:23) Уваж... Feb 13 2007, 14:26 Leen 2 Maks448:
Цитатаldi ZL,Low(9216)
ldi ZH,high(9216... Feb 13 2007, 14:42 rx3apf Цитата(Leen @ Feb 13 2007, 14:42) Т.е. пе... Feb 13 2007, 14:48 GDI Так он же и передает содержимое, собственно , реги... Feb 13 2007, 15:04 rx3apf Цитата(GDI @ Feb 13 2007, 15:04) Так он ж... Feb 13 2007, 15:25     rx3apf Цитата(=GM= @ Feb 13 2007, 19:52) Был не ... Feb 13 2007, 20:15      Maks448 Друзья! Дико извиняюсь за глупый, видимо вопро... Feb 14 2007, 12:44
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|