Свежие обсуждения
Микроконтроллеры

Ликбез по С для микроконтроллеров PIC

1 41 64

Смотрю на эту "сю", китайская грамота... Никак не соберусь выучить синтаксис, а вот асм, это да...

 

Зато практически не надо знать(может и к худшему) всяких внутренних дебрей МК,
Выражение типа: IF..... ELSE.... оно и в пиках и в остальных МК сделает одно и тоже, так намного проще и понятней !
А как оно там это все выполнять будет можно и не знать.

 

Left Radio: Зато практически не надо знать(может и к худшему) всяких внутренних дебрей МК
Как же ты сможешь использовать аппаратные средства мк, если не надо знать всяких внутренних дебрей МК

 

IMHO, начинать нужно с асма, и, обязательно, продолжать на ЯВУ. Увы, я застрял. Нет стимула. Именно нужно знать аппаратные тонкости железа.

 

Left Radio: А разве например команда выполняющаяся в прерывании delay_ms(100) не затормозит основную программу?

Я так понимаю, что "delay_ms(100)" - это функция, которую вы берете из хидера. И организована она стандартным образом. Если ее вставить в прерывание, то все пойдет наперекосяк. Например, таймер переполняется каждые 5мс, а ваша функция "залипнет" в цикле на 100 мс. Чувствуете подвох?
В прерывании не надо делать циклов.
Смысл такой. Заводим переменную unsigned char. В каждом прерывании проверяем состояние бита, к которому подключена кнопка. Если бит не меняется, то ничего не делаем и преспокойно выходим из прерывания. Если бит изменил свое состояние на противоположное, то делаем инкремент переменной. Далее сравниваем нашу переменную с константой, которая и определяет нужное время. В каждом прерывании при нажатой кнопке "переменная++;" делается только один раз. И когда в каком-то из последующих прерываний, переменная сравняется с константой - это и есть факт нажатия кнопки. Переменную можно обнулить. Константу выбирают исходя из необходимого времени на обработку кнопки. Например, нужно 50мс, а таймер переполняется каждые 5 мс. Тогда константа должна быть равна 10.
Как-то вот так, если в двух словах.
ЗЫ Правда в пиках лучше делать наоборот. Присваивать переменной значение константы, а далее делать ее декремент. А проверять на 0.

 

nemos : Как же ты сможешь использовать аппаратные средства мк, если не надо знать всяких внутренних дебрей МК
Я не те дебри имел ввиду, Аппаратные средства само собой надо знать.

Zandy: Например, таймер переполняется каждые 5мс, а ваша функция "залипнет" в цикле на 100 мс. Чувствуете подвох?

Я тоже так думал но...
Zandy: В прерывании по таймеру можно не только кнопки обрабатывать, а еще делать кучу всякой всячины. Например организовывать задержки любых длительностей без ущерба основной программе и т. д.

Наверно я неправильно понял.
По поводу прибавления переменной, понял спасибо.

Zandy: Правда в пиках лучше делать наоборот. Присваивать переменной значение константы, а далее делать ее декремент. А проверять на 0.

Почему? И как это на Си будет?
Примерно так?

int varible;
.....
void main(void)
{
varible = 10 ;
if ( input(PIN_E0) ) { flag = 1 }
else flag = 0 ;
}

....}

#INT_RTCC
VOID TIMER_INTERRUPT (void)
{
if (flag == 1) { varible-- }

if ( varible==0){ pwmDuty = ( pwmDuty + 1 ); varible=10; }
}

 

Left Radio: Почему?
Если писать на асме, то это потребует меньшее количество команд. Думаю, что и при компиляции с си код будет меньше.

Left Radio: if ( input(PIN_E0) ) { flag = 1 }
else flag = 0 ;

На самом деле не совсем так. Во-первых, проверку состояния входа надо делать не в основной программе, а в прерывании. Во-вторых эта ваша функция не имеет смысла. Точнее битовая переменная flag полностью повторяет состояние вывода порта. А в - третьих, все зависит от логики работы, которую вы хотите получить. Например, если вы хотите избавиться от дребезга контактов не только при замыкании, но и при размыкании кнопки, надо мутить более хитрую запись и там действительно может потребоваться процедура установки - сброса флагов.

 

Zandy: Если писать на асме, то это потребует меньшее количество команд. Думаю, что и при компиляции с си код будет меньше.

Не понимаю чем отличается реализация декремента от реализации инкремента.
Спасибо вам за пояснение.

Zandy: Во-первых, проверку состояния входа надо делать не в основной программе, а в прерывании. Во-вторых эта ваша функция не имеет смысла.

Уже разобрался и переписал код, но про дребезг контакта при отпускании кнопки даже и не подумал. Еще одной задачкой больше
Просто хочется написать что нибуть универсальное на Си, чтоб потом в других программах не мудрствовать...

 

Ну значится пока что примерно так:

#INT_TIMER2
VOID TIMER_2_INTERRUPT (void)
{
if(input(PIN_E0)){flagPin1 = 1; ++varible; ++N_overflows; }
else flagPin1 = 0;
if(input(PIN_E1)){flagPin2 = 1; ++varible; ++N_overflows;}
else flagPin2 = 0;
}

void button_put (void)
{
if(flagPin1 == 1 && N_overflows >= 1000)
{
if ( varible >= 10){ pwmDuty = pwmDuty + 1 ; varible=0; }
}
else if(flagPin1 == 1 && N_overflows < 1000)
{
if ( varible >= 100){ pwmDuty++ ; varible=0; }
}
else if(flagPin2 == 1 && N_overflows < 1000)
{
if ( varible >= 100){ --pwmDuty ; varible=0; }
}
else if(flagPin2 == 1 && N_overflows >= 1000)
{
if ( varible >= 10){ --pwmDuty ; varible=0; }
}
else N_overflows = 0;
}

Работает так:
При нажатии на PIN_E0 или PIN_E1 происходит уменьшение или увеличение скважности ШИМ на единицу, каждые 100 прерываний таймера. При удержании кнопки больше примерно 5сек уменьшение или увеличение скважности происходит один раз за 10 прерываний, то есть увеличилась скорость изменения скважности ШИМ.
Вместо ШИМ можно подставлять что угодно. Длительности тоже изменить очень просто, если не нужно приращение скорости то просто вырезаем и все. Пока довольно универсально.
Осталось выяснить будет ли дребезг контакта при отпускании кнопки, и все...

 

Zandy: ..."delay_ms(100)"... Если ее вставить в прерывание, то все пойдет наперекосяк. Например, таймер переполняется каждые 5мс, а ваша функция "залипнет" в цикле на 100 мс
так до выхода из прерывания новые прерывания будут помещатся в список отложенных. С другой стороны - этот список не конечный и будет только расти, собственно только прерывание и будет работать пока что-то не взорвется

Vladikas: Никак не соберусь выучить синтаксис, а вот асм, это да...
да там все просто Правда, я вначале Си под ДОСом изучал. Потом начал осваивать пики на асме. Теперь перешел на си для МК. Не вижу (для себя) смысла использовать асм там, где не критично быстродействие. Да и визуально намного все проще. Не нужно писать кучу кода для операции вроди 2.1*3.7 или if(ButtonPress) { PIN1=0; PIN2=1;} else {PIN3=1}. Все просто и читабельно. До того, как порпробовал Си для МК я тоже немного боялся его (точнее смутно представлял, как оно там работает).