|
|
  |
Вопрос по пикам и HITECH PICC, Как заставить его сгенерить код попроще |
|
|
|
Jul 26 2005, 05:48
|

Участник

Группа: Свой
Сообщений: 50
Регистрация: 23-07-05
Из: Россия, Киров
Пользователь №: 7 038

|
Хочу простого. Есть функция, которая в зависимости от состояния автомата, реализует те или иные действия и переводит автомат в другое состояние. На 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]() компилятор загружает полный адрес функции, после чего вызывает  . А если у меня все в одной странице помещается? Зачем тогда полный адрес? Как лечить, что читать? Извиняюсь за возможные ошибки, но с пиками знаком лишь один месяц
--------------------
Магам можно все.
|
|
|
|
|
Jul 28 2005, 08:37
|

Участник

Группа: Свой
Сообщений: 50
Регистрация: 23-07-05
Из: Россия, Киров
Пользователь №: 7 038

|
Вот нашел 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 CODE c=getch(); switch© { case 'A': { do something; break; }
case 'H': { do something; break; }
case 'Z': { do something; break; } }
Fast and Efficient CODE 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 не компилит Делает как в первом, так и во втором случае следующее: Код 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"? Где грабли?
--------------------
Магам можно все.
|
|
|
|
|
Aug 3 2005, 16:47
|

Участник

Группа: Свой
Сообщений: 50
Регистрация: 23-07-05
Из: Россия, Киров
Пользователь №: 7 038

|
Шаблонов не хватает, AKA C++  Спасибо, попробую и так.
--------------------
Магам можно все.
|
|
|
|
|
Aug 3 2005, 17:13
|

Участник

Группа: Свой
Сообщений: 50
Регистрация: 23-07-05
Из: Россия, Киров
Пользователь №: 7 038

|
Да, с X86 проще - знаешь какой код сгенерит компилятор. Да и время реакции не то. И вот еще вопрос назрел. Я пока пишу на асме, но планирую перейти на C. Так вот, мне надо генерить пачку из 10 импульсов по 10мкс (скважность 50%) для управления тиристором в начале каждой фазы. Что я делал на асме: каждую миллисекунду проверял наличие фазы с датчика и, соответственно, генерил пачку. Если ее генерить не надо было - выполнял другие действия (считал, обновлял дисплейчик, проверял кнопочки итд.) К услугам таймера прибегал только для того, чтобы выдержать это время в 1мс с начала выполнения задачи. Задач было несколько и, поскольку у меня асм, я мог легко определить время выполнения каждой из них и соответственно перемешать так, чтобы суммарное время выполнения не превышало эту 1мс. Частота камня 4МГц. Прерывания не использовал. При использовании С, черт его знает, что он там состряпает. Я так понимаю, что выход один - использовать прерывание от таймера и в нем выполнять обработку? Наверняка с проблемой генерации таких коротких последовательностей сталкивались, где бы посмотреть примерчик, а то я еще студент  , в смысле не волшебник  И еще: если вместо кварца на 4МГц поставить на 8МГц или больше - будет ли устройство более чувствительно к помехам, особенно, если монтаж пока выполнен на макетке проводом?
--------------------
Магам можно все.
|
|
|
|
|
Aug 4 2005, 02:18
|
Частый гость
 
Группа: Свой
Сообщений: 116
Регистрация: 14-05-05
Из: snz->ekb->msk.
Пользователь №: 5 026

|
мне кажется имеет смысл все переписать для работы с прерываниями. в этом нет ничего сложного. я вот делаю примерно так: 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
|
|
|
|
|
Sep 1 2005, 05:19
|
Частый гость
 
Группа: Свой
Сообщений: 90
Регистрация: 17-04-05
Из: Минск
Пользователь №: 4 215

|
Могу подсказать точно работающий способ создания табличных функций, которые работают лучше. Предположим, что функция берёт в качестве параметра 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: ..... Такого я ещё не умею.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|