|
|
  |
Прошу помощи |
|
|
|
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, 14:26
|
Гуру
     
Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047

|
Цитата(Maks448 @ Feb 13 2007, 13:23)  Уважаемые форумчане, объясните, пожалуйста, "чайнику" в чем прикол (или прокол?). Программка простая, как два пальца, по идее должна вывести в порт RS232 удвоенное количество байтов от числа, находящегося в счетчике (регистр Z). Реально же выводится 4608, т.е. четвертая часть. Где я допустил ошибку? Пробовал также на Mega8 - результат тот же. Безотносительно проблемы - декремент 16-битного счетчика красивее делать командой sbiw, а проверку на 0 - "mov temp,ZH or temp,ZL" или парой sbiw+adiw, или subi ZL,0 + sbci ZH,0 А что до логики - на первый взгляд все правильно. Надо бы глянуть терминалкой (с хексом) - а что же, собственно, реально ушло ? Цитата(Leen @ Feb 13 2007, 14:16)  Во-первых: а как это 9216/4=4608? Калькулятор и уроки математики говорят другое.. Во-вторых, а чем Вы смотрите, сколько приходит из выхода АВР? И еще: похоже, теряется ноль.. Вы не могли скорости портор приемника и передатчика разными сделать? Четвертая часть от ожидаемого. А ожидается удвоенное от счетчика, так что математика не возражает. И с учетом кратности, вариант с разной скоростью портов представляется малоправдоподобным - что-то уж очень подозрительно кратные (если и в самом деле так). Цитата(Leen @ Feb 13 2007, 14:16)  Еще могу посоветовать сделать эхо: поллим приемник, затем когда приняли, тут же кидаем обратно. И еще в таких случаях помогает вывод куда-нибудь какого-нибудь строб-сигнала, чтобы посмотреть скопом. Сразу видно и периоды, и общую длительность посылки. Если, конечно, есть скоп...
Сообщение отредактировал rx3apf - Feb 13 2007, 14:32
|
|
|
|
|
Feb 13 2007, 14:42
|
Частый гость
 
Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343

|
2 Maks448: Цитата ldi ZL,Low(9216) ldi ZH,high(9216) ;Загрузка счетчика байтов: Z = 9216 (0x2400); Loop: subi ZL,1 sbci ZH,0 ;Декремент счетчика: Z = 9215 (0x23FF) Wait1 out UDR,ZH ;Вывод старшего байта счетчика (0x23) Wait2 out UDR,ZL ;Вывод младшего байта (0xFF) brne Loop ;Не 0 - возврат Т.е. первым выведенным числом будет 9215, так??? Или у мну глюки? А как Вы тогда ожидаете, что прога выведет удвоенное содержимое Z? Объясните, пожалуйста. И по-прежнему вопрос: а чем смотрите? 2 rx3apf: Нда, че-то я гоню...
|
|
|
|
|
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
|
|
|
|
|
Feb 14 2007, 12:44
|
Группа: Новичок
Сообщений: 2
Регистрация: 13-02-07
Пользователь №: 25 298

|
Друзья! Дико извиняюсь за глупый, видимо вопрос. Глюк оказался не в AVRе, а в самопальной программке, ловившей байты на компутере. Вчера скачал Advanced Serial Port Monitor, загрузил им файл - все как в аптеке - один к одному, так что уж извиняйте.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|