Доброго времени суток, уважаемые читатели. Зарегистрировался на хабре я давно, но никак не решался оформить свой первый пост.
Хотелось написать что-то, что действительно может показаться интересным. Время шло, а идеи все никак не приходили.
И вот, буквально на днях, я закончил работу над одним из своих первых проектов, после чего, мне в голову пришла мысль сделать некий видео обзор и написать небольшую статью о приборе, над которым я работал достаточно продолжительный период времени. Работал не один, но речь пойдет о части, которая «висела» целиком и полностью на мне.

Во-первых, необходимо было разработать программу, управляющую зарядным устройством. Состоит оно по большому счету из микроконтроллера ADUC814 со встроенным аналого-цифровым преобразователем, пяти светодиодов, отвечающих за уровень заряда аккумулятора и кнопки включения заряда. Все достаточно просто, детально описывать смысла не вижу. По прерыванию АЦП получаем данные, которые потом переводятся в вольты, далее оперируя этим значением программа принимает те или иные решения, например какие диоды зажечь, что делать при критических уровнях заряда и т.п., а так же следит за кнопкой включения заряда.
Во-вторых, и это собственно самая сложная часть для меня, необходимо было разработать программу, управляющую блоком обработки информации и индикации. В БОИ входят такие узлы, как дисплей, клавиатура, пара вспомогательных светодиодов и управляющий всем этим микроконтроллер AT89C51RC2 (МК_БОИ). Обзор всех основных функций ваттметра представлен на видео.
К ваттметру подключается один из четырех преобразователей, в зависимости от измеряемой мощности. Данные с преобразователя поступают на аналого-цифровой преобразователь фирмы Analog Devices и далее с помощью RS232 передаются на еще одни ADUC814 (МК_АЦП), в котором проходят предварительную обработку. Программа пред. обработки и связи непосредственно с АЦП разрабатывалась не мной.
МК_АЦП по RS232 получает от МК_БОИ одну из нескольких команд, каждая из которых состоит из трех байт, далее он анализирует команду и в зависимости от нее, посылает обратно три байта номера команды и запрашиваемый результат. Это может быть номер преобразователя или, например, результаты измерений, которые подвергаются дальнейшей математической обработке. Некоторые команды отвечают за коррекцию нуля или калибровку АЦП. Всего около 8-9 команд, подробно останавливаться на них я также не вижу смысла.
В конце хотелось бы немного написать о функционале, подробней с которым можно ознакомиться на видео.
Основная часть кнопок клавиатуры выполняет двойную функцию, вспомогательные светодиоды позволяют легче сориентироваться в режимах работы, которых всего два, это режим меню, горит верхний диод и режим работы, горит нижний диод.
Вся необходимая информация выводится на дисплее. Значение измеряемой величины, которое так же переводится в dBm и dB, во время дрейфа нуля попадаются и отрицательные значения, в этих случаях на экран выводится сообщение Err. Результат сравнения мощности с величиной Рс. Номер подключенного преобразователя. Информация о том, что нажата кнопка СТОП, а так же при выходе из возможного диапазона измерений конкретного преобразователя также выводится соответствующее сообщение.
Еще хотелось бы добавить, что помимо частотных поправочных коэффициентов так же имеется и динамический поправочный коэффициент, рассчитывается индивидуально для каждого конкретного измерения.
На этом все, надеюсь, что найдутся люди, которым данный пост понравится, а так же хотелось бы увидеть комментарии, критического характера, возможно у кого-то будут интересные идеи, которые я смогу реализовать в дальнейшем в рамках этого проекта, учитывая, что намечается замена МК_БОИ на аналогичный, с большим объемом памяти, так как эти 32 кБ забиты под завязку.
Спасибо за внимание.
Прошу прощения за долгий перерыв. В комментариях были вопросы касательно процесса самого программирования, в связи с этим хочу обновить данную статью и добавить сюда код.
Вывод информации на дисплей был организован следующим образом. Был составлен список повторяющихся фраз и написана под них библиотека «alphabetLCD.h»:
Так как иногда приходилось выводить на дисплей результаты вычислений, реализованных в «main.c», я использовал ключевое слово
Ниже описаны все основные функции «main.h»:
Для удобства программирования дисплея, вызова его команд, перемещения курсора по строкам и т.п. активно использовались макросы:
ПРОДОЛЖЕНИЕ СЛЕДУЕТ...
Хотелось написать что-то, что действительно может показаться интересным. Время шло, а идеи все никак не приходили.
И вот, буквально на днях, я закончил работу над одним из своих первых проектов, после чего, мне в голову пришла мысль сделать некий видео обзор и написать небольшую статью о приборе, над которым я работал достаточно продолжительный период времени. Работал не один, но речь пойдет о части, которая «висела» целиком и полностью на мне.
Для начала приведу немного сухой технической информации

Ваттметр поглощаемой СВЧ мощности М3-114 предназначен для измерения в коаксиальном тракте среднего значения мощности непрерывных и импульсно- модулированных СВЧ сигналов при электропитании от промышленной электросети 220 В, 50 Гц, так и в автономном режиме, от внутренней или внешней аккумуляторной батареи 12 В. В приборе применён четырёх строчный текстовый вакуумно-люминесцентного дисплей высокой яркости. Подготовка прибора к работе осуществляется в диалоговом режиме, что упрощает эксплуатацию. Прибор оснащён портом RS-232, что позволяет выводить данные на ЭВМ.
Диапазон рабочих частот от 0,00 до 17,85 ГГц.
Диапазон измерения средних значений мощности от 1,0 мкВт до 100 Вт.
В диапазоне измеряемой мощности более 10 мВт на частотах от 0 до 12,05 ГГц предел основной погрешности ваттметра не превышает ±4 %, а в диапазоне частот свыше 12,05 ГГц до 17,85 ГГц — ±6 %.
КСВН ваттметра не более:
1,3 в диапазоне частот от 0,02 до 12,05 ГГц;
1,4 в диапазоне частот свыше 12,05 до 17,85 ГГц.
Нестабильность показаний ваттметра с учетом дрейфа “электрического нуля” не более 40 мкВт/мин.
Мощность, потребляемая ваттметром от сети напряжением 220 ±22 В, частотой 50±0,5 Гц при работе с ППК1 – ППК3, не более 12 ВА, при работе с ППК 4 — не более 15 ВА, при работе от автономного источника питания 6,5 ВА
Теперь перейдем непосредственно к тем задачам, которые были поставлены передо мной
Во-первых, необходимо было разработать программу, управляющую зарядным устройством. Состоит оно по большому счету из микроконтроллера ADUC814 со встроенным аналого-цифровым преобразователем, пяти светодиодов, отвечающих за уровень заряда аккумулятора и кнопки включения заряда. Все достаточно просто, детально описывать смысла не вижу. По прерыванию АЦП получаем данные, которые потом переводятся в вольты, далее оперируя этим значением программа принимает те или иные решения, например какие диоды зажечь, что делать при критических уровнях заряда и т.п., а так же следит за кнопкой включения заряда.
Во-вторых, и это собственно самая сложная часть для меня, необходимо было разработать программу, управляющую блоком обработки информации и индикации. В БОИ входят такие узлы, как дисплей, клавиатура, пара вспомогательных светодиодов и управляющий всем этим микроконтроллер AT89C51RC2 (МК_БОИ). Обзор всех основных функций ваттметра представлен на видео.
К ваттметру подключается один из четырех преобразователей, в зависимости от измеряемой мощности. Данные с преобразователя поступают на аналого-цифровой преобразователь фирмы Analog Devices и далее с помощью RS232 передаются на еще одни ADUC814 (МК_АЦП), в котором проходят предварительную обработку. Программа пред. обработки и связи непосредственно с АЦП разрабатывалась не мной.
МК_АЦП по RS232 получает от МК_БОИ одну из нескольких команд, каждая из которых состоит из трех байт, далее он анализирует команду и в зависимости от нее, посылает обратно три байта номера команды и запрашиваемый результат. Это может быть номер преобразователя или, например, результаты измерений, которые подвергаются дальнейшей математической обработке. Некоторые команды отвечают за коррекцию нуля или калибровку АЦП. Всего около 8-9 команд, подробно останавливаться на них я также не вижу смысла.
В конце хотелось бы немного написать о функционале, подробней с которым можно ознакомиться на видео.
Основная часть кнопок клавиатуры выполняет двойную функцию, вспомогательные светодиоды позволяют легче сориентироваться в режимах работы, которых всего два, это режим меню, горит верхний диод и режим работы, горит нижний диод.
С помощью меню можно выполнять ряд функций
- Управлять яркостью дисплея
- Выбирать частотный диапазон, на котором проводятся измерения. В зависимости от выбранного диапазона применяются те или иные поправочные коэффициенты, влияющие на конечный результат. Коэффициенты рассчитаны путем сравнения с эталонным прибором.
- Устанавливать некую величину P, с которой сравнивается измеряемая величина. Результат выводится на дисплей в процентах
- Устанавливать диапазон измеряемой величины, при выходе из которого, на дисплей выводиться соответствующая надпись < Pmin, > Pmax
В режиме работы пользователь может:
- Проводить коррекцию нуля и калибровку АЦП.
- Включить усреднение измеряемой величины или выключить его.
- «Заморозить» дисплей, путем нажатия кнопки СТОП
Вся необходимая информация выводится на дисплее. Значение измеряемой величины, которое так же переводится в dBm и dB, во время дрейфа нуля попадаются и отрицательные значения, в этих случаях на экран выводится сообщение Err. Результат сравнения мощности с величиной Рс. Номер подключенного преобразователя. Информация о том, что нажата кнопка СТОП, а так же при выходе из возможного диапазона измерений конкретного преобразователя также выводится соответствующее сообщение.
Еще хотелось бы добавить, что помимо частотных поправочных коэффициентов так же имеется и динамический поправочный коэффициент, рассчитывается индивидуально для каждого конкретного измерения.
На этом все, надеюсь, что найдутся люди, которым данный пост понравится, а так же хотелось бы увидеть комментарии, критического характера, возможно у кого-то будут интересные идеи, которые я смогу реализовать в дальнейшем в рамках этого проекта, учитывая, что намечается замена МК_БОИ на аналогичный, с большим объемом памяти, так как эти 32 кБ забиты под завязку.
Спасибо за внимание.
КОДИНГ
Прошу прощения за долгий перерыв. В комментариях были вопросы касательно процесса самого программирования, в связи с этим хочу обновить данную статью и добавить сюда код.
Алфавит дисплея
Вывод информации на дисплей был организован следующим образом. Был составлен список повторяющихся фраз и написана под них библиотека «alphabetLCD.h»:
void m3114(); // "МЕТЕОР МЗ-114"
void noSignalADC(); // "НЕТ СВЯЗИ С АЦП"
void wait(); // "ОЖИДАНИЕ"
void norma(); // норма
void PPK1();
void PPK2();
void PPK3();
void PPK4();
void prepareToWorkOnPPKEnter(); // подготовка к работе подключите ппк к источнику сигнала и нажмите "ввод"
void heating(); // прогерв 6с прервать? 34
void ifTNorm(); // ЕСЛИ Т=15-25 НАЖМИТЕ "ВВОД" ЕСЛИ НЕТ НАЖМИТЕ "ОТМЕНА"
void Kcoeff(); // К преобразования 1,000
void preparationOfMeasurement(); // ПОДГОТОВКА ИЗМЕРЕНИЙ САМОКАЛИБРОВКА 12с
void resetMenuParams(); // переустновка параметров в меню
void readyToMeasurement(); // ваттметр готов к измерениям
void menuSet1(); // установка К частот *** установка частоты *** установка Р сравнения *** допусковый контроль
void switchOffSVCHAndPressEnter(); // "ВЫКЛЮЧИТЕ свч сигнал и нажмите ввод
void preparationOfMeasurementCorrection0(); // подготовка измерений коррекция "0" норма
void preparationOfMeasurementCooling(); // подготовка измерений остывание 30 с
void preparationOfMeasurementStop32(); // подготовка измерений 32с прервать? 24
void preparationToWork(); // подготовка к работе выключите свч сигнал и нажмите ввод
void hertzType0(); // 0-1 1-4 4-8 8-12
void hertzType1(); // 12-15 15-17.85
void setPCompare(); //установка Р сравн. сохранить значение? 1,000 mW
void setPCompareChange(); //установка Р сравн. зпт - кнопкой зпт измените цифру: х,ххх
void allowenceControlMin(); // допусковый контроль Рmin: сохранить значение? Х,ХХХ W
void allowenceControlMax(); // допусковый контроль Рmax: сохранить значение? Х,ХХХ W
void setAllowenceControlMin(); //установка Р min зпт - кнопкой зпт измените цифру: х,ххх
void setAllowenceControlMax(); //установка Р max зпт - кнопкой зпт измените цифру: х,ххх
void menuSet2(); // без усреднения усреднение по 4м 8ми 16ти
void brightnessSet(); // 25% 50% 75% 100%
void fault(); // НЕИСПРАВНОСТЬ!!!
void incorrectValue(); // ОШИБКА ВВОДА! ОВТОРИТЕ ПОПЫТКУ
void overload(); // ПЕРЕГРУЗКА!!! при Р > крайнего значения диаппазона
Приведу пример реализации одной из функций из «alphabetLCD.с»:
void noSignalADC() // "НЕТ СВЯЗИ С АЦП"
{
writeData('H');
writeData('E');
writeData('T');
writeData(' ');
writeData('C');
writeData('B');
writeData(0x99);
writeData(0x8D);
writeData(0x8E);
writeData(' ');
writeData('C');
writeData(' ');
writeData('A');
writeData(0x90);
writeData(0x85);
}
Так как иногда приходилось выводить на дисплей результаты вычислений, реализованных в «main.c», я использовал ключевое слово
extern
:extern bit hertzType;
extern float xdata calibrFl;
extern unsigned char xdata ppkNumberCh; // номер ППК char
extern float xdata pCompareFl;
extern float xdata pMinFl; // записывает массив в float
extern float xdata pMaxFl; // записывает массив в float
Плавно перейдем к основной программе
Ниже описаны все основные функции «main.h»:
void initialization();
void delay(unsigned int);
void delay2s();
void zeroCorrection();
void calibration();
void measurement();
//****UART****
void sendData (unsigned char); // send to UART
//unsigned char recvData(); // recive from UART
void iToA (int , char * );
void getPPKnumber();
//****Keyboard****
void keyboardInit();
void keyboardPolling();
void downZero();
void upCalibr();
void lessAveraging();
void morePC();
void commaStop();
void cancel();
void enter();
void menu();
//****Display****
void dispInit();
void writeCmd(int);
void writeData(char);
void readBF();
void returnHome();
void clearDisp();
void reloadDisp();
void moreLessCheck();
Макросы
Для удобства программирования дисплея, вызова его команд, перемещения курсора по строкам и т.п. активно использовались макросы:
/* __________MAKROS BLOCK__________ */
#define FIRST_LINE 0x80
#define SECOND_LINE 0xC0
#define THIRD_LINE 0x94
#define FOURTH_LINE 0xD4
#define CURSOR_HOME 0x02
#define CLEAR_DISP 0x01
#define DISP_OFF 0x08
#define DISP_ON_CB_OFF 0x0C // Disp ON cursore & blink OFF
#define DISP_ON_CB_ON 0x0F
#define FIRST_SIMBOL 0xD4
#define SECOND_SIMBOL 0xD5
#define THIRD_SIMBOL 0xD6
#define FOURTH_SIMBOL 0xD7
#define FIFTH_SIMBOL 0xD8
#define SIXTH_SIMBOL 0xD9
/* __________MAKROS BLOCK END__________ */
Конфигурирование ножек процессора
* __________PINS BLOCK__________ */
sbit E = P3^4;
sbit RS = P3^6;
sbit RW = P3^5;
sbit workLed = P3^2;
sbit menuLed = P3^3;
sbit enterBut = P1^6;
sbit cancelBut = P1^5;
sbit uartPC = P3^7;
/* __________PINS BLOCK END__________ */
Описание переменных
/* __________VARIABLES BLOCK__________ */
unsigned char keyPressed = 0; // key pressed value
bit keyFlag = 0; // software flag
unsigned char xdata uartDataRecv = 0; // запоминает данные с уарт
unsigned char xdata uartDataSend = 0; // отправляет данные с уарт
char xdata uartRecvCount = 0; // счетчик принятых данных с уарт
bit menuFlag = 0; // контролирует зажигание диодов клавиатуры, если 1 - горит верхний, если 0 - нижний
char xdata move = 1; // перемещение по пунктам меню
bit signalFlag = 0; // если флаг установлен значит есть инфа о номере ППК
char xdata enterFlag = 0; // инкрементируется при нажатии ввод
char xdata cancelFlag = 0; // инкрементируется при нажатии отмена
bit modeFlag = 0; // игнорирует нажатие кнопок вне бесконечного цикла
bit brightnessFlag = 0; // устанавливается, если мы внутри меню яркости дисплея
char xdata brightnessMove = 1; // флаг для перемещения по меню яркости
char xdata brightnessSetFlag = 0; // установка яркости дисплея, контролирует нажатие ввод
bit hertzFlag = 0; // устанавливается, если мы внутри меню установки частоты
char xdata hertzSetFlag = 0;
char xdata menuStep = 0; // глубина меню
char xdata hertzMove = 1; // флаг для перемещения по меню частоты
bit hertzType; // флаг типа меню частоты
bit compareFlag; // флаг меню Р сравнения
char xdata compareFlagEnter = 0; // нажат ВВОД для Р сравнения
char xdata compareFlagCancel = 0; // нажата ОТМЕНА для Р сравнения
char xdata moreLess = 0x30; // значение Р сравнения и допускового контроля
char xdata moreLessFlag = 0; // флаг для подсчета количества введенных знаков
bit moreFlag = 0; // если 1 то при вычитании moreLess -= 2
bit lessFlag = 0; // если 1 то при прибавлении moreLess +=2
char xdata wattFlag = 0; // флаг переключения размерности Р сравн
bit commaFlag = 0; // проверка нажатия кнопки ЗПТ для ввода Р сравн и допускового контроля
unsigned char xdata pCompare[10] = 0; // запоминает Р сравн
float xdata pCompareFl = 1.0;
//float xdata pCompareFlTemp = 1.0; // для сохранения предыдущего состояния переменной в случае отмены.
// ДОРАБОТАТЬ, ЗНАЧЕНИЕ НЕ СОХРАНЯЕТСЯ!!!
bit controlFlag = 0; // флаг меню допускового контроля
char xdata controlFlagEnter = 0; // нажат ВВОД для допускового контроля
char xdata controlFlagCancel = 0; // нажата ОТМЕНА для допускового контроля
unsigned char xdata pMin[10]; // запоминает Р min
unsigned char xdata pMax[10]; // запоминает Р max
float xdata pMinFl = 0; // записывает массив в float
float xdata pMaxFl = 0; // записывает массив в float
bit pMinFlag = 0; // устанавливаем флаг когда изменяем Р min
bit pMaxFlag = 0; // устанавливаем флаг когда изменяем Р max
unsigned char xdata zeroCoef1 = 50; // коэффициент коррекции нуля 50 - 200
unsigned char xdata zeroCoef2 = 30; // коэффициент коррекции нуля 50 - 200
unsigned char xdata zeroCoef3 = 30; // коэффициент коррекции нуля 50 - 200
unsigned char xdata zeroCoef4 = 100; // коэффициент коррекции нуля 50 - 200
unsigned long xdata zero; // значение после коррекции нуля
unsigned char xdata calibrCoef1 = 50; // коэффициент калибровки 50 - 200
unsigned char xdata calibrCoef2 = 30; // коэффициент калибровки 50 - 200
unsigned char xdata calibrCoef3 = 30; // коэффициент калибровки 50 - 200
unsigned char xdata calibrCoef4 = 100; // коэффициент калибровки 50 - 200
unsigned long xdata calibr; // значение после калибровки К преобразования
float xdata calibrFl; // значение после калибровки К преобразования
unsigned int xdata PPK1CalibrPower; // эталон калибровочного коэффициента для ППК1 мощьность Р
unsigned long xdata PPK23CalibrPower; // эталон калибровочного коэффициента для ППК1 - 2 мощьность Р
unsigned long xdata PPK4CalibrPower; // эталон калибровочного коэффициента для ППК4 мощьность Р
float xdata PPK1CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5)
float xdata PPK2CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5)
float xdata PPK3CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5)
float xdata PPK4CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5)
unsigned char xdata uartData[10]; // данные о номере ППК приходящие на УАРТ по запросу
unsigned char xdata ppkNumberCh; // номер ППК char
float xdata measurementResult = 0; // результат основных измерений
bit averagingFlag = 0; // флаг устреднения
bit averaging4 = 0; // усреднение по 4-ем
bit averaging8 = 0; // усреднение по 8-ми
char xdata averagingMove = 1; // для перемещения по меню усреднения
float idata hertzRate = 1; // поправочный коэффициент для коррекции принимает 6(диаппазонов) * 4(ППК) = 24 значения
float idata dynamicRate = 1; // динамический поправочный коэффициент
//для коррекции принимает 4(диаппазонов) * 4(ППК) = 16 значения
char idata stop = 0; // устанавливается в 1 и экран замирает при нажатии кнопки СТОП, в 0 при повторном нажатии
char idata pc = 0; // бит для вывода данных на ПК
//bit key = 0;
xdata union
{
unsigned long bytes;
unsigned char byteArr[4];
} byteUnion;
/* __________VARIABLES BLOCK END__________ */
Прерывания
/* __________INTERUPTS BLOCK__________ */
void keyboard_interrupt() interrupt 7 using 1
{
IEN1 &= ~(1<<0); //запрещаем прерывания клавиатуры
keyFlag = 0;
keyPressed = KBF; /* save pressed key */
keyFlag = 1; /* set the software flag */
KBF = 0x00; /* clear keyboard flags */
delay(50000); // 50 mc
IEN1 |= 0x01; //разрешаем прерывания клавиатуры
}
void serial_IT(void) interrupt 4
{
if (RI == 1)
{
uartDataRecv = SBUF;
uartData[uartRecvCount] = uartDataRecv;
++uartRecvCount;
}
RI = 0;
}
/* __________INTERUPTS BLOCK END__________ */
ПРОДОЛЖЕНИЕ СЛЕДУЕТ...