Модераторы: PILOT, ManiaK, Mazzi
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вычисляемый переход, Как увеличить значение PC ? 
:(
    Опции темы
fol
Дата 30.10.2006, 03:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Общий привет.
Извиняйте за такой вопрос, но перерыв кучу исходников так и не нашел
ответа. Пишу (а точнее перписываю под AVR) драйвер LED индикатора,
и застопорилось все на выборке данных из таблицы. То есть в зависимости
от определенной константы в буфере происходит выборка данных
из таблицы. В старых своих прогах под PIC контроллер, все решалось
очень просто и изящно:

   addwf      PC,F        ; Увеличить значение PC на величину лежащую в W

После этого голова программы скакала на нужное место в таблице.
С AVR... застопорилось.
Я конечно использовал другой способ, когда программа последовательно 
сравнивает знчение буфера и констант, и таким образом находит 
нужную позицию в таблице. Но так все это не красиво.
Даже когда производим вывод чисел от 0 до 9 имеем 10 позиций-меток.
А если нужно выбирать еще символы и т.д. вообще все это разрастается.

Подскажите пожалуйста, как решается задача.
Дайте формулу на ASM, или хоть направление.

Плиз. Пжалста. Буду благодарен, правда... на хлеб не намажешь.
PM MAIL   Вверх
Ivan.
Дата 30.10.2006, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



В AVR контроллерах регистр PC не доступен, я тебе могу предложить IJMP, переход по регистру Z. Если тебе надо скокнуть относительно какойто позиции, то ты должен знать какую нибудь точную позицию, относительно каторой известен здвиг. Если ты и этого не знаешь, то можно извратиться так: скокнуть RCALL на следующую команду - ты в стеке получишь типо PC. Выдави из стека информацию, измени, вдави обратно и сделай RET (изврат, а что делать).
Вопрос, ты пишешь на чистом ASM или используешь ассемблерные вставки в C-шный код?

Это сообщение отредактировал(а) Ivan. - 30.10.2006, 17:24


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
PILOT
Дата 30.10.2006, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


производство
****


Профиль
Группа: Модератор
Сообщений: 2724
Регистрация: 4.4.2002
Где: москва

Репутация: 20
Всего: 54



Ivan в принципе прав, но.

Задача 
case MyVar of
1:
2:
3:
...
N:
решается действительно с помощью IJmp, но других применений кроме как в машине состояний я пока этой команде не нашел.
В вашем случае, я так понял, нужно выводить двоичное число в десятиричном виде на индикатор.
В такой постановке делается примерно так:
1) вы находите десятичное представление, т.е. переводите то что нужно отобразить в так называемый BCD формат (можно и не в сжатый)
2) создаете в памяти программ таблицу соответствия десятичного числа семисегментному (или любому другому коду) отображению.
3) после определения какие цифры отображать (т.е. после перевода в BCD) вы смещаетесь по этой созданной таблице на номинал цифры (например, если ноль, то не смещаетесь, а значит отобразится символ сообтетвующий нулю по нулевому смещению).
4) повторяете пункт 3 до тех пор пока все разряды не отобразятся.

СУВ.


--------------------
тут могла быть Ваша реклама...
PM MAIL WWW ICQ   Вверх
fol
Дата 31.10.2006, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Привет. Спасибо что ответили.
Сейчас как раз занимаюсь моделированием всех этих вариантов.
То есть имеем два основных, возможных варианта вычисляемого 
перехода, в рамках камня AVR.
Резюме:
1. Вариант. "Ivan"
Это косвенная загрузка счетчика команд через регистр Z.
Кстати это не такой уж изврат а нормальный подход, по моему на 
такой способ где то была ссылка в фирменном даташите на Atmega16,
которую я сейчас юзаю на макете. Основной недостаток,
нырнув в этот тоннель, надо точно знать координаты выхода из тоннеля.
А это всегда вычисления, причем вручную.
А вот попользоваться услугой стека, это очень перспективно.
2. Вариант. "PILOT"
Попробую наиболее подробно поработать с вариантом создания таблиц.
Подозреваю что при больших массивах (вборка большого к-ва ячеек)
вариант табличного размещения будет наиболее компактен,
и возможно даже более визуально нагляден. Но так же подозреваю
что этот вариант будет иметь серьезный недостаток. А именно 
нужно всегда быть очень внимательным при размещении таблицы в памяти
чтобы ни она никуда не "уползла", ни на нее никто не "наехал".
Это весьма проблематичной, с моей философией письма, вариант. 
Я предпочитаю, составление полностью готовых, снаряженных, 
и универсальных модулей. Это в особенности актуально при смене контроллера. 

Дело в том что я стараюсь составлять даже простейшую программу,
из набора подпрограмм, модулей, по типу конструктора. Естественно
каждый модуль должен перед эти пройти все испытания, причем во всех
возможных режимах и т.д. То есть в каждом модуле я должен быть уверен.
Если к этому подойти философски, это можно представить как 
язык программирования сверх высокого уровня, то есть оперируем 
глобальными величинами, ну как наше правительство. А я президент, ха.
По загрузке, использовании памяти проца это конечно
не эффективно. Но с точки зрения времени на создание проекта,
и отладку, это оправдано. К тому же последнее время не помню когда
ограничивала память. Если надо больше, взял другой кристалл, и все.
Так вот, в стремлении создать очередной такой модуль, как я называю
его, драйвер LED индикатора, я пытаюсь изучить все досконально.
Зато потом можно забыть, и заниматься другим. Готовый модуль 
нужно только врезать в основную прогу, прописывать его там и т.д.

Вначале я применил метод последовательного перебора:

SELECT_SYMBOL_LINE:

    inc    Count            ; Увеличить счетчик разрядов на 1 (+1)

   ;----- В регистре Temp находится двоично-десятичное число -------
   ;----- В регистре Count находится номер текущего разряда --------


   ;-------------------- ВКЛЮЧИМ  СЕГМЕНТЫ ----------------------------
   ;----- Выберем сегменты соответствуюшие числу в регистре Temp ------

    cpi    Temp, 0               ; Если содержимое Temp = КОНСТАНТА
    breq   SYMBOL_0         ; то производим выборку SYMBOL_0.
    cpi    Temp, 1               ; Если содержимое Temp = КОНСТАНТА
    breq   SYMBOL_1         ; то производим выборку SYMBOL_1.

               ; НУ И ТАК ДАЛЕЕ

Вот какая махина.!!!
Ни красоты ни изящества.
Я много просмотрел прог в инете, ну там всякие частотомеры, вольтметры,
и везде (вроде) народ пользует этот алгоритм.

Опять че то меня понесло.
Ладно, у меня точно что то с головой.
Спасибо всем, будем работать.

"А у вас нет, точно такого же, но с перламутровыми пуговицами?
 Нет? Будем искать..."
PM MAIL   Вверх
PILOT
Дата 31.10.2006, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


производство
****


Профиль
Группа: Модератор
Сообщений: 2724
Регистрация: 4.4.2002
Где: москва

Репутация: 20
Всего: 54



Рассказываю!

Берем и делаем так

          LdI     ZL, low(lCaseLabels<<1);
          LdI     ZH, high(lCaseLabels<<1);
          AdIW  ZL, R16;
          LPM
          MovW ZL,R0
          IJmp
Symbol1:
{commands}
          RJmp lSymExt
Symbol2:

Symbol3:


SymbolN:

lSymExt:

{commands after case}

RJmp      lMainLoop;

lCaseLabels: .dw Symbol1, Symbol2, Symbol3,..., SymbolN;


За компилируемость не ручаюсь, но суть должна быть ясна smile

СУВ.


--------------------
тут могла быть Ваша реклама...
PM MAIL WWW ICQ   Вверх
PILOT
Дата 31.10.2006, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


производство
****


Профиль
Группа: Модератор
Сообщений: 2724
Регистрация: 4.4.2002
Где: москва

Репутация: 20
Всего: 54



На таблицу никогда ничего не наедет, за этим следит линкер. Так что делай что хочешь smile

СУВ.


--------------------
тут могла быть Ваша реклама...
PM MAIL WWW ICQ   Вверх
fol
Дата 31.10.2006, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Ну спасибочки. 
Теперь минимум на три дня засяду. Пока все переварится,
отложиться и сформируется... Пока щетина не вылезет.
Это примета такая, как только начал врубаться, это значит
прошло около трех, четырех дней. Все это время как бы в отключке.
Все же не совершенен мозг человека, (или мой? тьфу через левое плечо)
необъятное не обнимается.
А потом, однажды, вдруг... выходишь на улицу, и, нифига себе...
Облака летят, листья падают. И где это меня носило? А нигде.
Вычисляемый переход постигал, понимашь, это не хухры мухры.
А за это время столько облаков улетело...
И че в жизни САМОЕ. ?

Всем спасибо!!!.
Временно отключаюсь. 
Потрудимся на благо себя.
PM MAIL   Вверх
Ivan.
Дата 3.11.2006, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Если рассмотреть задачу глобальней, то я так понял, что тебе надо управлять сегментным индикатором (скорей всего 7-ми сегментным).
Чем тебе не подошел классический способ управления 7-ми сегментным индикатором?
например дано:
5 7-ми сегментных индикаторов, расположенных в ряд.
Код

#define MAX_SYMBOLS 5
#define SEGMENTS PORTA
#define SEG_A  PORTA0
#define SEG_B  PORTA1
#define SEG_C  PORTA2
#define SEG_D  PORTA3
#define SEG_E  PORTA4
#define SEG_F  PORTA5
#define SEG_G  PORTA6
#define SEG_DP PORTA7
#define SYMBOLS PORTB
#define SYMB0 PORTB0 // крайний правый
#define SYMB1 PORTB1
#define SYMB2 PORTB2
#define SYMB3 PORTB3
#define SYMB4 PORTB4 // крайний левый
#define MASK_DOT 0x80
char PROGMEM SymbTab[] = {0x00, 0x00, ..., MASK_DOT, ...}; // Таблица кодировки символов, расположенная в памяти кода
char Text[MAX_SYMBOLS]; // Выводимая строка
char Dots; // Маска точек (DP)
char Pos = 0;
char Mask = 1;
//---------------------------------------------------------------------------
void mSec(){
    SEGMENTS = 0; // Отключаем сегменты, чтобы символы не просвечивали на соседних элементах
    SYMBOLS = SYMBOLS & (0xFF << MAX_SYMBOLS) | Mask; // Меняем символ
    char Segments = pgm_read_byte(Text[Pos]); // Берем эскиз символа
    if (Dots & Mask) // Добавляем точку
        Segments |= MASK_DOT;
    SEGMENTS = Segments; // Выводим символ
    Pos++; // Увеличиваем позицию
    Mask <<= 1; // Смещаем маску
    if (Pos == MAX_SYMBOLS){ // Если позиция вышла за пределы
        Pos = 0; // Переходим на следующий круг
        Mask = 1;
    }
}
//---------------------------------------------------------------------------
void Text(const char *text){
    Flag = 1; // Помечаем, что функция уже занята
    Dots = 0x00; // Сбрасываем все точки
    uchar i = 0; // Позиция символа в 0
    while (*text){ // Циклируем пока есть текст
        if (*text == '.'){ // Если точка
            if (i == 0 || Dots & (1 << (i - 1))) // Если это первый символ или точка уже есть
                Text[i++] = ' '; // добавляем пробел
            Dots |= 1 << (i - 1); // выставляем точку
        }
        else { // если не точка
            if (i == MAX_SYMBOLS) // Если места в строке больше нет
                break; // Выходим из цикла
            Text[i] = *text; // Добавляем символ
            i++; // Увеличиваем позицию
        }
        text++; // Переходим на следующий символ
    }
    while (i < MAX_SYMBOLS){ // Циклируем если текст короче чем поле
        Text[i] = ' '; // Рисуем пробелы
        i++; // Увеличиваем позицию
    }
    Flag = 0; // Сбрасываем флаг занятости функции
}
//---------------------------------------------------------------------------
void Dec(short Value, uchar Dot){
    Flag = 1; // Помечаем, что функция уже занята
    char *text = Text; // Берем адрес строки
    uchar size = MAX_SYMBOLS; // Берем максимальный размер строки
    Dots = 0; // Сбрасываем точки
    if (Value < 0){ // Если число отрицательное
        *(text++) = '-'; // Рисуем знак "-"
        size--; // Уменишаем оставшийся размер
        Value = abs(Value); // Сбрасиваем знак числа
    }
    uchar j = size; // Берем оставшийся размер строки
    while (Value || Dots == 0 || j){ // Циклируем пока есть число или нет ниодной точки
        uchar S = Value % 10; Берем младшую цифру
        for (int i = size - 1; i > 0; i--) // Смещаем текст в право
            text[i] = text[i - 1];
        if (Value || Dots == 0) // Если число еще осталось или еще нет ни одной точки
            *text = '0' + S; // Рисуем цифру
        else { // Иначе если число уже кончилось и есть точка
            if (Text != text){ // Если есть возможность - смещаем знак "-" в право
                text--;
                text[1] = '-';
            }
            *text = ' '; // Рисуем пробел
        }
        if (Dots & 1) // Если есть точка в нулевой позиции
            if (Dots == 1) // Если кроме этой точки ничего нет
                Dots = (Dots << 1) | 1; // Рисуем первое переполнение
            else // Иначе
                Dots = ((Dots & ~1) << 1) | 1; // Добавляем переполнение
        else // Если нет точки в нулевой позиции
            Dots >>= 1; // Смещаем точки
        Value /= 10; // Вырезаем из числа младший разряд
        if (Dot == 0) // Если текущая позиция равна нулю
            Dots |= 1 << (size - 1); // Значит пора ее рисовать
        Dot--; // Уменьшаем позицию точки
        if (j) // Если еще осталось место в строке
            j--; // Уменьшаем остаточное место
    }
    uchar D = 0; // Временная переменная маски точек
    for (uchar i = 0; i < MAX_SYMBOLS; i++){ // Переворачиваем маску точек
        D <<= 1;
        D |= Dots & 1;
        Dots >>= 1;
    }
    Dots = D; // Сохраняем маску точек
    Flag = 0; // Сбрасываем флаг занятости функции
    // Без бутылки не разобраться !!!
}
//---------------------------------------------------------------------------

ну и так далее.
Функция Dec выводит число в десятичном формате с точкой в позиции Dot. Если разряды после запятой не влезают в строку, функция уменьшает точность выводимого числа. Если целая часть числа тоже не влезает функция выводит закодированную ошибку в виде (например надо вывести число 12345 с точкой после первого разряда на трех сегментах) "12.3." указывая, что один разряд не влез. второй пример, если надо вывести число 12345 с Dot = 0 => "1.23." - невлезло 2 символа. конечно это необходимо только если число действительно может не влезти на дисплей, например при дисплее величиной в 3 разряда. А вообще по логике программы таких чисел допускать впринципе нельза.

Если хочешь, могу выложить полную версию моей компоненты TLed7_2 - Это динамическая компонента (class) для управления семисегментным двухцветным индикатором с возможность автоматического мигания.

Это сообщение отредактировал(а) Ivan. - 3.11.2006, 22:53


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)"
PILOT ManiaK
UniBomb Mazzi

На данный раздел помимо Правил форума распространяются текже следующие правила:


  • Прежде чем создать тему воспользуйтесь поиском или посмотрите в faq. Возможно на форуме уже есть ответ на ваш или близкий к вашему вопрос.
  • В заголовке темы в квадратных скобках обозначьте используемое семейство микроконтроллера: [avr],[pic],[arm].
  • При создании темы с вопросом указывайте участок кода с ошибкой, версию компилятора, схемы подключения, fuse биты и прочие данные, которые помогут найти правильный ответ. Для форматирования текста программ используйте кнопку код.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Для флуда, просьб выполнить задание, поиска партнёров или исполнителей существуют свои разделы.
  • Если вы заметили несовместимое с правилами сообщение, то можете уведомить об этом модератора раздела нажав кнопку Репорт у соответствующего сообщения.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема »


 




[ Время генерации скрипта: 0.0494 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.