Программное управление технологическим оборудованием
.pdfЛабораторная работа 4
Изучение системы программирования микроконтроллеров dsPIC33 с помощью языка программирования Cи
Цель работы:
Изучить правила программирования микроконтроллера на языке программирования C, особенности использования языка при разработке программ. По заданному алгоритму составить программу, откомпилировать и исследовать ход её работы в симуляторе
Порядок выполнения работы:
Изучить основные положения и конструкции языка Cи.
Разработать программу в соответствии с вариантом индивидуального задания.
Отладить работу программы.
Проследить ход выполнения программы в симуляторе.
Оформить отчёт по лабораторной работе.
Ответить на контрольные вопросы.
1 Краткие теоретические сведения
MPLAB C30 – это профессиональный компилятор языка Си высокого уровня. При установке компилятора происходит его полная интеграция со средой разработки MPLAB IDE.
Основные особенности компилятора C30:
ANSI C совместимый, в комплекте поставляются стандартные библиотеки.
поддержка типов 32-bit double и 64-bit double, 64-битного целого (long long).
поддержка всех 16-битных семейств Microchip.
поддержка смешанного кода Си + asm.
поддержка расширенных настроек оптимизации кода.
наличие встроенных (intrinsincs) функций для работы с DSP-ядром. Для каждого микроконтроллера всех поддерживаемых семейств компилятор
MPLAB C30 имеет в своём составе заголовочные файлы с описанием всех доступных регистров микроконтроллера с указанием их адресов. Символьные
461
имена регистров полностью совпадают с названиями, предложенными в документации на микроконтроллер, таким образом, обращение к регистрам микроконтроллера из кода программы происходит в простой, удобной и наглядной форме. Название заголовочного файла подразумевает модель микроконтроллера. Например, для микроконтроллера dsPIC33fj32mc204 подключение заголовочного файла с описанием всех его регистров на языке С будет выглядеть следующим образом:
#include <P33FJ32MC204.h>
Однако для реализации специфических функций микроконтроллера, компилятор поддерживает некоторые дополнительные возможности. Наиболее часто используемые из них:
определение атрибутов переменных; определение атрибутов функций;
Inline-функции;
переменные в определённых регистрах;
целые размером в двойное слово.
Определение атрибутов переменных
Атрибуты переменных устанавливаются с помощью ключевого слова
__attribute__
• задают такие специфические свойства переменной, как расположение по указанному адресу либо в указанной области памяти, выравнивание переменной, параметры загрузки начального значения, инициализации либо очистки значения переменной и прочее. Например, для объявления переменной целочисленного типа, расположенной по адресу 0x900 секции «mysection», необходимо воспользоваться следующей конструкцией:
int foo __attribute__((section("mysection"),address(0x900)));
Определение атрибутов функций
С помощью атрибутов функций объявляются сведения о функции, вызываемой основной программой, что помогает компилятору оптимизировать вызов функции и более тщательно проверять код. Атрибуты функции задаются так же с помощью ключевого слова __attribute__, за которым следует вспомогательная спецификация в двойных круглых скобках. С помощью атрибутов возможно задать абсолютный адрес функции,
462
поместить функцию в сегмент загрузки программной flash памяти, указать компилятору на функцию-обработчик прерывания и прочее. Например, объявление функции-обработчика прерывания таймера T1 с указанием компилятору не генерировать дополнительный код будет выглядеть следующим образом:
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt( void ) { }
Inline-функции
Объявление функции с ключевым словом inline приводит к тому, что компилятор внедряет код этой функции в код вызывающих ее операторов. Это обычно ускоряет выполнение, устраняя накладные расходы на вызов. Кроме того, если любые фактические параметры — константы, знание их величин позволяет упрощать код на этапе компиляции, чтобы сократить объем включаемого кода. Объявление inline-функции происходит следующим образом:
inline int inc (int *a)
{
(*a)++;
}
Переменные в определённых регистрах
Компилятор позволяет помещать несколько глобальных переменных в определенные аппаратные регистры. Глобальные регистровые переменные резервируют регистры на все время исполнения программы. Для определения глобальной регистровой переменной необходимо воспользоваться следующей конструкцией:
register int *foo asm ("w8");
Здесь w8 - имя регистра, который будет использован.
Целые размером в двойное слово
Компилятор поддерживает типы данных для целых, которые в два раза длиннее чем long int. Тип таких переменных long long int для целого со знаком или unsigned long long int для целого без знака. Для записи констант типа long long int, добавляется суффикс LL к целому. Для записи констант типа unsigned long long int, добавляется суффикс ULL к целому.
Данные типы можно использовать в арифметике подобно любым другим
463
целым типам. Сложение, вычитание и поразрядные логические операции для этих типов реализованы открытым кодом, но деление и сдвиги реализованы не на основе открытого кода. Операции, не использующие для реализации открытый код, требуют специальных библиотечных подпрограмм, которые поставляются с компилятором.
Так же компилятор MPLAB C30 позволяет устанавливать биты конфигурации микроконтроллера в коде программы следующими директивами:
_FOSCSEL(st ate); _FOSC(state); _FWDT(state) ; _FICD(state);
Синтаксис использования директив аналогичен синтаксису вызова функций, однако установка битов конфигурации должна осуществляться вне кода какой-либо из функций.
Главный цикл
Язык C предполагает, что по завершении функции main() управление должно возвращаться операционной системе. Однако во встраиваемых приложениях требуется,
чтобы программа выполнялась бесконечно с момента включения питания и до его выключения, следовательно, приложения разрабатываются с тем расчѐтом, что главный цикл программы будет выполняться бесконечно.
Для реализации данного принципа с помощью языка C наибольшее распространение получил способ использования цикла while:
while (1)
{
// код программы
}
Всё, что помещено в теле цикла, будет повторяться до тех пор, пока условие цикла возвращает значение «истина». А так как условие цикла представляет собой константу, возвращающую «истина», тело цикла будет выполняться бесконечно.
464
2 Пример выполнения работы
Задача: Разработать программу для разбиения числа на цифры. Проверить корректность выполнения алгоритма в симуляторе. Промежуточные значения переменных на каждом шаге занести в таблицу.
Анализ задачи: Операция разбиения числа на цифры оформлена в виде функции. Передача значения числа в функцию осуществляется через параметр типа unsigned int. Результат разбиения возвращается через указатель на массив типа char, каждый элемент которого содержит цифру числа.
Листинг программы:
char* Convert(unsigned int a)
{
char digits[5] = {0, 0, 0, 0, 0}; int i = 0;
while (a)
{
digits[i] = a % 10; i = i + 1; a = a / 10;
}
return &(digits[0]);
}
void main()
{
char digits = Convert(53417);
}
|
|
|
|
|
Таблица 2.1 |
|
Значение переменных во время выполнения программы |
||||||
|
|
|
Значение |
|
|
|
|
|
|
переменой |
|
|
|
Шаг |
|
|
|
|
|
|
|
|
a |
i |
|
digits[5] |
|
1 |
0xD0A9 (53417) |
0 |
|
{0, 0, 0, 0, 0} |
|
|
2 |
0x14DD (5341) |
1 |
|
{0, 0, 0, 0, 7} |
|
|
3 |
0x0216 |
(534) |
2 |
|
{0, 0, 0, 1, 7} |
|
4 |
0x0035 |
(53) |
3 |
|
{0, 0, 4, 1, 7} |
|
5 |
0x0004 |
(5) |
4 |
|
{0, 3, 4, 1, 7} |
|
6 |
0x0000 |
(0) |
5 |
|
{5, 3, 4, 1, 7} |
|
465
3 Варианты индивидуальных заданий к лабораторной работе
Разработать программу в соответствии с вариантом задания. Проверить корректность выполнения алгоритма в симуляторе. Промежуточные значения переменных на каждом шаге занести в таблицу.
4 Контрольные вопросы
1.Укажите особенности компилятора MPLAB C30.
2.Для чего применяются атрибуты переменных?
3.Для чего применяются атрибуты функций?
4.Каким образом объявляется функция обработки прерывания?
5.Каким образом можно разместить переменную по абсолютному адресу?
6.Каким образом устанавливаются биты конфигурации?
466
Лабораторная работа 5
Изучение устройств ввода-вывода дискретных сигналов в микропроцессорных системах управления
Цель работы:
Изучить структуру и особенности работы портов микроконтроллера, схему подключения входных и выходных дискретных сигналов к микроконтроллеру, особенности программирования ввода-вывода дискретных сигналов на языке программирования. Составить программу ввода, обработки по заданному алгоритму и вывода дискретных сигналов, записать в память программ микроконтроллера и выполнить.
Порядок выполнения работы:
•Изучить теоретические вопросы, связанные с функционированием дискретных входов-выходов.
•Изучить принципиальную электрическую схему к лабораторной работе.
•Разработать программу в соответствии с индивидуальным заданием.
•Отладить программу в среде MPLAB IDE.
•Загрузить программу в учебный стенд.
•Исследовать работу дискретных входов и выходов.
•Оформить отчёт по лабораторной работе.
•Ответить на контрольные вопросы.
1 Краткие теоретические сведения
1.1 Параллельные порты ввода-вывода микроконтроллера dsPIC33fj32mc204
Все выводы микроконтроллера (кроме выводов питания Vdd, Vss, AVdd, AVss, VCap и вывода сброса MCLR) могут использоваться как периферийными модулями, так и параллельными портами ввода/вывода. Все вводные линии портов имеют триггер Шмидта по входу для исключения влияния электромагнитных помех и шумов.
Линии ввода/вывода микроконтроллера разделены на три порта: RA, RB, RC. Подавляющее большинство линий ввода/вывода всех портов имеют дополнительные функции и могут использоваться различными периферийными модулями микроконтроллера. Блок-схема структуры линии порта в таком случае приведена на рис. 1.1.
467
Рисунок 1.1 – Блок-схема структуры линии порта, объединённой с выводами периферийных функций
Мультиплексор выбирает, каким образом функционирует линия порта (в качестве части периферийного модуля, либо в качестве линии параллельного порта ввода/вывода). Таким образом, перед использованием таких линии в качестве линий порта ввода/вывода необходимо предварительно отключить соответствующие периферийные устройства. Например, при использовании порта RA2 как линии ввода, необходимо отключить дополнительную функцию порта RA2 (выход тактирующего сигнала внутреннего генератора) следующей директивой:
_FOSC(OSCIOFNC_ON & POSCMD_NONE)
Для работы с портами каждый из них имеет 3 специальных регистра:
TRISx1 – регистр направления данных – задаёт каким образом используется линия порта (как вход либо как выход). При установке соответствующего бита в 1 линия порта будет сконфигурирована как вход.
468
1 Действительные названия регистров получаются подстановкой названия порта вместо символа х. Соответственно, регистры порта А называются
TRISA, LATA, PORTA, порта В - TRISB, LATB, PORTB, порта C - TRISC, LATC, PORTC.
LATx – регистр выводов порта – при установке соответствующего бита в 1 данного регистра позволяет установить высокий уровень сигнала на выходе линии порта, при установке соответствующего бита в 0 – низкий уровень сигнала.
PORTx – регистр состояния порта – чтение соответствующего бита из данного регистра позволяет получить состояние сигнала (высокий либо низкий уровень) на входе линии порта.
Примечание. Для того, чтобы установка бита регистра LATx приводила к соответствующему изменению состояния линии вывода порта, необходимо чтобы эта линия была предварительно сконфигурирована как выход установкой требуемого бита в регистре TRISx. Аналогично, чтобы чтение бита регистра PORTx отображало действительное состояние линии ввода порта, необходимо чтобы эта линия была предварительно сконфигурирована как вход установкой требуемого бита в регистре TRISx.
Таким образом, настройка линии 2 порта RA на вход осуществляется следующим образом:
TRISA |= (1 << 2);
А настройка линии 15 порта RB на выход осуществляется следующим образом:
TRISB &= ~(1 << 15);
Так же MPLAB позволяет обращаться напрямую к битам регистров портов. Используя такой приём, вышеприведённые примеры будут выглядеть следующим образом:
TRISAbits.TRISA2 = 1;
TRISBbits.TRISB15 = 0;
Кроме того, некоторые линии портов микроконтроллера могут быть сконфигурированы как выход с открытым коллектором. В таком случае линии порта функционирует как транзистор, эмиттер которого подключён к земле, а
469
коллектор к выводу линии порта. Подключение внешнего подтягивающего резистора к такому выводу позволяет получить на выходе линии напряжение, отличное от напряжения питания микроконтроллера, что в свою очередь необходимо для согласования микросхем с различными напряжениями питания. Настроить как выходы с открытым коллектором можно те выводы микроконтроллера, которые обозначены как выводы, допускающие подачу на них 5-вольтового напряжения. Настройка вывода микроконтроллера как выход с открытым коллектором осуществляется установкой соответствующего бита в регистрах
ODCx2. Например, настройка линии 8 порта RA как выхода с открытым коллектором будет осуществляться следующим образом:
ODCAbits.ODCA8 = 1;
После настройки линии порта как выхода с открытым коллектором управление состоянием транзистора рекомендуется осуществлять с помощью регистра TRISx. Для открытия транзистора следует установить соответствующий бит регистра, для закрытия транзистора – сбросить. Таким образом, управление транзистором линии 8 порта RA (настроенной как выход с открытым коллектором), будет осуществляться следующем образом:
TRISAbits.TRISA8 = 1; // Открытие транзистора
TRISAbits.TRISA8 = 0; // Закрытие транзистора
2 Электрическая принципиальная схема к лабораторной работе
Для ввода дискретной информации в микроконтроллер широко применяются различные переключатели, кнопки и клавиатуры, либо иные дискретные датчики. Дискретными выходами микроконтроллер управляет различными исполнительными устройствами, работающими по принципу включено/выключено.
На рис. 2.1 приведена электрическая принципиальная схема к лабораторной работе.
470
