Перейти к содержанию
    

Вопрос по пикам и HITECH PICC

Хочу простого. Есть функция, которая в зависимости от состояния автомата, реализует те или иные действия и переводит автомат в другое состояние.

На MPASM сделал так:

ReadUserInput:
       movlw high ReadUserInput_gotos
       movwf PCLATH
       movf a1_state, W      ; W <- a1_state
       andlw b'00000011'     ; clip to [0..3]
       addwf PCL, F          ; jump
ReadUserInput_gotos:
       goto read_user_input_0
       goto read_user_input_1
       goto read_user_input_2
       goto read_user_input_3
      ; ^^^ 8 Tcy

read_user_input_0:
       jbc b_tst, rui_00
       bsf a1_state, 0
       goto read_user_input_end
rui_00:
       jbc b_dwn, rui_01
       bsf a1_state, 1
       goto read_user_input_end
rui_01:
 clb b_ui_mc
       jbs b_mc, read_user_input_end
       seb b_ui_mc
       bsf a1_state, 0
       bsf a1_state, 1
       goto read_user_input_end

read_user_input_1:
       jbs b_tst, read_user_input_end
       bcf a1_state, 0
       seb b_ui_tst
       goto read_user_input_end

read_user_input_2:
       jbs b_dwn, read_user_input_end
       bcf a1_state, 1
       seb b_ui_dwn
       goto read_user_input_end

read_user_input_3:
       jbs b_mc, read_user_input_end
       bcf a1_state, 0
       bsf a1_state, 1
      ;seb b_ui_mc
      ;goto read_user_input_end
read_user_input_end:
       return

 

А теперь вопрос: как на C осуществить табличный переход? А то при использовании switch (a1_state) {case0: break; case 1: break; ...} или при использовании if (a1_state == 0) ... компилятор генерит код, который осуществляет проверку значения переменной a1_state на равенство сначала 0, потом 1, потом ... долго в общем. Пробовал еще так:

typedef void (* StatePtr ) ( void );

void state0( void ) {}
void state1( void ) {}
...

const StatePtr states[] = {state0, state1, state2, state3};

char a1_state = 0;

void main()
{
 while (1)
 {
   // some stuff
   states[a1_state] ();
 }
}

Но перед вызовом функции states[a1_state]() компилятор загружает полный адрес функции, после чего вызывает :cranky: . А если у меня все в одной странице помещается? Зачем тогда полный адрес?

 

Как лечить, что читать?

 

Извиняюсь за возможные ошибки, но с пиками знаком лишь один месяц :biggrin:

 

DukeXar.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Значит так, про страницы памяти можно позабыть и просто писать код, он сам всё сделает. чем проще пишешь тем легче компилируется, для интереса там есть опция компиляции в ассемблер. Можешь посмотреть код на асме.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И вообще красивый баннерок моей лисичке тоже понравилось, я заставил её прикинутся Осликом и вижу что получилось. Извини за OFFTOPIC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот нашел http://www.microchipc.com/Hi-Tech_C_speed_optimization.htm

 

In switch - case, change constants to be sequental numbers, without gaps.

Optimization Tip 5: Case statements

 

Slow and Inefficient

 

c=getch();
switch©
{
  case 'A':
  {
    do something;
    break;
  }

  case 'H':
  {
    do something;
    break;
  }

  case 'Z':
  {
    do something;
    break;
  }
}

 

Fast and Efficient

 

c=getch();
switch©
{
  case 0:
  {
    do something;
    break;
  }

  case 1:
  {
    do something;
    break;
  }

  case 2:
  {
    do something;
    break;
  }
}

The Hi-Tech C optimizer turns the switch statement into a computed goto if possible.

Пробовал я такой switch. Нифига он его в computed goto не компилит :angry2:

Делает как в первом, так и во втором случае следующее:

movf c, W
btfsc STATUS, Z
goto case_0
xorlw 1
btfsc STATUS, Z
goto case_1
xorlw 2
btfsc STATUS, Z
goto case_2

Ну и в чем же разница между "Slow and Inefficient" и "Fast and Efficient"? Где грабли?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проще пишите, ещё проще поставьте ряд IF, и самое главное не поднимайте степень оптимизации выше 1-2 эффекта это даёт мало, а ошибок много. структуру switch - case использовать не желательно. лучше if- elseif - else.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"Особенность" данного чудо - компилятора состоит в том что он проглатывает все стандартные Сишные обороты включая очень круто - завёрнутые, но не все их поддерживает. НО то что работает- работает очень хорошо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендую попробовать такой вариант:

if(A > 10)

{

 

}

else if((A <10) && (A > 0))

{

 

}

else

{

 

}

До сего дня у меня работал, думаю должен работать и у Вас.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, с X86 проще - знаешь какой код сгенерит компилятор. Да и время реакции не то.

 

И вот еще вопрос назрел. Я пока пишу на асме, но планирую перейти на C. Так вот, мне надо генерить пачку из 10 импульсов по 10мкс (скважность 50%) для управления тиристором в начале каждой фазы. Что я делал на асме: каждую миллисекунду проверял наличие фазы с датчика и, соответственно, генерил пачку. Если ее генерить не надо было - выполнял другие действия (считал, обновлял дисплейчик, проверял кнопочки итд.) К услугам таймера прибегал только для того, чтобы выдержать это время в 1мс с начала выполнения задачи. Задач было несколько и, поскольку у меня асм, я мог легко определить время выполнения каждой из них и соответственно перемешать так, чтобы суммарное время выполнения не превышало эту 1мс. Частота камня 4МГц. Прерывания не использовал. При использовании С, черт его знает, что он там состряпает. Я так понимаю, что выход один - использовать прерывание от таймера и в нем выполнять обработку? Наверняка с проблемой генерации таких коротких последовательностей сталкивались, где бы посмотреть примерчик, а то я еще студент :blush:, в смысле не волшебник :rolleyes: И еще: если вместо кварца на 4МГц поставить на 8МГц или больше - будет ли устройство более чувствительно к помехам, особенно, если монтаж пока выполнен на макетке проводом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

мне кажется имеет смысл все переписать для работы с прерываниями. в этом нет ничего сложного. я вот делаю примерно так:

1. в файле picxxxx.lkr вносим изменения:

CODEPAGE NAME=resvectors START=0x0 END=0x3 PROTECTED

CODEPAGE NAME=intvectors START=0x4 END=0xff PROTECTED

CODEPAGE NAME=page START=0x100 END=0x3FE

 

 

SECTION NAME=RESET_VECTOR ROM=resvectors // Reset and interrupt vectors

SECTION NAME=INT_VECTOR ROM=intvectors // Reset and interrupt vectors

SECTION NAME=PROG ROM=page // ROM code space

 

теперь у нас разделен вектор ресета (начальной загрузки) и прерывания. числа обязательно проверяются по мануалу. да бы не париться с банками я обычно откаменцичаваю

//SHAREBANK NAME=gpr0 START=0xA0 END=0xDF

так что переменные созданые через res выбираются тока в нулевом банке. ;)

Теперь в .asm. Начало кода будет как

RESET_VECTOR CODE ; processor reset vector

goto main ; go to beginning of program

с ресета идем на меин ;)

 

INT_VECTOR CODE ;interrupt vector location

movwf w_temp ;save off current W register contents

movf STATUS,w ; move status register into W register

movwf status_temp ; save off contents of STATUS register

bcf PORTC,0

goto but

сохранили регистры w, STATUS далее проверили от чего прерывание. в данном случае проверялась ножка по порту. далее так же можно проверить по завершенности работы таймера и т д.

хочется заметить, что в процессе работы с 16ыми пиками нашелся интересный глючек. как известно у 16го пика 8ми уровневый стек, но при этом нет флажка в флайловых регистрах сообщающих о его переполнении. при таком раскладе вроде бы можно отрываться на прерывание и не возвращаться из него по retfie. ну в общем это не так )) в дебаггере все работает на ура, а в реальной плате пик либо просто не шьется, либо сходит сума. ...мы разменяли с пяток адамов пока поняли в чем дело ))) (с).

а потом совсем все просто. запускаешь таймер разрешаешь прерывания, пускаешь вечный цыкл время от времени его будет отдергивать по таймеру. вот так.

кстати в си ты всегда можешь подсунуть асемблерный год при помощи

#asm

blabla

#endasm

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще, конечно придётся делать от прерываний таймера. Конечно можно просто поднять частоту, это криминал, но не великий, просто поднимется ток потребления. Лучше при этом ещё и перейти на серию контроллеров в маркировке которой стоит цифра 10, а лучше 20 это позволит поднять частоту до указанных цифр. И конечно воспользоваться опцией : компиляции в асм для контроля длин ходов программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Могу подсказать точно работающий способ создания табличных функций, которые работают лучше.

Предположим, что функция берёт в качестве параметра unsigned char и возвращает параметр unsigned short согласно таблице.

Тогда где-нибудь в заголовочном файле или отдельно создаём постоянный массив, по порядку вписываем туда все значения, а в теле функции просто делаем выбор из массива.

const unsigned short TableOne[128] = {0x0EDA, 0x0000, ....};

unsigned short MyFunction (unsigned char Param)
{
   Param &= 0x007F;
   return TableOne[Param];
}

Таким образом, весь массив постоянных будет размещён в памяти программ, и компилятор сгенерирует код табличного чтения. Если таблица достаточно большая, выигрыш получается очень существенный.

Можно расположить массив постоянных и в обычной памяти, но тогда на его создание нужно процессорное время и свободный срам.

 

А вот делать функции так, чтобы компилятор создавал код навроде этого:

CLRF PCLATH;
BSF PCLATH, 2;
ANDLW 0x07;
ADDWF PCL, F;

GOTO Branch_01;
GOTO Branch_02;
GOTO Branch_03;
GOTO Branch_04;
GOTO Branch_05;
GOTO Branch_06;
GOTO Branch_07;
GOTO Branch_08;

Branch_01:
....
Branch_02:
.....

Такого я ещё не умею.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...