DukeXar 0 26 июля, 2005 Опубликовано 26 июля, 2005 · Жалоба Хочу простого. Есть функция, которая в зависимости от состояния автомата, реализует те или иные действия и переводит автомат в другое состояние. На 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: . А если у меня все в одной странице помещается? Зачем тогда полный адрес? Как лечить, что читать? Извиняюсь за возможные ошибки, но с пиками знаком лишь один месяц Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 27 июля, 2005 Опубликовано 27 июля, 2005 · Жалоба Значит так, про страницы памяти можно позабыть и просто писать код, он сам всё сделает. чем проще пишешь тем легче компилируется, для интереса там есть опция компиляции в ассемблер. Можешь посмотреть код на асме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 27 июля, 2005 Опубликовано 27 июля, 2005 · Жалоба И вообще красивый баннерок моей лисичке тоже понравилось, я заставил её прикинутся Осликом и вижу что получилось. Извини за OFFTOPIC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DukeXar 0 28 июля, 2005 Опубликовано 28 июля, 2005 · Жалоба Вот нашел 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"? Где грабли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 3 августа, 2005 Опубликовано 3 августа, 2005 · Жалоба Проще пишите, ещё проще поставьте ряд IF, и самое главное не поднимайте степень оптимизации выше 1-2 эффекта это даёт мало, а ошибок много. структуру switch - case использовать не желательно. лучше if- elseif - else. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 3 августа, 2005 Опубликовано 3 августа, 2005 · Жалоба "Особенность" данного чудо - компилятора состоит в том что он проглатывает все стандартные Сишные обороты включая очень круто - завёрнутые, но не все их поддерживает. НО то что работает- работает очень хорошо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 3 августа, 2005 Опубликовано 3 августа, 2005 · Жалоба Рекомендую попробовать такой вариант: if(A > 10) { } else if((A <10) && (A > 0)) { } else { } До сего дня у меня работал, думаю должен работать и у Вас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DukeXar 0 3 августа, 2005 Опубликовано 3 августа, 2005 · Жалоба Шаблонов не хватает, AKA C++ :a14: Спасибо, попробую и так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DukeXar 0 3 августа, 2005 Опубликовано 3 августа, 2005 · Жалоба Да, с X86 проще - знаешь какой код сгенерит компилятор. Да и время реакции не то. И вот еще вопрос назрел. Я пока пишу на асме, но планирую перейти на C. Так вот, мне надо генерить пачку из 10 импульсов по 10мкс (скважность 50%) для управления тиристором в начале каждой фазы. Что я делал на асме: каждую миллисекунду проверял наличие фазы с датчика и, соответственно, генерил пачку. Если ее генерить не надо было - выполнял другие действия (считал, обновлял дисплейчик, проверял кнопочки итд.) К услугам таймера прибегал только для того, чтобы выдержать это время в 1мс с начала выполнения задачи. Задач было несколько и, поскольку у меня асм, я мог легко определить время выполнения каждой из них и соответственно перемешать так, чтобы суммарное время выполнения не превышало эту 1мс. Частота камня 4МГц. Прерывания не использовал. При использовании С, черт его знает, что он там состряпает. Я так понимаю, что выход один - использовать прерывание от таймера и в нем выполнять обработку? Наверняка с проблемой генерации таких коротких последовательностей сталкивались, где бы посмотреть примерчик, а то я еще студент , в смысле не волшебник :rolleyes: И еще: если вместо кварца на 4МГц поставить на 8МГц или больше - будет ли устройство более чувствительно к помехам, особенно, если монтаж пока выполнен на макетке проводом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
katarsis 0 4 августа, 2005 Опубликовано 4 августа, 2005 · Жалоба мне кажется имеет смысл все переписать для работы с прерываниями. в этом нет ничего сложного. я вот делаю примерно так: 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Samrat 0 4 августа, 2005 Опубликовано 4 августа, 2005 · Жалоба Вообще, конечно придётся делать от прерываний таймера. Конечно можно просто поднять частоту, это криминал, но не великий, просто поднимется ток потребления. Лучше при этом ещё и перейти на серию контроллеров в маркировке которой стоит цифра 10, а лучше 20 это позволит поднять частоту до указанных цифр. И конечно воспользоваться опцией : компиляции в асм для контроля длин ходов программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Epikur 0 1 сентября, 2005 Опубликовано 1 сентября, 2005 · Жалоба Могу подсказать точно работающий способ создания табличных функций, которые работают лучше. Предположим, что функция берёт в качестве параметра 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: ..... Такого я ещё не умею. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться