П З (1230299), страница 4
Текст из файла (страница 4)
- программный имитатор – позволяет тестировать программу, которая находится в стадии разработки, при этом могут имитироваться входные и выходные сигналы, а также наблюдаться состояния ячеек памяти;
- программный отладчик – включает средства, обеспечивающие полный контроль за выполнением программы, например: пошаговая реализация программы, запуск её с пониженной скоростью исполнения либо остановка по конкретному адресу памяти.
При создании проекта любой сложности интегральная среда разработки MPLAB создает значительное число файлов, которые обозначаются соответствующими расширениями, приведенными в таблице 4.1. При объявлении проекта создаются файлы типа «.mcp» и «.mcw». Если исходный текст будет успешно скомпонован, то будут сгенерированы файлы с расширением «.lst», «.cof» и «.hex», а в случае возникновения ошибки – «.err».
Таблица 4.1 – Основные файловые расширения, используемые в MPLAB
| Расширение файла | Функция |
| .c | Исходный файл на языке C |
| .err | Файл ошибок |
| .hex | Файл машинной программы в шестнадцатеричном формате |
| .cod | Файл отладки и обозначений |
| .lib | Библиотечный файл |
| .lst | Файл, показывающий первоначальный исходный код |
| .o | Объектный файл, содержащий перемещаемый код |
| .mcp | Файл проектной информации |
| .mcw | Файл информации о рабочем пространстве |
| .cof | Файл, с конечным модулем, представляющий отладочную информацию |
4.2 Комментарии
Комментарии начинаются с комбинации «/*» и заканчиваются «*/». В такой форме они могут выходить за пределы одной строки, могут предшествовать или следовать за инструкциями и объявлениями.
Альтернативный формат комментариев – двойной «слэш» (//) перед комментарием. Тогда такой комментарий продолжается только до конца данной строки и не требует никакого завершающего символа.
4.3 Объявления
Объявления используются во многих местах для создания программных элементов, например, такие как переменные или функции и указания их свойств. Важно, что все переменные и функции в С должны быть объявлены до того, как они будут использоваться. Задаваемые характеристики включают тип элемента данных (например, с фиксированной точкой)
4.4 Подключение библиотек
Директива #include включает в текст программы содержимое указанной библиотеки
#include <p18f452.h> /*Объявление библиотеки, содержащей весь функционал микроконтроллера*/
#include <delays.h> /*Объявление библиотеки задержек*/
4.5 Настройка порта C для вывода на экран
Директива #define служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами.
#define LED PORTC //Порту С присвоено имя LED
#define Set_Enumber PORTBbits.RB3 = 1 //Вкл. разряд единиц
#define Reset_Enumber PORTBbits.RB3 = 0 //Выкл. разряд единиц
#define Set_Dnumber PORTBbits.RB4 = 1 //Вкл. разряд десятков
#define Reset_Dnumber PORTBbits.RB4 = 0 //Выкл. разряд десятков
#define Set_Snumber PORTBbits.RB5 = 1 //Вкл. разряд сотен
#define Reset_Snumber PORTBbits.RB5 = 0 //Выкл. разряд сотен
#define Set_Tnumber PORTBbits.RB6 = 1 //Вкл. разряд тысяч
#define Reset_Tnumber PORTBbits.RB6 = 0 //Выкл. разряд тысяч
4.6 Настройка параметров микроконтроллера
Директива #pragma необходима для реализации директив, предоставляющих компилятору различные инструкции.
#pragma config OSC = XT /* Режим генератора XT*/
#pragma config OSCS = OFF /* Запрещено переключение источника тактового сигнала*/
#pragma config PWRT = ON /* Разрешена работа таймера включения питания*/
#pragma config BOR = OFF /* Запрещен сброс МК по снижению напряжения питания*/
#pragma config WDT = OFF /* Сторожевой таймер отключен*/
#pragma config STVR = ON /* Разрешен сброс МК при переполнении стека*/
#pragma config LVP = OFF /* Низковольтное программирование запрещено*/
4.7 Ввод переменных для подсчета частоты и вывода на динамическую индикацию результата
В языке C различают понятия "тип данных" и "модификатор типа". Модификатор – это число с запятой, а тип данных – это целое число. Целое число со знаком будет иметь как положительные, так и отрицательные значения, а целое без знака – только положительные значения. В языке Си можно выделить пять базовых типов, которые задаются следующими ключевыми словами:
- char – символьный;
- int – целый;
- float – вещественный;
- double – вещественный двойной точности;
- void – не имеющий значения.
Модификатор типа unsigned указывает, что переменная может принимать неотрицательные значения.
unsigned int counter = 0; /*Ввод переменной для счета входящих в микроконтроллер сигналов*/
unsigned char thousand = 0; /*Ввод переменной для вывода на экран разряда тысяч*/
unsigned char hundred = 0; /*Ввод переменной для вывода на экран разряда сотен*/
unsigned char ten = 0; /*Ввод переменной для вывода на экран разряда десятков*/
unsigned char one = 0; /*Ввод переменной для вывода на экран разряда едениц*/
char led_on = 0;
unsigned char dig[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; /*Ввод массива, для вывода цифр на динамическую индикацию*/
4.8 Настройка прерывания высокого уровня
Ключевое слово void, при использовании в качестве типа возвращаемого значения для метода, указывает, что метод не возвращает значение.
Ключевое слово _asm означает, что мы перешли на язык ассемблера. Оператор GOTO – это оператор перехода к какой-либо строчке программы, который работает только в ассемблере.
void prervo (void);
#pragma interrupt prervo
#pragma code high_vector = 0x08
void high_vector (void)
{
_asm GOTO prervo _endasm
}
#pragma code
4.9 Функция обработки прерывания
Для начала необходимо разрешить прерывания по таймеру 1, за это отвечает регистр PIR1.
Прерывание по таймеру 1 нужно посчитать по формуле 2.1. Полученное значение должно быть загружено в регистр TMR1H и TMR1L в двоичном виде, до момента переполнения таймера.
В нашем случае таймер должен досчитать до 5 мс, то есть 5000 мкс, таймер работает в 16-разрядном режиме, то есть B равно 65536, кварцевый резонатор выдает частоту в 4 МГц, а предделитель настроен на деление на 4. Данная зависимость будет выглядеть следующим образом
Полученный результат нужно перевести в двоичную систему счисления, чтобы определить какие значения требуется в
и
: 6428610 = 1111 1011 0001 11102. Следовательно, в
требуется загрузить число 1111 10112, а в
– 0001 11102.
Чтобы таймер работал нужным нам образом, его нужно настроить. Регистром управления данного таймера является T1CON, приведенный в приложении 2.
Операторы switch и case помогают управлять сложными условными операциями и операциями ветвления. Оператор switch передает управление в оператор внутри своего тела. Управление передается оператору, значение выражения case константное-выражение которого соответствует значению выражения switch (выражение). Оператор switch может содержать любое число экземпляров case, однако никакие две константы варианта в одном операторе switch не могут иметь одинаковые значения. Выполнение тела оператора начинается с выбранного оператора и продолжается до конца тела оператора или пока управление не будет передано за пределами тела оператора с помощью оператора break.
void prervo (void) //Функция прерывания
{
if (PIR1bits.TMR1IF == 1) //Флаг прерывания по переполнению TMR1
{
PIR1bits.TMR1IF = 0; //Сброс флага переполнения TMR1
TMR1H = 0b11111011; //Запись числа в TMR1H
TMR1L = 0b00011110; //Запись числа в TMR1L
switch (led_on) //Переключение разрядов динамической индикации
{
case 0: //Разряд тысяч
{
led_on++; //Увеличение переменной led_on на 1
Reset_Enumber;
LED = *(dig+thousand); /*Вывод в порт С цифры из массива*/
Set_Tnumber; break;
}
case 1: //Разряд сотен
{
Reset_Tnumber;
led_on++; //Увеличение переменной led_on на 1
LED = *(dig+hundred); /*Вывод в порт С цифры из массива*/
Set_Snumber; break;
}
case 2: //Разряд десятков
{
Reset_Snumber;
led_on++; //Увеличение переменной led_on на 1
LED = *(dig+ten); /*Вывод в порт С цифры из массива*/
Set_Dnumber; break;
}
case 3: //Разряд единиц
{
Reset_Dnumber;
led_on = 0; //Увеличение переменной led_on на 1
LED = *(dig+one); /*Вывод в порт С цифры из массива*/
Set_Enumber; break;
}
}
}
Для работы с таймером 0 необходимо его правильно настроить с помощью регистра управления режимом прерываний INTCON, приведенным в приложении 1.
В данном случае таймер 0 должен досчитать до 1 секунды, то есть 1000000 мкс, таймер работает в 16-разрядном режиме, то есть B равно 65536, кварцевый резонатор выдает частоту в 4 МГц, а предделитель настроен на деление на 256. Данная зависимость будет выглядеть следующим образом
Полученный результат нужно перевести в двоичную систему счисления, чтобы определить какие значения требуется в TMR0H и TMR0L: 6153610 = 1111 0000 0110 00002. Следовательно, в TMR0H требуется загрузить число 1111 00002, а в TMR0L – 1011 11102.
Чтобы таймер работал нужным нам образом, его нужно настроить. Регистром управления данного таймера является T0CON, приведенный в приложении 2.
if (INTCONbits.TMR0IF == 1) //Флаг прерывания по переполнению TMR0
{
INTCONbits.TMR0IF = 0; /*сброс флага прерывания по переполнению TMR0*/
TMR0H = 0b11110000; //Запись числа в TMR0H
TMR0L = 0b01100000; //Запись числа в TMR0H
thousand = hundred = ten = one = 0; //Сброс переменных в 0
/*подсчет количества разрядов динамической индикации*/
for (; counter >= 1000; counter = counter - 1000) thousand++;
for (; counter >= 100; counter = counter - 100) hundred++;
for (; counter >= 10; counter = counter - 10) ten++;
for (; counter >= 1; counter--) one++;
counter = 0; //Сброс counter в 0
}
Для подсчета количества импульсов, поступающих в микроконтроллер в течении секунды, используем прерывание по порту B, то есть , когда поступает импульс на ножку порта B, происходит прерывание и значение переменной counter увеличивается на 1.
if (INTCONbits.INT0IF == 1) /*Флаг прерывания по изменению сигнала на ножке RB0*/
{
INTCONbits.INT0IF = 0; /*Сброс флага прерывания по изменению сигнала на ножке RB0*/
counter++; //Увеличение переменной counter на 1
}
}
4.10 Главная функция
Главная функция нужна только для настройки определенных параметров, таких как настройка портов ввода/вывода, разрешение различных прерываний, а так же настройка таймеров.
void main (void) //Основная функция
{
TRISB = 0b00000001; //Настройка первого бита порта B на ввод информации
PORTB = 0b00000000; //Обнуление значений порта B
TRISC = 0b00000000; //Настройка порта C на вывод информации PORTC = 0b00000000; //Обнуление значений порта C
INTCONbits.PEIE = 1; //Разрешение периферийных прерываний
INTCONbits.INT0IE = 1; //Разрешение внешнего прерываний
INTCON2bits.INTEDG0 = 1; //Прерывание по фронту входящего сигнала
INTCONbits.TMR0IE = 1; /*Разрешение прерывания по переполнению TMR0*/
PIE1bits.TMR1IE = 1; //Разрешение прерывания по переполнению TMR1















