Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
печать шпоры мпт.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
708.61 Кб
Скачать

18. Реализация широтно-импульсной модуляции в pic-микроконтроллерах: параметры шим, функции управления шим на языке с18.

Скважностью импульсной последовательности называется отношение периода следования импульсов Т к их длительности tИ и обозначается буквой Q:

Q = T / tИ

Скважность – величина безразмерная и не имеет единиц измерения.

Часто вместо скважности используется термин коэффициент заполнения γ, который является величиной, обратной скважности:

γ = 1 / Q = tИ / T

Коэффициент заполнения обычно выражается в процентах:

γ = (tИ / T) 100%

Иногда в англоязычной литературе вместо коэффициента заполнения используется термин Duty Cycle (величина рабочего цикла).

Все микроконтроллеры семейства PIC18 имеют внутренние модули, которые могут вырабатывать импульсные последовательности с широтно-импульсной модуляцией (ШИМ). Количество этих модулей или по-другому каналов ШИМ может быть от 1 до 5.

Для облегчения разработки программ управления каналами ШИМ в библиотеке пакета МСС18 имеются несколько функций. В табл.1 приведены некоторые наиболее часто используемые функции. Полное описание их дано в заголовочном файле pwm.h.

Таблица 1

Функции ШИМ

Функция

Описание

ClosePWMx

Дезактивирует ШИМ канала х

OpenPWMx

Конфигурирует ШИМ канала х

SetDCPWMx

Записывает значение нового рабочего цикла в ШИМ канала х

Рассмотрим вкратце библиотечные функции ШИМ на примере канала 1.

ClosePWM1( ) – дезактивирует ШИМ канала 1. Прототип функции:

void ClosePWM1(void);

OpenPWM1( ) – конфигурирует ШИМ канала 1, задавая период и длительность импульсов. Для работы ШИМ используется только таймер 2. Прототип функции:

void OpenPWM1(char period);

Аргумент функции period – может быть любым числом в пределах от 0х00 до 0xFF.

SetDCPWM1( ) – записывает новое значение рабочего цикла в регистр ШИМ канала 1. Прототип функции:

void SetDCPWM1(unsigned int dutycycle);

Аргумент функции dutycycle – может быть любым 10-битным числом. Только младшие 10 бит числа dutycycle записываются в регистры канала ШИМ.

unsigned int i=512;

void init(void); // прототип функции инициализации МК

void main(void)

{

init( );

SetDCPWM1( i );

while(1);

}

void init(void) // функция инициализации МК

{

PORTC = 0;

TRISC = 0;

OpenTimer2(TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1);

// функция открытия таймера 2 при следующих параметрах:

// прерывания запрещены, коэффициент деления прескалера

// равен 1, коэффициент деления постскалера равен 1

OpenPWM1(0xFF); // период ШИМ равен 0xFF

SetDCPWM1(0); // рабочий цикл (коэффициент заполнения) =0

19. Прерывания в pic18: источники прерываний, управляющие биты, программирование прерываний на языке с18.

Микроконтроллеры PIC18 имеют несколько источников прерываний и функцию приоритетной системы прерываний, которая позволяет для каждого источника прерываний назначить высокий или низкий приоритет. При возникновении прерывания с высоким приоритетом происходит переход по вектору 000008h, а при возникновении прерывания с низким приоритетом – по вектору 000018h.

Каждому источнику прерываний соответствует три управляющих бита:

  • флаг прерываний, указывает на то, что выполнено условие возникновения прерывания;

  • бит разрешения прерывания, разрешает переход по вектору прерывания при установке соответствующего флага;

  • бит приоритета, выбор низкого или высокого приоритета прерывания.

Обработка прерывания заключается в следующем. Приостанавливается выполнение текущей программы, сохраняется текущий контекст и передается управление подпрограмме обработки прерывания ISR. После выполнения ISR восстанавливается информация о предыдущем контексте и возобновляется нормальная работа программы.

Рассмотрим основные особенности программирования прерываний при использовании компилятора С18.

Как и любая функция языка Си, подпрограмма обработки прерывания ISR может иметь локальные и глобальные переменные. Однако ISR не может иметь входных параметров и не может возвращать какого-либо значения, то есть объявляется как:

void isr(void)

{

……..

}

ISR может быть вызвана только реакцией на работу аппаратуры, но не из другой Си-функции.

В языке С18 не производится автоматическое размещение начала ISR по адресу вектора прерывания. Это объясняется тем, что источников прерывания, а следовательно, и ISR может быть несколько. Векторов прерывания, то есть адресов только два: 000008h для высокого приоритета и 000018h для низкого приоритета.

Обычно по адресу вектора прерывания размещается ассемблерная команда GOTO для перехода на нужную ISR. Используется in-line ассемблер, при этом блок команд ассемблерного кода должен начинаться с директивы _asm и кончаться директивой _endasm:

_asm

…………

………… // команды Ассемблера

…………

_endasm

Для размещения вектора прерывания в программном коде используется директива

#pragma code section_name = address

Здесь section_name – идентификатор языка Си, address – целая константа (integer).

Для возврата в исходную секцию кода используется директива

#pragma code

В языке С18 для задания приоритета функции обработки прерывания имеются две директивы:

#pragma interrupt fname

#pragma interruptlow fname

Директива #pragma interrupt объявляет функцию обработки прерывания как имеющую высокий приоритет, а директива #pragma interruptlow – как имеющую низкий приоритет.

Пример программирования прерываний в языке С18.

#include <p18fxxx.h>

void high_isr(void); // прототип ISR с высоким приоритетом

void low_isr(void); // прототип ISR с низким приоритетом

#pragma interrupt high_isr // функция high_isr объявляется с высоким приоритетом

#pragma interruptlow low_isr // функция low_isr объявляется с низким приоритетом

#pragma code high_vector = 0x08 // дальнейший программный код будет начинаться с адреса 000008h

void high_interrupt(void)

{

_asm

goto high_isr // переход на функцию с именем high_isr

_endasm

}

#pragma code low_vector = 0x18 // дальнейший программный код будет начинаться с адреса 000018h

void low_iterrupt(void)

{

_asm

goto low_isr // переход на функцию с именем low_isr

_endasm

}

#pragma code // возврат в исходную программную секцию кода

………………………………..

void main(void) // главная функция программы

{

……………………..

}

void high_isr(void) // функция обработки прерывания с высоким приоритетом

{

………

}

void low_isr(void) // функция обработки прерывания с низким приоритетом

{

…….

}

Управление приоритетной системой прерываний в микроконтроллерах семейства PIC18 выполняется с помощью бита с именем IPEN, который находится в регистре специальных функций RCON.

Если IPEN = 0, то приоритетная система прерываний выключена, и все прерывания имеют одинаковые приоритеты. По умолчанию предполагается, все прерывания будут иметь высокий приоритет, т.е. при возникновении любого прерывания происходит переход по вектору 000008h. Для общего (глобального) разрешения прерываний надо установить бит GIE = 1, который находится в регистре INTCON.

Если IPEN = 1, то приоритетная система прерываний включена. Для общего (глобального) разрешения прерываний с высоким приоритетом надо установить бит GIEH = 1. Для общего разрешения прерываний с низким приоритетом надо установить бит GIEL = 1. Эти биты находятся в регистре INTCON.

20.Динамическое управление линейным дисплеем на семисегментных индикаторах в PIC-микроконтроллерах.

Для отображения цифровой и буквенной информации в микроконтроллерных системах широко используются семисегментные индикаторы, которые бывают светодиодные, вакуумно-люминесцентные, жидкокристаллические, вакуумно-накаливаемые, газоразрядные. Наибольшее распространение получили семисегментные светодиодные индикаторы (ССДИ) ввиду большой яркости, малыми габаритами, способности работать в широком диапазоне температур, механической прочности. На рис. 1,а показано расположение и обозначение сегментов ССДИ. Семь отображающих элементов позволяют высвечивать десятичные и шестнадцатиричные цифры, некоторые буквы латинского и русского алфавитов, а также некоторые специальные знаки. При формировании, например, цифры 3 будут подсвечиваться сегменты a, b, c, d и g, а сегменты e и f останутся темными. При формировании буквы F будут подсвечиваться сегменты a, e, f и g, а темными останутся сегменты b, c и d.

По способу соединения отдельных светодиодов в ССДИ различают индикаторы с общими катодами (ОК) и с общими анодами (ОА). Их схемы внутренних соединений показаны на рис. 1,б, в. На рис. 1,г приведено условное графическое изображение ССДИ.

Рис. 1. Семисегментный светодиодный индикатор: а) - условное обозначение сегментов; б) – индикатор с общими катодами (ОК); в) – индикатор с общими анодами (ОА); г) - условное графическое обозначение на схемах

При формировании символов в ССДИ требуются специальные семисегментные коды, которые отличаются от обычных позиционных двоичных кодов, используемых в МК. Для получения семисегментных кодов могут быть применены два метода:

  1. аппаратурный;

  2. программный.

Аппаратурный метод основан на использовании специальных микросхем преобразователей кодов, которые преобразуют двоичный позиционный код в семисегментный. В качестве таких преобразователей наиболее широко применяются микросхемы КР514ИД1 и КР514ИД2, которые обычно называют дешифраторами кода. Микросхема КР514ИД1 используется для индикаторов с ОК, а КР514ИД2 – для индикаторов с ОА. Недостатком этих дешифраторов является то, что они позволяют получить только семисегментные коды десятичных цифр от 0 до 9. При этом на их входы должен подаваться двоично-десятичный код.

Программный метод получения семисегментного кода основан на том, что каждому сегменту индикатора поставлен в соответствие определенный бит D7, D6,…, D0 байта. Для индикаторов с ОК принято, что если этот бит равен 1, то сегмент светится. Определенные комбинации единичных значений битов формируют на индикаторе отображаемый символ, как это приведено в табл. 1.

Семисегментные коды для отображения символов от 0 до 9

для индикаторов с ОК

D7 - h

D6 –g

D5 –f

D4 –e

D3 –d

D2 – c

D1 -b

D0 –

a

HEX

Сим-

вол

0

0

0

0

0

1

1

0

1

1

0

0

1

0

1

1

1

1

1

1

1

1

0

1

3F

06

6F

0

1

9

Таблица семисегментных кодов обычно хранится в памяти программ.

Для отображения многосимвольной информации используются линейные (однострочные) дисплеи. Такие дисплеи представляют собой “линейку”, смонтированную из отдельных ССДИ. Число знакомест (позиций или разрядов) дисплея определяется в соответствии с требованиями к МКС.

Существует два способа организации МК с линейными дисплеями: статический и динамический (мультиплексный).

Первый требует наличие на входах каждого индикатора специальных буферных регистров для хранения кодов выводимых символов. Естественно, что с увеличением разрядности дисплея возрастает число дополнительных микросхем, а, следовательно, и стоимости МКС.

Второй способ (динамический) основан на том, что любой световой индикатор является инерционным прибором, а человеческому глазу отображаемая на дисплее информация, если ее обновлять с частотой не менее 20 раз в секунду, представляется неизменной. Динамический способ вывода информации на дисплей требует значительно меньших аппаратных затрат, но более сложного программного обеспечения.

rom near char table[ ] =

{

0x3F, 0x06, 0x5B,0x4F, 0x66, 0x6D,0x7D,0x07, 0x7F, 0x6F,

};

char count; // переменная-счетчик

void main(void)

{

char select; // код для выбора индикатора (его включения)

char a; // переменная-счетчик индикаторов дисплея

PORTB = 0xFF;

TRISB = 0; // настроить порт В на вывод

PORTC = 0;

TRISC = 0; // настроить порт С на вывод

count = 0;

while( 1 ) // бесконечный цикл вывода на дисплей

{

/* вывод цифр одновременно на все индикаторы дисплея */

POTRB = 0xFF; // гашение дисплея

PORTC = table[ count ]; // вывод на сегменты индикаторов

PORTB &= 0b11110000; // включение индикаторов дисплея

Delay10KTCYx(50); // задержка на 0,5 секунды

/* вывод цифр поочередно на индикаторы дисплея*/

select = 0b11111110; // код для выбора 1-го индикатора

for ( a = 0; a < 4; a++)

{

POTRB = 0xFF; // гашение дисплея

PORTC = table[ count ]; // вывод на сегменты индикаторов

PORTB = select; // включение индикатора

select = (select << 1) | 0b00000001; // сдвиг кода влево и вставка 1 в младший разряд

Delay10KTCYx(50); // задержка на 0,5 секунды

}

count++; // следующая цифра для вывода

if( count >= 10 )

count = 0;

} }