Система управления стабилизатором переменного напряжения
МИНИСТЕРСТВО
ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
Брянский
государственный технический университет
КАФЕДРА «ЭРЭ
и ЭС»
Пояснительная
записка к курсовой работе
по
дисциплине «Отладочные средства микропроцессорных систем»
на тему
«Система управления стабилизатором переменного напряжения»
Брянск 2015
ВВЕДЕНИЕ
Микроконтроллер - функционально законченное
устройство обработки информации, управляемое хранимой в памяти программой.
Появление микроконтроллеров стало возможным благодаря развитию интегральной
электронике. Это позволило перейти от схем малой и средней степени интеграции к
большим и сверхбольшим интегральным микросхемам (БИС и СБИС).
Микроконтроллеры и микроЭВМ, вследствие малой
материалоемкости и стоимости, низкого энергопотребления и высокой надежности
находят всё большее применение в промышленности. Эти устройства позволяют
создавать миниатюрные, дешёвые и экономичные, но в то же время достаточно
«умные» и сложные приборы, способные управлять силовыми преобразователями,
коммутирующими большие токи и напряжения.
Область применения микроконтроллеров не
ограничивается только силовой электроникой, с каждым годом значительно
расширяясь.
1. ОПИСАНИЕ СХЕМЫ ПРЕОБРАЗОВАТЕЛЯ
Необходимо разработать систему управления
стабилизатором переменного напряжения, в котором используется регулирующий
орган с вольтодобавкой на основе ячейки с ОРМ (однополярной реверсивной
модуляцией) однократного преобразования. Схема такой ячейки и режимы её работы
приведены в табл.1.1.
Таблица 1.1
Схема
регулирующего органа С ОРМ с однократным преобразованием
|
Режим
|
Цикл
замыкания ключей
|
|
РД
|
1,4-3,4
|
|
НП
|
2,3-1,4
|
|
РО
|
2,3-1,2
|
РД - регулируемая добавка; НП - неискаженная
(прямая передача); РО - регулируемая отбавка.
Выходное напряжение с регулирующего органа
проходит через LC фильтр, который подавляет лишние гармоники и на нагрузке
формируется синусоидальное напряжение.
Напряжение сети изменяется в
пределах 220В ±%, т.е.
187…242В.
Напряжение на выходе регулируется в
пределах 50…200В.
Частоту квантования выберем в q=10
раз больше частоты сети:
.
Выходное напряжение регулируется в
соответствии с формулой:
,
где “-“ - отбавка, “+“ - добавка;
Диапазон изменения ,
обеспечивающий заданную регулировку напряжения:
Отбавка:
Добавка:
Основная задача системы управления -
контролировать выходное напряжение (по действующему, либо по мгновенному
значению) и в случае его отклонения от заданного изменять сдвиг открытых
состояний ключей определённым образом, осуществляя при этом добавку либо
отбавку.
Второстепенная задача - обеспечить
взаимодействие пользователя с устройством. Должна быть возможность задавать
необходимую величину выходного напряжения с помощью клавиатуры, а также
возможность отображения текущего выходного напряжения.
Стабилизация будет осуществляться по
действующему значению выходного напряжения следующим образом: к выходу
стабилизатора подключаем RMS-DC-конвертер. Он формирует постоянное напряжение,
соответствующее действующему значению напряжения сети. Микроконтроллер в
определении действующего значения не участвует, а только получает результат в
аналоговом виде.
Преимущество такого способа -
довольно высокая точность определения действующего значения выходного
напряжения.
Недостаток в том, такие устройства
обладают задержкой определения действующего значения около 100мс и дорого
стоят.
Определять действующее значение
можно проще - опрашивать выход и находить максимальное, т.е. амплитудное. Но
форма напряжения сети может отклоняться от синусоидальной, а значит
определённое таким способом действующее значение может отличаться от реального.
Можно также использовать способ
получения мгновенных значений в течение полупериода через определённые
интервалы времени с последующим вычислением действующего значения в конце
полупериода и поправкой. Но в данном случае информация о выходном напряжении
поступает лишь через половину периода и система управления только тогда
реагирует на изменения.
2. ФУНКЦИОНАЛЬНАЯ СХЕМА СИСТЕМЫ
Рис. 2.1 - Функциональная схема
стабилизатора
Описание функциональной схемы:
Изолирующий усилитель производит
гальваническую развязку выходной цепи и микроконтроллера.
Конвертер RMS-DC выполняет функцию
получения величины действующего значения выходного напряжения и преобразует
текущее его значение в соответствующее постоянное.
Драйвер АЦП осуществляет опрос
выходного напряжения выпрямителя и обновляет значение сигнала обратной связи
XОС .
Драйвер клавиатуры опрашивает порт
клавитуры и обновляет значение сигнала задания XЗ.
ПИ-регулятор нужен для задания
скорости изменения управляющего воздействия при отклонении XОС от XЗ.
Драйвер индикатора осуществляет
индикацию вводимых с клавиатуры цифр и текущего действующего значения
напряжения на выходе преобразователя.
3. ОПИСАНИЕ ОСНОВНЫХ ФУНКЦИОНАЛЬНЫХ
БЛОКОВ СИСТЕМЫ И ВЫБОР ЭЛЕМЕНТНОЙ БАЗЫ
Выбор микроконтроллера.
Исходя из предложенного задания на
курсовую работу, выбираем микроконтроллер AT89C51RB2-SLSCM фирмы Atmel.
Описание:
Рис. 3.1 -- Расположение выводов ИС
AT89C51RB2-SLSCM
Особенностями используемого микроконтроллера
являются:
• Совместимость с серией MCS-51
• 16 кБ флэш-памяти с внутрисхемным
программированием (ISP)
• Износостойкость: 100000 циклов
записи/стирания
• Рабочий диапазон питания 3/5 В
• Полностью статическое функционирование
: 0 …60 МГц
• Три уровня защиты памяти программ
• Внутреннее ОЗУ размером 1280x8
• 32 программируемые линии ввода-вывода
• Три 16-разрядных таймера-счетчика
• PCA матрица
• Десять источников прерываний
• Четыре уровня прерываний
• Полнодуплексный канал последовательной
связи на УАПП
• SPI
• Режимы снижения потребления: холостой
ход и экономичный
• Восстановление прерываний при выходе из
экономичного режима
• Сторожевой таймер
• Двойной указатель данных
• Флаг выключения питания
Порты 1, 2 и 3 являются 8-разрядным двунаправленными
портами ввода/вывода. Линии этих портов имеют внутренние нагрузочные резисторы,
а линии порта Р0 требуют внешних.
В режиме холостого хода (Idle) останавливается
ЦПУ, но ОЗУ, таймеры-счетчики, последовательный порт и система прерываний продолжают
функционировать. В экономичном режиме (Power-down) сохраняется информация в
ОЗУ, но остановлен генератор, выключены все остальные функциональные блоки до
внешнего запроса на прерывание или аппаратного сброса.
Выбор ключей.
Выбраны транзисторы со встроенными обратными
диодами фирмы International Rectifier IRG4PH50UD со следующими параметрами:
Для управления ключами выбран драйвер фирмы
Avago Technologies ACNW3130. Канал драйвера гальванически развязан от входной
цепи.
Максимальный пиковый выходной ток драйвера :
2,5А.
Минимальный пиковый выходной ток драйвера : 2А.
Максимум низкого уровня выходного напряжения:
0,5В.
Максимальный ток питания: 5мА.
Диапазон напряжения питания: 15-30В.
Максимальное время переключения: 500нс.
Температурный диапазон: -40-100˚С.
Рис. 3.2 - Блок-диаграмма драйвера
При рекомендуемых производителем параметрах ,
выбираем внешний резистор . Пиковый ток
затвора транзистора составляет:
.
Подключаем по два транзистора к каждому
драйверу. На 8 транзисторов нужно 4 штуки.
Резистивный делитель обеспечивает понижение
уровня выходного напряжения стабилизатора до уровня изоляционного усилителя
(±200мВ). Пусть R12=100 кОм, а R13=40,2 Ом, тогда максимальное напряжение на
входе изоляционного усилителя составит 480/(100000/40,4)=0,193В, что входит в
допустимые пределы.to-DC конвертер обеспечивает определение действующего
значения напряжения. Выбираем микросхему AD736А фирмы Analog Devices. Параметры
конвертера:
Напряжение питания: +2,8В, -3,2В…±16,5В;
Максимальное входное напряжение: 200мВ;
Входное сопротивление 1012 Ом
Температурный диапазон: -40…+85˚С
Рис. 3.3 - Схема конвертера
Изолирующий усилитель обеспечивает
гальваническую развязку выходного напряжения. Выбираем изолирующий усилитель
HCPL-7850 фирмы Avago Technologies. Параметры усилителя:
Напряжение питания: +5В;
Входное напряжение: -200…+200мВ;
Выходное напряжение: +5,5В;
Температурный диапазон: -55…+125˚С
погрешность нелинейности: 0,1%
Рис. 3.4 - Схема изоляционного усилителя
Операционный усилитель обеспечивает повышение
напряжения обратной связи до уровня АЦП (5В). Так как изолирующий усилитель
усиливает напряжение в 8 раз, то максимально возможное напряжение на его выходе
составит 0,193∙8=1,544В. Выберем схему неинвертирующего усилителя на
LM324. При усилении напряжения в 3 раза 1+R19/R18=3, принимаем значения
сопротивлений R7=2,05 кОм и R3=1 кОм.
Выбор АЦП
Выбран АЦП ADC0831:
Разрешение: 8бит
Напряжение питания: 5В
Время конвертации: 32мкс
Температурный диапазон: 0…+70˚С
Ввод и отображение информации
Для ввода требуемого на выходе напряжения
используется клавиатура с 12-ю клавишами:
цифровых (0-9) и 2 сервисных (Ввод, Сброс).
Клавиатуру набираем из отдельных тактовых кнопок TS-A3PS-130.
Для отображения введённого с клавиатуры и
текущего значения выходного напряжения выбран жидкокристаллический индикатор
МТ-16S2D от фирмы МЭЛТ.
Рис. 3.5 - Внешний вид индикатора
4. СХЕМА ЭЛЕКТРИЧЕСКАЯ
ПРИНЦИПИАЛЬНАЯ
Рис. 4.1 - Схема принципиальная
микропроцессорного устройства
Рис. 4.2 - Схема принципиальная силовой части
. ОПИСАНИЕ ПРОГРАММЫ
Программа для микроконтроллера была написана на
языке Си в среде uVision.
Программа осуществляет управление стабилизатором
переменного напряжения. С RMS-DC датчика считывается действующее значение
напряжение на выходе устройства. Циклически вычисляется статическая ошибка.
Суммарная ошибка за все время работы
системы:
Новое значение напряжения на выходе
системы:
Действующее значение сетевого
напряжения:
Коэффициент заполнения импульсами
для следующего цикла работы:
Таймерами формируется управляющий
сигнал для силовых ключей.
В программе предусмотрен ввод с
клавиатуры действующего значения напряжения на выходе стабилизатора. А также
отображение введенного значения на индикаторе.
6. АЛГОРИТМ ФУНКЦИОНИРОВАНИЯ
ПРОГРАММЫ
Рис. 6.1 - Алгоритм основной программы
Подключается библиотека с регистрами микроконтроллера
и библиотека работы со строками.
1 #include <REG52.H>
#include <string.h>
Объявляются константы.
#define DataInd P0
#define klav P2
#define Kp 0.2
#define Ki 0.015
#define Ktr 1.5
#define T ((60/12)*1000000/500)
#define Tic (0-T)
Линиям портов присваиваются символьные имена.
12 sbit RS = P3^7;
sbit RW = P3^6;
sbit E = P3^5;
sbit CS = P1^7;
sbit CLK = P1^6;
sbit DO = P1^5;
sbit K1 = P1^1;
sbit K3 = P1^2;
sbit K2 = P1^3;
sbit K4 = P1^4;
Объявляются переменные.
unsigned char data i=0;
24 unsigned char data nop;
unsigned short data DataKlav=0x200;
unsigned short data Uout=200;
unsigned char data buf;
unsigned short data buf2;
unsigned char code
str1[]="Uout= V";
unsigned char code
str2[]="Uizm= V";
unsigned char code strZero[]="
";
unsigned char data str[10];
unsigned short data rms;
unsigned short data rmsBCD;
unsigned short data Uin = 200;
float data gamma;
signed short data oh;
signed short data oh_do = 0;
signed short data S;
unsigned short data Ui;
unsigned short data Tic2;
signed short data Upr;
signed short data Uint;
И флаг.
bit regim;
Объявляются функции.
void WeitBW(void);
void PutCom(unsigned char data
OutByte);
void PutStrobe(void);
void PutData(unsigned char data
OutByte);
void PutString(unsigned char Str[]);
unsigned char ADC(void);
void DecodSts(unsigned short Uxxx);
Начинается основная программа. Сразу после
включения устройства происходит инициализация. Все силовые ключи отключаются.
Определяется режим работы таймеров. Таймеры Т0 и Т1 работают в режиме
шестнадцатибитных таймеров-счетчиков. Для таймера Т1 задается начальное
значение.
void main(void)
{
1 //Инициализация
1 K1 = K2 = K3 = K4 = 0;
59 1 TMOD = 0x11;
1 TH0 = (Tic >> 8);
1 TL0 = Tic;
Разрешаются прерывания (глобально). Также
разрешаются прерывания от Таймеров Т0 и Т1, а также внешние прерывания по INT0
и INT1.
62 1 EA = 1;
1 ET0 = ET1 = 1;
1 EX0 = EX1 =1;
Вычисляется начальный коэффициент заполнения
импульсами.
65 1 gamma =
(1-((float)Uout/Uin))*Ktr;
Производится инициализация индикатора. Команда
0х38 устанавливает режим отображения с матрицей 5х8 точек и работу с 8-ми
разрядной шиной данных; 0х0C включает отображение на экране ЖКИ-модуля, без
отображения курсоров; 0х06 устанавливает режим автоматического перемещения
курсора слева направо после вывода каждого символа; 0х01 очищает содержимое
экрана и переводит курсор в первое положение.
67 1 PutCom(0x38);
1 PutCom(0x0c);
1 PutCom(0x06);
70 1 PutCom(0x01);
Таймер Т0 запускается.
1 TR0 = 1;
Далее идет бесконечный цикл основной программы.
1 while(1)
1 {
Который начинается с опроса клавиатуры. В строки
записываются лог. 0, а в столбцы лог. 1. Состояние клавиатуры считывается в
буфер.
2 klav = 0x0f;
2 buf = klav;
Далее в строки записываются лог. 1, а в столбцы
лог. 0. Производится операция побитного ИЛИ предыдущего и нынешнего состояния
клавиатуры. Результат также сохраняется в буфере.
2 klav = 0xf0;
2 buf = buf | klav;
Полученный код сравнивается с числом 0хff. Если
ни одна кнопка нажата не была то будет возвращено занчение 0xff. Иначе в каждой
тетраде будет по одному нулю, соответствующему нажатой кнопке (строка и
столбец).
2 if(buf != 0xff)
2 {
Если какая-либо кнопка была нажата, то
проверяется состояние флага "режим" и кнопки "режим" (код
"0xb7"). Если одно из условий выполнено, то будет произведено
определение, какая именно кнопка была нажата.
3 if(regim == 1||buf == 0xb7)
3 {
Значение переменной, в которой хранится
введенное число, сдивигается на 4 бита влево. К текущему значению переменной
прибавляется число, соответствующее нажатой кнопке.
4 DataKlav = DataKlav << 4;
85 4 switch(buf)
4 {
5 case(0x7d): DataKlav += 0; break;
5 case(0xee): DataKlav += 1; break;
5 case(0xde): DataKlav += 2; break;
5 case(0xbe): DataKlav += 3; break;
5 case(0xed): DataKlav += 4; break;
5 case(0xdd): DataKlav += 5; break;
5 case(0xbd): DataKlav += 6; break;
5 case(0xeb): DataKlav += 7; break;
5 case(0xdb): DataKlav += 8; break;
96 5 case(0xbb): DataKlav += 9; break;
Если была нажата кнопка "сброс", то
значение переменной обнуляется.
5 case(0xe7): DataKlav = 0; break;//Сброс
Если была нажата кнопка "режим", то
значение переменной сдвигается на 4 позиции вправо (компенсируется сдвиг
данных).
98 5 case(0xb7): //Режим
5 {
6 DataKlav = DataKlav >> 4;
Проверяется состояние флага "режим",
если он установлен, то введенное с клавиатуры значение пересчитывается в
бинарный код.
101 6 if(regim == 1)
6 {
7 Uout = ((DataKlav & 0x0f00)
>> 8)*100 + ((DataKlav & 0x00f0) >>4)*10 + (DataKlav &
0x000f);
Далее проверяются границы введенного значения.
Если введено число меньше 50, то устанавливается 50.
104 7 if (Uout < 50)
7 {
8 Uout = 50;
8 DataKlav = 0x50;
108 8 }
Если введено число больше 200, то
устанавливается 200.
109 7 if (Uout > 200)
7 {
8 Uout = 200;
8 DataKlav = 0x200;
113 8 }
7 }
Значение флага "режим" инвертируется.
6 regim = !regim;
6 break;
6 }
5 }
4 }
Далее ожидается, когда кнопка будет отпущена,
после этого на все линии клавиатуры подается лог. 1.
120 3 while(klav!=0xf0);
3 klav = 0xff;
122 3 }
Введенные данные, а также данные, полученные с
АЦП по прерываниям от Таймера Т0 выводятся на индикатор.
Курсор устанавливается в начало первой строки
(команда "0x80"). Надпись первой строки из ПЗУ копируется в
переменную в ОЗУ.
124 2 PutCom(0x80);
2 strcpy(str,str1);
Вызывается фунуция "DecodSts", которая
добавляет числовые данные в строку текста. В качестве параметра функции
передается введенное значение с клавиатуры в BCD коде.
2 DecodSts(DataKlav);
Вызывается фунуция "PutString",
которая выводит строку текста на индикатор.
2 PutString(str);
Далее отображается вторая строка аналогичным
образом. Только теперь курсор переводится в начало второй строки (команда
"0xc0").
2 PutCom(0xc0);
Проверяется флаг "режим", если он не
установлен, то в строковую переменную копируется из ПЗУ вторая строка. И
вызывается функция "DecodStr", теперь в качестве параметра ей
передаются данные, полученные с АЦП и перевеленные в BCD формат.
130 2 if(regim ==0)
2 {
3 strcpy(str,str2);
133 3 DecodSts(rmsBCD);
3 }
Иначе выводится пустая строка.
135 2 else strcpy(str,strZero);
2 PutString(str);
Далее цикл фоновой задачи повторится заново.
2 }//while
1 }//main
Теперь рассмотрим обработку прерываний от
таймера Т0 (рис6.2).
141 void Timer0(void) interrupt 1
using 0
142 {
Рис. 6.2 - Алгоритм прерываний от таймера Т0
Таймер останавливается, значения в его регистрах
обновляются для следующего цикла работы. Таймер запускается.
1 TR0 = 0;
1 TH0 = (Tic >> 8);
1 TL0 = Tic;
1 TR0 = 1;
Вызывается функция "ADC", которая
опрашивает АЦП и возвращает принятое значение. Полученные данные приводятся к
шкале (умножаются на 2,5).
1 rms = ADC();
1 rms = rms * 2.5;
Создается копия в BCD формате для отображения на
индикаторе. Для этого в двухбайтный буфер помещается число сотен (результат
целочисленного деления на 100), сдвинутое на 8 позиций влево. В буфер
(однобайтный) - остаток от деления. Далее к значению в двухбайтном буфере
прибавляется количество десятков (результат целочисленного деления на 10),
сдвинутый на 4 позиции влево и остаток от деления.
150 1 buf2 = (rms/100) << 8;
1 buf = rms%100;
1 rmsBCD = buf2 + ((buf/10) <<
4) + buf%10;
Далее реализован ПИ-регулятор. Вычисляется
ошибка, как разность заданного действующего значения выходного напряжения и
измеренного.
1 oh = Uout - rms;
Суммарная ошибка вычисляется как сумма всех
ошибок с запуска устройства. К предыдущему значению суммарной ошибки
прибавляется текущая ошибка.
1 S = S + oh;
Вычисляется пропорциональная и интегральная
составляющие действующего значения выходного напряжения, А также действующее
значение выходного напряжения.
156 1 Upr = Kp*oh;
1 Uint = Ki*S;
158 1 Ui = rms + Upr + Uint;
По предыдущему значению гаммы и измеренному
значению напряжения вычисляется входное напряжение.
1 Uin = rms / (1-(gamma/Ktr));
Вычисляется новое значение гаммы.
160 1 gamma = ((1-((float)Ui/Uin))*Ktr);
Далее проверяется режим работы. Если гамма равна
нуля, значит режим прямой передачи. В этом случае таймер Т1 сработает через
половину периода. Ключи К2 и К3 выключаются, а ключи К1 и К4 включаются.
162 1 if (gamma == 0)
1 {
2 Tic2 = (0 - T/2);
2 TH1 = (Tic2 >> 8);
166 2 TL1 = Tic2;
2 K2 = K3 = 0;
2 K1 = K4 = 1;
Если гамма положительная, значит режим
вольтодобавки. Таймер Т1 сработает через время, равное произведению гаммы на
период. Ключи К2 и К3 включаются, а ключи К1 и К4 выключаются.
172 1 else if (gamma > 0)
1 {
2 Tic2 = (0 - gamma*T);
2 TH1 = (Tic2 >> 8);
2 TL1 = Tic2;
2 K2 = 1;
178 2 K4 = 0;
2 K3 = 1;
2 K1 = 0;
2}
Если же предыдущие условия выполнены не были,
значит режим вольтоотбавки. Таймер Т1 также сработает через время, равное произведению
гаммы на период. Ключи К2 и К3 выключаются, а ключи К1 и К4 включаются.
183 1 else
1 {
2 Tic2 = (0 + gamma*T);
2 TH1 = (Tic2 >> 8);
2 TL1 = Tic2;
2 K2 = 0;
2 K4 = 1;
2 K3 = 0;
2 K1 = 1;
2}
Запускается таймер
Т1.
На
этом прерывания от таймера Т0 завершаются.
1 TR1 = 1;
1}
Рис. 6.3 - Алгоритм прерываний от таймера Т1
Прерываний от таймера Т1 (рис.6.3). Состояние
ключей К1 и К3 инвертируется.
196 void Timer1(void) interrupt 3
using 0
197 {
1 K3 = !K3;
1 K1 = !K1;
Если режим прямой передачи (гамма равна нулю),
то состояние ключей К2 и К4 также инвертируется.
200 1 if (gamma == 0)
1 {
2 K2 = !K2;
2 K4 = !K4;
204 2 }
Останавливается таймер Т1. На этом прерывания от
таймера Т1 завершаются.
1 TR1 = 0;
1}
При обнаружении прерываний от INT0 и INT1 все
ключи выключаются. Эти прерывания формируют узлы защиты по мощности и
напряжению.
208 //Прерывания
Int0
void Inn0(void) interrupt 0 using 0
{
1 K1 = K2 = K3 = K4 = 0;
1 }
//Прерывания
Int1
void Inn1(void) interrupt 2 using 0
215 {
1 K1 = K2 = K3 = K4 = 0;
1 }
Далее рассмотрим функции.
Функция "Wait_BW" ожидает сброса флага
занятости индикатора. Все линии шины данных индикатора устанавливаются в лог.
1. Линия RS сбрасывается, что соответствует выбору регистра команд. Линия RW
устанавливает в состояние лог. 1, что соответствует чтению данных из
индикатора. Индикатор в ответ должен установить старший бит в ноль по
отрицательному перепаду сигнала Е. Далее в цикле линию Е сбрасываем и с
задержкой устанавливаем заново. После задержки проверяем старший бит линии
данных. Если он сброшен, то происходит выход из цикла, в противном случае цикл
повторяется. Количество попыток чтения принято равным 250. После 250-й неудаче
попытки будут прекращены.
219 void WeitBW(void)
{
1 DataInd = 0xff;
1 RS = 0;
1 RW = 1;
1 for(i=0;i<250;i++)
1 {
2 E = 0;
2 nop++;
2 E = 1;
2 nop++;
2 if((DataInd & 0x80) == 0)
break;
231 2 }
1 }
Функция "PutStrobe" формирует строб
записи данных в индикатор. Она сбрасывает линию тактирования Е и после задержки
устанавливает ее снова, что соответствует фиксации данных в индикаторе.
234 void PutStrobe(void)
{
1 E = 0;
1 nop++;
238 1 nop++;
1 nop++;
1 nop++;
1 E = 1;
1 }
Функция "PutCom" выдает команды на
индикатор. Она вызывает функцию ожидания сброса флага занятости
"Wait_BW". Затем сигнал RW сбрасывается, что соответствует записи
данных в индикатор. В шину данных индикатора копируется выдаваемая команда.
Далее вызывается функция выдачи строба "PutStrobe".
244 void PutCom(unsigned char data
OutByte)
{
1 WeitBW();
1 RW = 0;
1 DataInd = OutByte;
1 nop++;
250 1 nop++;
1 PutStrobe();
1}
Функция "PutData" запускает уже
рассмотренную функцию ожидания готовности индикатора "Wait_BW".
Устанавливает сигнал RS, выбирая тем самым регистр данных и сбрасывает сигнал
RW, определяя работу на запись. Данные помещаются на линию данных индикатора.
Вызывается функция выдачи строба "PutStrobe".
254 void PutData(unsigned char data
OutByte)
{
1 WeitBW();
1 RS = 1;
1 RW = 0;
1 DataInd = OutByte;
260 1 nop++;
1 nop++;
1 PutStrobe();
1}
Функция "PutString" выводит текстовую
строку на индикатор. Определяются локальные переменные.
void PutString(unsigned char Str[])
266 {
1 data char i;
1 data unsigned char C;
269 1 i = 0;
В цикле символ из строки копируется в переменную
"С" и выводится на индикатор функцией "PutData". При
достижении нуля (последний символ строки) цикл прекращается.
1 do
1 {
2 C = Str[i++];
273 2 PutData(C);
2 } while (Str[i]!= 0);
275 1 }
Функция "ADC" получает данные с АЦП.
Здесь также определяются локальные переменные.
277 unsigned char ADC(void)
{
1 unsigned char data byte;
280 1 unsigned char i;
Все линии АЦП устанавливаются в состояние лог.
1. Данные в переменной АЦП обнуляются.
1 CS = 1;
1 CLK = 1;
1 DO = 1;
1 byte = 0;
Линия "CS" устанавливается в лог. 0,
после чего АЦП начинает преобразование данных. Ожидается готовность данных.
Линия "DO" будет установлена в лог. 1.
1 CS = 0;
1 while (~DO);
Далее начинает тактироваться линия
"CLK".
1 CLK = 1;
1 CLK = 0;
1 nop++;
Начиная со второго такта биты данных в цикле
принимаются в младший бит переменной.
290 1 for (i = 1; i < 9; i++)
1 {
2 CLK = 1;
2 CLK = 0;
2 nop++;
2 byte = byte << 1;
2 byte = byte | DO;
297 2 }
Функция возвращает принятое значение напряжения
с АЦП.
1 return byte;
1 }
Функция "DecodStr" добавляют в строку
с текстом числовые значения. Она к качестве параметра получает трехзначное
число в BCD коде. Функция переводит в кодировку ASCII младший символ
переданного ей числа. Затем этот символ помещается в строку на i-тую позицию.
Данные в переменной сдвигаются на 4 позиции влево. Операции производятся в
цикле начиная с символа в строке с индексом 7. При обработке всех трех цифр
цикл прекращается. Цифры преобразуются начиная с младшего разряда.
300 void DecodSts(unsigned short
Uxxx)
{
1 for(i = 7;i > (5-1);i--)
1 {
2 str[i] = (0x30+(Uxxx &
0x000f));
305 2 Uxxx = Uxxx >> 4;
2 }
1 }
7. ПРОВЕРКА РАБОТОСПОСОБНОСТИ
Для проверки работоспособности написанной
программы используем ПК, на котором установлена программа ISIS программного
комплекса Proteus. На рисунке 4 изображена модель для тестирования программы.
Рис. 7.1 - Модель в среде Proteus
Моделирование произведено в режиме прямой
передачи.
Рис. 7.2 - Старт с питания 242 В, скачек питания
до 187 В, Uвых = 200 В
Рис. 7.3 - Старт с питания 187 В, скачек питания
до 242 В, Uвых = 200 В
Рис. 7.4 - Старт с питания 242 В, Uвых = 50 В,
изменение Uвых = 200 В
Рис. 7.5 - Старт с питания 187 В, Uвых = 200 В,
изменение Uвых = 50 В
8. ЛИСТИНГ
COMPILER V8.05a, COMPILATION OF
MODULE STABILIZATORMODULE PLACED IN stabilizator.OBJINVOKED BY:
C:\Keil\C51\BIN\C51.EXE stabilizator.c BROWSE DEBUG OBJECTEXTENDlevel source
#include <REG52.H>
#include <string.h>
#define DataInd P0
#define klav P2
#define Kp 0.2
#define Ki 0.015
#define Ktr 1
#define T ((60/12)*1000000/500)
#define Tic (0-T)
sbit RS = P3^7;
sbit RW = P3^6;
sbit E = P3^5;
sbit CS = P1^7;
sbit CLK = P1^6;
sbit DO = P1^5;
sbit K1 = P1^1;
sbit K3 = P1^2;
sbit K2 = P1^3;
sbit K4 = P1^4;
unsigned char data i=0;
unsigned char data nop;
unsigned short data DataKlav=0x220;
unsigned short data Uout=200;
unsigned char data buf;
unsigned short data buf2;
unsigned char code
str1[]="Uout= V";
unsigned char code
str2[]="Uizm= V";
unsigned char code strZero[]="
";
unsigned char data str[10];
unsigned short data rms;
unsigned short data rmsBCD;
unsigned short data Uin = 220;
float data gamma;
signed short data oh;
signed short data oh_do = 0;
signed short data S;
unsigned short data Ui =
(160*2.5);//
unsigned short data Tic2;
signed short data Upr;//
signed short data Uint;//
bit regim;
void WeitBW(void);
void PutCom(unsigned char data
OutByte);
void PutStrobe(void);
void PutData(unsigned char data
OutByte);
void PutString(unsigned char Str[]);
unsigned char ADC(void);
void DecodSts(unsigned short Uxxx);
void main(void)
{
1 //Инициализация
1 K1 = K2 = K3 = K4 = 0;
1 TMOD = 0x11;
1 TH0 = (Tic >> 8);
1 TL0 = Tic;
1 EA = 1;
1 ET0 = ET1 = 1;
1 EX0 = EX1 = 1;
1 gamma = (1-((float)Uout/Uin))*Ktr;
66 1 //Инициализация индикатора
1 PutCom(0x38);
1 PutCom(0x0c);
69 1 PutCom(0x06);
1 PutCom(0x01);
1
1 TR0 = 1;
73 1 while(1)
1 {
2 //Опрос клавиатуры
2 klav = 0x0f;
77 2 buf = klav;
2 klav = 0xf0;
2 buf = buf | klav;
2 if(buf != 0xff)
2 {
3 if(regim == 1||buf == 0xb7)
3 {
4 DataKlav = DataKlav << 4;
4 switch(buf)
4 {
5 case(0x7d): DataKlav += 0; break;
5 case(0xee): DataKlav += 1; break;
5 case(0xde): DataKlav += 2; break;
5 case(0xbe): DataKlav += 3; break;
5 case(0xed): DataKlav += 4; break;
5 case(0xdd): DataKlav += 5; break;
5 case(0xbd): DataKlav += 6; break;
5 case(0xeb): DataKlav += 7; break;
5 case(0xdb): DataKlav += 8; break;
5 case(0xbb): DataKlav += 9; break;
5 case(0xe7): DataKlav = 0; break;//Сброс
5 case(0xb7): //Режим
5 {
6 DataKlav = DataKlav >> 4;
6 if(regim == 1)
6 {
7 Uout = ((DataKlav & 0x0f00)
>> 8)*100 + ((DataKlav & 0x00f0) >>4)*10 + (DataKlav &
0x000f);
7 if (Uout < 50)
7 {
8 Uout = 50;
8 DataKlav = 0x50;
8 }
7 if (Uout > 200)
7 {
8 Uout = 200;
8 DataKlav = 0x200;
8 }
7 }
6 regim = !regim;
6 break;
6 }
5 }
4 }
3 while(klav!=0xf0);
3 klav = 0xff;
3 }
2 //Индикация
2 PutCom(0x80);
2 strcpy(str,str1);
2 DecodSts(DataKlav);
2 PutString(str);
2
2 PutCom(0xc0);
2 if(regim ==0)
2 {
3 strcpy(str,str2);
3 DecodSts(rmsBCD);
3 }
2 else strcpy(str,strZero);
2 PutString(str);
2 }//while
1 }//main
//Прерывания
Таймера
Т0
void Timer0(void) interrupt 1 using
0
{
1 TR0 = 0;
1 TH0 = (Tic >> 8);
1 TL0 = Tic;
146 1 TR0 = 1;
1 //Получаем данные с RMS-DC датчика
148 1 rms = ADC();
1 rms = rms * 2.5;
1 buf2 = (rms/100) << 8;
1 buf = rms%100;
1 rmsBCD = buf2 + ((buf/10) <<
4) + buf%10;
1 //ПИ-регулятор
1 oh = Uout - rms;
1 S = S + oh;
1 Upr = Kp*oh;
1 Uint = Ki*S;
1 Ui = rms + Upr + Uint;
1 Uin = rms / (1-(gamma/Ktr));
1 gamma = ((1-((float)Ui/Uin))*Ktr);
161 1 //Прямая передача
1 if (gamma == 0)
1 {
2 Tic2 = (0 - T/2);
165 2 TH1 = (Tic2 >> 8);
2 TL1 = Tic2;
2 K2 = K3 = 0;
2 K1 = K4 = 1;
2 }
1
1 //Отбавка
1 else if (gamma > 0)
1 {
2 Tic2 = (0 - gamma*T);
2 TH1 = (Tic2 >> 8);
2 TL1 = Tic2;
2 K2 = 1;
2 K4 = 0;
2 K3 = 1;
2 K1 = 0;
2 }
1 //Добавка
1 else
1 {
2 Tic2 = (0 + gamma*T);
2 TH1 = (Tic2 >> 8);
2 TL1 = Tic2;
2 K2 = 0;
2 K4 = 1;
2 K3 = 0;
2 K1 = 1;
2 }
1 }
//Прерывания
Таймера
Т1
void Timer1(void) interrupt 3 using
0
{
1 K3 = !K3;
1 K1 = !K1;
1 if (gamma == 0)
1 {
2 K2 = !K2;
2 K4 = !K4;
2 }
1 TR1 = 0;
1 }
//Прерывания
Int0
void Inn0(void) interrupt 0 using 0
{
1 K1 = K2 = K3 = K4 = 0;
1 }
//Прерывания
Int1
void Inn1(void) interrupt 2 using 0
215 {
1 K1 = K2 = K3 = K4 = 0;
1 }
//Функции работы с индикатором
219 void WeitBW(void)
{
1 DataInd = 0xff;
1 RS = 0;
1 RW = 1;
1 for(i=0;i<250;i++)
1 {
2 E = 0;
2 nop++;
2 E = 1;
2 nop++;
2 if((DataInd & 0x80) == 0)
break;
2 }
1 }
void PutStrobe(void)
{
1 E = 0;
1 nop++;
1 nop++;
1 nop++;
1 nop++;
1 E = 1;
1 }
void PutCom(unsigned char data
OutByte)
{
1 WeitBW();
1 RW = 0;
1 DataInd = OutByte;
1 nop++;
1 nop++;
1 PutStrobe();
1 }
void PutData(unsigned char data
OutByte)
{
1 WeitBW();
1 RS = 1;
1 RW = 0;
1 DataInd = OutByte;
1 nop++;
1 nop++;
1 PutStrobe();
1 }
void PutString(unsigned char Str[])
{
1 data char i;
1 data unsigned char C;
269 1 i = 0; // Счетчик символов
1 do
1 { // Цикл вывода строки
272 2 C = Str[i++];
2 PutData(C);
2 } while (Str[i]!= 0); // Признак
конца
- 0
1 }
unsigned char ADC(void)
{
1 unsigned char data byte;
1 unsigned char i;
1 CS = 1;
1 CLK = 1;
1 DO = 1;
1 byte = 0;
1 CS = 0;
1 while (~DO);
1 CLK = 1;
1 CLK = 0;
1 nop++;
1 for (i = 1; i < 9; i++)
1 {
2 CLK = 1;
2 CLK = 0;
2 nop++;
2 byte = byte << 1;
2 byte = byte | DO;
2 }
1 return byte;
1 }
void DecodSts(unsigned short Uxxx)
{
1 for(i = 7;i > (5-1);i--)
1 {
2 str[i] = (0x30+(Uxxx &
0x000f));
2 Uxxx = Uxxx >> 4;
2 }
1 }
INFORMATION: STATIC OVERLAYABLESIZE
= 1250 ----SIZE = 30 ----SIZE = ---- ----SIZE = ---- ----SIZE = 43 3SIZE = ----
----SIZE = 1 ----OF MODULE INFORMATION.COMPILATION COMPLETE. 0 WARNING(S), 0
ERROR(S)
ЛИТЕРАТУРА
программа листинг моделирование
индикатор
1. Магда
Ю. С. Микроконтроллеры серии 8051: практический подход. - М.: ДМК Пресс, 2008.
- 228 с.
. Керниган,
Брайан У., Ритчи, Деннис М. Язык программирования С, 2-е издание. : Пер. с
англ. - М. : Издательский дом "Вильяме", 2009. - 304 с.: ил.
. Стабилизаторы
переменного напряжения с высокочастотным широтно-импульсным регулированием/
А.В. Кобзев, Ю.М. Лебедев, Г.Я. Михальченко и др. - М.: Энегроатомиздат. 1986.
. Александров,
К.К. Электротехнические чертежи и схемы / К.К. Александров, Е.Г. Кузьмина. -
М.: Энергоатомиздат, 1990. - 288 с.
. www.gaw.ru
. www.alldatasheet.com