На очередном видеоуроке мы научимся регулировать скорость вращения нашего двигателя при помощи МК PIC.
Разберёмся чуть подробнее с нашей ручной газа. Рассмотрим реальное положение дел.
В крайнем левом положении, которое должно соответствовать мощности 0%, напряжение на бегунке переменного резистора не равно 0В. Допустим, около 0,1В. Значит, наш АЦП намеряет около 2-4ИЕ. Записав эти данные в регистр OCR2, мы видим с вами на осциллографе тонкие иголки.
Поворачивая переменный резистор, мы увеличиваем напряжение на бегунке переменного резистора и как следствие на входе АЦП. Измеренное значение записываем в регистр OCR2, тем самым увеличивая заполнение.
Достигнув крайнего правого положения, которое соответствует мощности 100%, напряжение на бегунке, в идеале, должно равняться 5В. На самом деле оно или немногим меньше, к примеру 4,91В или больше, к примеру 5,09.
В первом случае АЦП намеряет немногим меньше максимума, что-то около 251ИЕ. На осциллограмме мы видим длинный импульс и коротенькие паузы в виде иголок.
Во втором АЦП выдаст максимум 255ИЕ, несмотря на то, что напряжение в реальности больше. Загрузив это значение в регистр OCR2, на выходе получаем сплошной уровень +5В без переключений.
Настраивая периферию МК, я привык детально комментировать регистры, такой подход занимает много строк. Шапка программы разрастается. В предыдущем уроке инициализация периферии заняла 34 строки. В нашем уроке это уже 232 строки. Да и функций становится больше и больше. Лично мне трудно ориентироваться в таком длинном коде.
Спасение я нашёл в заголовочных файлах. Содержимое этих файлов автоматически добавляется препроцессором в исходный текст в том месте, где располагается директива include.
Файловая структура программы теперь выглядит следующим образом: основной код содержится в main.c, все строки инициализации периферии вынесены в файл initHard.c, в initHard.h размещены объявления функций содержащихся в initHard.c.
Итак разберём программу…
Ручку газа подключаем к АЦП – pin13, RC2/CPP1. Выход ШИМ последовательности наблюдаем на pin2, RA0/AN0.
Настроим соответствующие линии порта…
TRISCbits.TRISC2 = 0; //Настраиваем RC2/CCP1 на вывод, ручка газа
TRISAbits.TRISA0 = 1; //Настраиваем RA0/AN0 на ввод, АЦП
Для того, чтобы запустить модуль CCP в режиме ШИМ, необходимо включить таймер 2. Настроим его…
В соответствии с даташитом выбираем частоту ШИМ последовательности 1,22кГц.
//T2CKPS1:T2CKPS0: Timer2 Clock Prescale Select bits
//00= Prescaler is 1
//01= Prescaler is 4
//1x= Prescaler is 16
T2CKPS0 = 0;
T2CKPS1 = 1;
Включаем таймер.
//TMR2ON: Timer2 On bit
//1= Timer2 is on
//0= Timer2 is off
TMR2ON = 1;
Запускаем модуль CCP1 в режиме ШИМ.
//CCPxM3:CCPxM0: CCP1 Mode Select bits
//…
//11xx=PWM mode
CCP1M0 = 0;
CCP1M1 = 0;
CCP1M2 = 1;
CCP1M3 = 1;
Загружаем в регистр периода таймера 2 значение, соответствующее частоте 1,22кГц.
PR2 = 255; //Установка периода 1,22кГц
Напоследок настроим АЦП. Выберем левое выравнивание результата.
//ADFM: A/D Result Format Select bit
//1= Right justified. 6 Most Significant bits of ADRESH are read as С0Т.
//0= Left justified. 6 Least Significant bits of ADRESL are read as С0Т.
ADFM = 0;
Выберем аналоговую линию.
//PCFG3:PCFG0: A/D Port Configuration Control bits
//Mode 1110: AN5-AN1 is digital, AN0 is analog
PCFG0 = 0;
PCFG1 = 1;
PCFG2 = 1;
PCFG3 = 1;
Включим модуль АЦП.
//ADON: A/D On bit
//1= A/D converter module is operating
//0= A/D converter module is shut-off
ADON = 1;
Рассмотрим основной код. С заголовком вы уже знакомы.
#define _XTAL_FREQ 20000000 //Указываем тактовую частоту процессора
#include //Содержит в себе макроопределения, в частности __CONFIG
#include «pic16f876a.h» //Файл определения имён регистров, портов…
#include «initHard.h» //Содержит в себе определение процедур инициализации периферии
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & WRT_OFF);
Теперь основная процедура main. Инициализируем периферию.
//Инициализация периферии…
initPORTs(); //Инициализация портов
initTIMERs(); //Инициализация таймеров
initCCPs(); //Инициализация CCP-модулей
initADC(); //Инициализация АЦП
Далее, в бесконечном цикле выполняем три действия: запускаем преобразование, ждём окончания цикла преобразования, загружаем значение скважности в CCP модуль
//Бесконечный цикл
while(1)
{
GO_DONE = 1; //Запуск преобразования АЦП
__delay_us(100); //Пауза перед следующим измерением
CCPR1L = ADRESH; //Загружаем значение скважности
}
ПРОЕКТ С ИСХОДНЫМ КОДОМ И СИМУЛЯЦИЯ В PROTEUS во вложении.
Прикрепленные файлы:
- microchip.rar (83 Кб)