реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Прошу помощи
Maks448
сообщение Feb 13 2007, 13:23
Сообщение #1





Группа: Новичок
Сообщений: 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 ;зациклить программу
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Feb 13 2007, 13:33
Сообщение #2


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Банальный вопрос - в AVRStudio пробовали просимулировать?
Go to the top of the page
 
+Quote Post
Leen
сообщение Feb 13 2007, 14:16
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 172
Регистрация: 5-08-06
Из: Владивосток
Пользователь №: 19 343



Во-первых: а как это 9216/4=4608? Калькулятор и уроки математики говорят другое.. Во-вторых, а чем Вы смотрите, сколько приходит из выхода АВР? И еще: похоже, теряется ноль.. Вы не могли скорости портор приемника и передатчика разными сделать?
Еще могу посоветовать сделать эхо: поллим приемник, затем когда приняли, тут же кидаем обратно.
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 14:26
Сообщение #4


Гуру
******

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Leen
сообщение Feb 13 2007, 14:42
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 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:
Нда, че-то я гоню...
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 14:48
Сообщение #6


Гуру
******

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



Цитата(Leen @ Feb 13 2007, 14:42) *
Т.е. первым выведенным числом будет 9215, так??? Или у мну глюки?
А как Вы тогда ожидаете, что прога выведет удвоенное содержимое Z?
Объясните, пожалуйста.
И по-прежнему вопрос: а чем смотрите?
2 rx3apf:
Нда, че-то я гоню...

Или не выспался wink.gif Программа не удвоенное содержимое Z пытается выводить, а само содержимое. По два байта на каждую иттерацию. "Удвоенное" относилось к числу байтов на выходе UART...
Go to the top of the page
 
+Quote Post
GDI
сообщение Feb 13 2007, 15:04
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Так он же и передает содержимое, собственно , регистра и надо посмотреть что же он передает.. т.е. не количество байт посчитать, а посмотреть что в этих байтах содержится, т.е он просто числа через 2(4) считает или на каком-то числе просто останавливается.. а еще регистр Z может работать с автоинкрементом и -декрементом... может это и происходит?


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 15:25
Сообщение #8


Гуру
******

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



Цитата(GDI @ Feb 13 2007, 15:04) *
Так он же и передает содержимое, собственно , регистра и надо посмотреть что же он передает.. т.е. не количество байт посчитать, а посмотреть что в этих байтах содержится, т.е он просто числа через 2(4) считает или на каком-то числе просто останавливается.. а еще регистр Z может работать с автоинкрементом и -декрементом... может это и происходит?

Если такое происходит - автор здорово замаскировал соответствующие команды wink.gif

Короче, все сходятся в одном - надо смотреть, что реально передается...
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 13 2007, 15:43
Сообщение #9


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".


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 16:07
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 13 2007, 18:22
Сообщение #11


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


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 19:20
Сообщение #12


Гуру
******

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 13 2007, 19:52
Сообщение #13


Ambidexter
*****

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



Был не прав. Признаю. Флаг Z в команде cpc формируется не так, как в команде cpi. Флаг С ни при чём.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 13 2007, 20:15
Сообщение #14


Гуру
******

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



Цитата(=GM= @ Feb 13 2007, 19:52) *
Был не прав. Признаю. Флаг Z в команде cpc формируется не так, как в команде cpi. Флаг С ни при чём.

BTW, то же касается и других команд, предназначенных для многоразрядной арифметики и работающих с результатом предыдущей команды. Поэтому вполне законна конструкция subi zl,0 sbci zh,0
Go to the top of the page
 
+Quote Post
Maks448
сообщение Feb 14 2007, 12:44
Сообщение #15





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



Друзья! Дико извиняюсь за глупый, видимо вопрос. Глюк оказался не в AVRе, а в самопальной программке, ловившей байты на компутере. Вчера скачал Advanced Serial Port Monitor, загрузил им файл - все как в аптеке - один к одному, так что уж извиняйте.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 18:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01521 секунд с 7
ELECTRONIX ©2004-2016