На этом уроке мы портируем программную реализацию интерфейса передатчика и приёмника с формированием импульсов переменной длительности на микроконтроллер PIC.
Начнём с передатчика. Инициализируем периферию, настраиваем порты…
TRISAbits.TRISA0 = 1; //Вход ручки газа TRISAbits.TRISA2 = 0; //Выход интерфейса TRISBbits.TRISB1 = 1; //Вход кнопки заднего хода TRISBbits.TRISB2 = 1; //Вход кнопки поворот вправо TRISBbits.TRISB4 = 1; //Вход кнопки поворот влево
Настройка таймера 0 не требуется. Модули CCP не используем. Включаем АЦП…
ADON = 1;
Конфигурируем порт А следующим образом: линия AN0 - аналоговый вход, линии AN1 - AN5 цифровые, двунаправленные линии порта ввода вывода.
PCFG0 = 0; PCFG1 = 1; PCFG2 = 1; PCFG3 = 1;
Настроим прерывания: разрешаем прерывания периферийных модулей…
PEIE = 1;
Включаем прерывания таймера 0…
T0IE = 1;
Разрешаем все прерывания…
GIE = 1;
В основном цикле запускаем измерение АЦП и опрашиваем клавиши пульта…
while(1) //Основной цикл { GO_DONE = 1; //Начать измерение __delay_us(100); //Ждём окончание измерения //Направление движения if (PORTBbits.RB1 == 0) direction_of_motion = 255; else direction_of_motion = 127; //Направление поворота if (PORTBbits.RB2 == 0) direction_of_rotation = 3; //Влево if (PORTBbits.RB4 == 0) direction_of_rotation = 255; //Вправо if (PORTBbits.RB2 == 1 && PORTBbits.RB4 == 1) direction_of_rotation = 127; //Прямо }
Теперь про обработчик прерывания. У нашего МК один вектор прерывания! Поэтому внутри обработчика необходимо опрашивать флаги прерываний, чтобы выяснить что именно вызвало прерывание. Нам проще, т.к. прерывание у нас одно, поэтому проверять флаг T0IF нам нет смысла. Содержание обработчика прерывания идентично варианту для AVR, код говорит сам за себя…
interrupt void entry_point() //Точка входа в прерывание { OPTION_REGbits.T0CS = 1; //Выключить таймер //Первый импульс, мощьность двигателя if (counter_cycles == 400) PORTAbits.RA2 = 1; //Формируем фронт if (counter_cycles == (400 + ADRESH)) PORTAbits.RA2 = 0; //Формируем срез //Второй импульс, направление движения if (counter_cycles == 705) PORTAbits.RA2 = 1; //Формируем фронт if (counter_cycles == (705 + direction_of_motion)) PORTAbits.RA2 = 0; //Формируем срез //Третий импульс, направления поворота if (counter_cycles == 1010) PORTAbits.RA2 = 1; //Формируем фронт if (counter_cycles == (1010 + direction_of_rotation)) PORTAbits.RA2 = 0; //Формируем срез counter_cycles++; //Инкремент счётчика отсчётов if (counter_cycles > 1265) counter_cycles = 0; //Проверяем признак окончания кадра TMR0 = 0; //"Калибровочная константа" OPTION_REGbits.T0CS = 0; //Включить таймер INTCONbits.T0IF = 0; //Сбросить флаг прерывания }
Теперь разберёмся с приёмником. Инициализируем периферию, настраиваем порты…
TRISAbits.TRISA2 = 1; //Вход интерфейса TRISBbits.TRISB1 = 0; //Выход кнопки заднего хода TRISBbits.TRISB2 = 0; //Выход кнопки поворот вправо TRISBbits.TRISB4 = 0; //Выход кнопки поворот влево TRISCbits.TRISC2 = 0; //Выход PWM
Настраиваем таймер 1, выберем предделитель на 4…
T1CKPS0 = 0; T1CKPS1 = 1;
Настраиваем таймер 2 для работы с CCP модулем. Выберем предделитель на 16…
T2CKPS0 = 0; T2CKPS1 = 1;
Включаем таймер…
TMR2ON = 1;
Настроим модуль CCP. Выберем частоту ШИМ в 1,22кГц, для этого запишем в регистр уставку…
PR2 = 255; //Установка периода 1,22кГц
Включаем CCP модуль в режиме ШИМ…
CCP1M0 = 0; CCP1M1 = 0; CCP1M2 = 1; CCP1M3 = 1;
Несмотря не то, что АЦП не используется конфигурируем порт А следующим образом: линии AN0 - AN5 цифровые, двунаправленные линии порта ввода вывода…
PCFG0 = 0; PCFG1 = 1; PCFG2 = 1; PCFG3 = 0;
Рассмотрим программу. В основном цикле декодируем стартовую паузу…
//Начало декодирования посылки while(PORTAbits.RA2); //Ждём логического ноля TMR1 = 0; //Сбросить счётчик отсчётов TMR1ON = 1; //Включить таймер while(!PORTAbits.RA2); //Считаем, пока принимаем логический ноль TMR1ON = 0; //Выключить таймер
Проверяем длительность…
if (TMR1 < 38000) continue; //Если пауза не выдержана...
…если длительность соответствует, декодируем первый импульс…
//Декодирование первого импульса TMR1 = 0; //Сбросить счётчик отсчётов TMR1ON = 1; //Включить таймер while(PORTAbits.RA2); //Считаем, пока принимаем логическую единицу TMR1ON = 0; //Выключить таймер
Загружаем измеренное значение скважности, предварительно масштабировав его…
CCPR1L = TMR1/96; //Загружаем значение скважности
Аналогично декодируем второй импульс. Основываясь на измеренной длительности определяем направление движения…
if (TMR1 > 18000) PORTBbits.RB1 = 1; else PORTBbits.RB1 = 0;
Аналогично декодируем третий импульс. Основываясь на измеренной длительности определяем направление поворота…
if (TMR1 < 1000) PORTBbits.RB2 = 1; else PORTBbits.RB2 = 0; if (TMR1 > 18000) PORTBbits.RB4 = 1; else PORTBbits.RB4 = 0;
На сегодня всё! До новых встреч!
ПРОЕКТ С ИСХОДНЫМ КОДОМ И СИМУЛЯЦИЯ В PROTEUS во вложении.
Прикрепленные файлы:
- atmel.rar (146 Кб)
- microchip.rar (328 Кб)
Комментарии (0) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация