Мы обсудили условия применения CMOS, внешние и внутренние источники помех в схеме, методы снижения помех, методики испытаний на помехи и современные рекомендации по борьбе с помехами. Мы также обсуждали проблемы питания для встроенной системы, включая типы батареи, ее емкость, схемы управляющие питанием и меры энергосбережения. Хотя эти проблемы относятся к самым разным источникам, все они связаны общей нитью — их решение может превратить хороший проект на бумаге устройство, правильно работающее в «реальном мире».
6.8. Что еще прочитать?
1. Atmel, Inc. «EMC Design Considerations.» Application Note AVR040. 2004.
2. Atmel, Inc. «External Brown-out Protection.» Application Note AVR180. 2002.
3. Barrett, S. F. «Heart Arrhythmia Simulator.» Senior Design Project presented at the annual Nebraska Academy of Science, Lincoln, NE, 1979.
4. Campbell, D. «Designing for Electromagnetic Compatibility with Single-Chip Microcontrollers.» Application Note AN1263/D. Motorola, Inc., 1995.
5. Catherwood, M. «Designing for Electromagnetic Compatibility.» Application Note AN1050/D. Motorola, Inc., 2000.
6. Corp, M. Bruce. ZZAAP! Taming ESD, RFI, and EMI. Academic Press, 1990.
7. Federal Communication Commission. Rules and Regulations Part 15 Radio Frequency Devices, www.fcc.gov, 2004.
8. Glenewinkel, M. «System Design and Layout Techniques for Noise Reduction in MCU-Based Systems.» Application Note AN1259/D. Motorola, Inc., 1995.
9. Horowitz, Paul, and Winfleld Hill. Art of Electronics, 2nd ed. Cambridge, England: Cambridge University Press, 1989.
10. International Electro technical Commission. IEC 61000 Series Guidelines, www.iec.ch.
11. Johnson, Howard. High-Speed Digital Design: A Handbook of Black Magic. Upper Saddle River, NJ: Prentice Hall, 1993.
12. Kobeissi, I. «Noise Reduction Techniques for Microcontroller-Based Systems.» Application Note AN1705/D. Motorola, Inc., 1999.
13. Lun, Т. С. «Designing for Board Level Electromagnetic Compatibility.» Application Note AN2321/D. Motorola, Inc., 2002.
14. Maxim Integrated Products, «MAXIM Microprocessor Supervisory Circuits.» MAX 690-695. April 1995.
15. Motorola, Inc. «High-Speed CMOS Logic Data.» 1989.
16. Welch, Т. В. «Teaching Three Phase Power — A Low Voltage Approach.» Paper presented at the ASEE Annual Conference, Milwaukee, WI, June 1997. Welch, Т. В., and J. N. Berry. «Teaching Three-Phase Electrical Power Using a Low-Vollage Power Supply.» Paper presented at the ASEE Annual Conference, Seattle, WA, 1998.
6.9. Вопросы и задания
1. Опишите методы правильного обращения с устройствами CMOS.
2. Что может случиться, если обращаться с устройствами CMOS неправильно?
3. Что такое «дребезг» переключателя? Как исключить влияние «дребезга» переключателя?
4. Опишите методы снижения потребляемой мощности во встроенных микроконтроллерных системах.
5. Создайте карту выбора батареи из обычно доступных типов. Включить такие пункты, как тип батареи, конструктивные размеры, емкость и стоимостные показатели.
6. Что такое стабилизация напряжения? Почему важно использовать методы стабилизации напряжения во встроенных микроконтроллерных системах?
1. Опишите различие между ESD, RFI, ЭМП помехами, посадками, и импульсами напряжения. Приведите пример для каждого типа помех.
2. Почему таймеры для встроенных микроконтроллерных систем представляют собой традиционный источник помех? Какие методы могут использоваться, чтобы снизить помехи от таймеров?
3. Почему важно подсоединять свободные вводы портов во встроенных микроконтроллерных системах? Как эти вводы должны быть правильно подключены?
4. Почему важно подсоединять свободные входы аппаратного прерывания во встроенной системе контроллера? Как эти вводы должны быть правильно подключены?
5. Расскажите о методах программной защиты.
1. Разработайте систему источника питания с напряжением 5 В для 68HC12. Система должна иметь резервную литиевую батарею и содержать супервизор компании MAXIM. Разработайте блок-схему системы и детально опишите ее работу.
2. Опишите на двух страницах методы проектирования, позволяющие минимизировать чувствительность к помехам.
3. Изучите рекомендации от IEC 6100–4–2 до 6100–4–9. Кратко опишите каждое испытание.
Глава 7ПРИМЕРЫ ВСТРОЕННЫХ СИСТЕМ УПРАВЛЕНИЯ
ПОСЛЕ ИЗУЧЕНИЯ ГЛАВЫ ВЫ СМОЖЕТЕ:
• Применить структурный системный подход к проектированию встроенных микроконтроллерных систем;
• Создать детальное описание проекта;
• Выбрать модули в составе 68HC12, необходимые для конкретного применения;
• Описать структуру программного обеспечения встроенной микроконтроллерной системы, используя структуру программы и блок-схему алгоритма;
• Написать программу на языке Си для конкретного приложения.
Представим себе красивый, старинный дубовый сундучок для инструментов, подобный показанному на рис. 7.1. Каждая его секция разбита на отделения, для хранения ценных инструментов в каждом из лотков. На каждом из войлочных лотков аккуратно написано название инструмента. В том же лотке хранится также и инструкция по применению инструмента. В предыдущих главах мы описывали аппаратные средства, программное обеспечение, и средства разработки систем. Именно они и лежат в этом «сундучке» инструментов, позволяющих разрабатывать, производить и внедрять встроенные системы управления. В этой главе мы покажем на различных примерах, как разрабатываются встраиваемые микроконтроллерные системы. Мы тщательно выбрали проекты, чтобы показать, как используются подсистемы МК 68HC12 и HCS12 для выполнения разнообразных задач. Методы совместного использования этих периферийных модулей мы покажем на ряде примеров. Для каждого такого примера, мы приведем детальное описание проекта, список используемых в нем подсистем 68HC12, краткие основы теории, если это необходимо, детальную структуру программы, сопровождаемую блок-схемой алгоритма и хорошо документированным программным кодом. Будут рассмотрены следующие примеры применения:
• Система привода для робота, движущегося вдоль стенок лабиринта;
• Лазерный проектор;
• Цифровой вольтметр;
• Система стабилизации скорости вращения двигателя с оптическим тахометром;
• Парящий робот;
• Система защиты от несанкционированного внедрения на базе нечеткой логики;
• Электронная версия популярной игры в «15».
Рис. 7.1. Старинный сундук, с несколькими ящиками. В лотки ящиков мы уложили инструментальные средства, рассмотренные в предшествующих главах
В конце главы мы рассмотрим также процедуру программирования Flash-памяти с помощью отладочной платы «B32».
7.1. Система привода робота, движущегося вдоль стенок лабиринта
7.1.1. Описание проекта
В техническом задании на этот проект, предлагается разработать автономный робот, который мог бы проходить через неизвестный лабиринт. Робот должен двигаться через лабиринт, находя стенки лабиринта с помощью инфракрасных (ИК) локаторов (пар излучатель-приемник), и принимая решения, продвигаться вперед или назад, чтобы продолжить путь через лабиринт. При своем движении робот должен также избегать «мин» (магнитов), скрытых в полу лабиринта. Робот обнаруживает «мины» с помощью датчика Холла. Если робот обнаруживает «мину», то он останавливается, дает задний ход и объезжает ее.
Конструкция робота приведена на рис. 7.2. Корпус его состоит из двух легких связанных вместе алюминиевых платформ. На нижней платформе расположены два двигателя постоянного тока, приводящие в движение два больших колеса, установленных с обеих сторон корпуса. При использовании этой конструкции с двумя колесами, робот может управляться подобно танку. То есть, чтобы выполнить поворот по часовой или против стрелки на двигатели подаются сигналы. Два маленьких ролика с обеих сторон от робота используются, чтобы обеспечить его равновесие и устойчивость. Находясь в покое, робот опирается на три точки. На верхней платформе установлены пять ИК пар излучатель-приемник, которые позволяют роботу обнаружить стенки прямо перед собой и с любой стороны от корпуса. Верхняя платформа содержит также отладочную плату с микроконтроллером 68HC12, которая используется, чтобы принимать входные сигналы, вырабатывать решения, основанные на этих сигналах, и формировать сигналы управления двигателями для реализации этих решений. На нижней пластине робота установлен датчик Холла, позволяющий обнаруживать магнитные «мины».
Рис. 7.2. Робот, движущийся вдоль стенок лабиринта
Робот оборудован двумя основными колесами, с приводом от двигателей постоянного тока. Когда робот движется вперед, он постоянно следит за положением стенок, используя инфракрасные локаторы (пары излучатель-приемник), и за «минами», скрытыми в полу, с помощью датчика Холла.
Чтобы начать движение через неизвестный лабиринт, робот помещается вблизи от его входа. Предназначение робота состоит в том, чтобы проходить через лабиринты, избегая столкновения со стенками и контакта с «минами», скрытыми в полу. Робот едет вперед, когда на оба двигателя поступает одинаковое постоянное напряжение. Когда робот движется вперед с помощью двигателей постоянного тока, он непрерывно проверяет свое положение относительно стенок и магнитов с помощью пяти ИК локаторов и датчика Холла.
Стенки лабиринта окрашены белой краской с высоким коэффициентом отражения, чтобы ИК-сигналы, поступающие от источников, отражались от стенок обратно на приемники. Если робот приближается к стенке, то ее присутствие обнаруживается соответствующим ИК локатором. Например, если робот приближается к углу, расположенному с правой стороны (см. рис. 7.3), то передняя стенка обнаруживается передним локатором, а правая — правым локатором. Робот затем отвечает на принятые им входные сигналы, поворачивая влево, чтобы избежать столкновения со стенками.
Рис. 7.3. Робот, разработанный, чтобы обнаруживать близлежащие стенки
При использовании пяти инфракрасных датчиков, робот готовится сделать левый поворот, избегая стенок, расположенных спереди и справа
Естественная реакция разработчика, получившего задание на столь сложный проект — это паника. Однако если мы используем нисходящее проектирование, мы сможем разбить общее техническое задание на частные требования, выполняемые отдельными подсистемами. Начнем с создания списка функций, требуемых операционной системе робота для выполнения всех его задач. Эти задачи сводятся к следующим:
• Аналого-цифровое преобразование выходных сигналов ИК-датчиков;
• Создание алгоритма поворота робота, позволяющего определить, в каком направлении он должен повернуть в ответ на сигналы ИК-датчиков;
• Разработка функций управления приводом, осуществляющих движение робота вперед и назад и повороты влево или вправо;
• Создание механизма для обработки выходных сигналов датчика Холла;
• Обеспечение функции, позволяющей останавливаться, давать задний ход и обходить обнаруженную «мину»;
• Отображение выполняемых функций на символьном ЖК индикаторе.
7.1.2. Подсистемы 68HC12, используемые в проекте
По списку требуемых функций мы можем определить, какие периферийные модули МК 68HC12 необходимо использовать и какие другие внешние устройства будут необходимы для решения нашей задачи. К используемым устройствам и системам относятся:
• Датчики ИК-излучения и датчики Холла;
• Модуль аналого-цифрового преобразования ATD в составе МК 68HC12 для оцифровки сигналов инфракрасных датчиков и датчика Холла;
• Модуль ШИМ МК 68HC12 для модуляции ширины импульса;
• Интерфейс сопряжения МК с ЖК дисплеем;
• Интерфейс сопряжения МК с ИК-датчиками;
• Интерфейс сопряжения МК с датчиком Холла;
• Интерфейс драйвера двигателя;
• Аккумуляторные батареи, для питания двигателей, датчиков, и отладочной платы MC68HC912B32EVB.
7.1.3. Компоненты системы
Убедимся сначала, что на рынке имеются инструментальные средства, позволяющие выполнить весь список требуемых функций. В предыдущих главах (уложенных в наш сундучок) мы рассматривали следующие компоненты:
• Модуль АЦП в составе МК семейства 68HC12;
• Модуль ШИМ в составе МК семейства 68HC12;
• Интерфейс и программное обеспечение ЖК дисплея;
• Интерфейс драйвера двигателя;
• Батарею для питания системы.
Если вы еще не познакомились с этими устройствами и подсистемами МК, вернитесь к соответствующим главам. Мы же остановимся на двух темах, которые не рассматривали ранее: на паре излучатель-приемник, образующей ИК-локатор, и на датчике Холла.
Пара ИК излучатель-приемник. В паре ИК излучатель-приемник объединены источник и приемник инфракрасного (ИК) излучения. Источником является светоизлучающий диод с соответствующей схемой, а приемником — фототранзистор, чувствительный к ИК-диапазону излучения с собственной схемой, показанной на рис. 7.4. Для питания ИК диода используются электрические цепи, описанные ранее в разделе, посвященном светодиодам. Фототранзистор имеет светочувствительный переход база-база-эмиттер. Когда свет соответствующей длины волны падает на переход, в нем возникает базовый ток. В цепь эмиттера включен резистор нагрузки, сопротивление которого позволяет обеспечить необходимую величину выходного напряжения. Часто вместо резистора с фиксированным сопротивлением используется 10-оборотный измерительный потенциометр, позволяющий индивидуально подстраивать чувствительность каждого приемника. График зависимости выходного напряжения от расстояния до стенки лабиринта может быть получен экспериментально. Выходной сигнал каждого приемника подается на канал АЦП микроконтроллера 68HC12.
Рис. 7.4. Пара излучатель-приемник — ИК-локатор
Резистор (Re) ограничивает ток ИК излучателя на уровне номинального значения (Ie). Ток приемника формирует на резисторе Rd выходное напряжение приемника (Vout)
Датчики Холла, как и показывает их название, используют эффект Холла, чтобы генерировать напряжение, пропорциональное напряженности обнаруженного магнитного поля. На рынке имеются датчики Холла двух типов: (1) переключатели и (2) линейные датчики. Датчик переключающегося типа, обнаружив присутствие магнитного поля, фиксируется во включенном состоянии. Он остается в этом состоянии, даже если магнитное поле исчезает.
Линейный датчик формирует аналоговое выходное напряжение, пропорциональное измеряемому магнитному потоку. И именно такой прибор мы будем использовать для обнаружения «мин».
Рис. 7.5. Датчик Холла HAL114 компании Micronas
Датчики Холла поставляются несколькими изготовителями. Мы выбрали простой датчик с тремя выводами HAL114 фирмы Micronas, схема включения которого содержит два резистора R, RL и конденсатор C, как показано на рис. 7.5. Как и ранее, график зависимости выходного напряжения от расстояния до стенки лабиринта может быть получен экспериментально. Выходной сигнал с датчика подается на канал АЦП микроконтроллера 68HC12. Полная схема интерфейса связи МК 68HC12 с аппаратными средствами робота показана на рис. 7.6. Закончив на этом краткий обзор аппаратных средств, мы перейдем к обзору программного обеспечения робота.
Рис. 7.6. Интерфейс между аппаратными средствами робота и 68HC12
7.1.4. Структура программы и блок-схема алгоритма
Рабочая программа для этого проекта разработана Томом Шеи, бывшим студентом университета штата Вайоминг, с помощью компилятора ImageCraft ICC12. Прежде чем представить полный текст программы, рассмотрим структуру основной программы и блок-схему ее алгоритма, представленные на рис. 7.7. Мы просим читателя, самостоятельно разработать блок-схему алгоритма для каждой из функций в качестве домашней работы (см. задание 12).
а) Структура программы
б) Блок-схема алгоритма UML
Рис. 7.7. К программе управления роботом, движущимся вдоль стенок лабиринта
7.1.5. Программный код
/********************************************************************/
/*имя файла: robot.c */
/* Система управления роботом, движущимся в лабиринте: это система */
/* состоящих из излучателя и приемника, чтобы определять свое положение*/
/* относительно стенок лабиринта. */
/* опорного напряжения, то стенка находится в непосредственной близости*/
/* от робота.Основываясь на информации, получаемой от пяти датчиков,*/
/* робот может определять, какое направление дальнейшего движения */
/* избрать, чтобы избежать столкновения со стенками лабиринта. */
/* Датчик Холла позволяет роботу обнаружить магниты или "скрытые мины",*/
/* установленные под полом лабиринта. Робот имеет также ЖК дисплей */
/* для сообщения информации пользователю. Программа использует метод*/
/* полинга для считывания результатов АЦП.Сигнал модуля ШИМ */
/* управляет драйвером двигателей колес робота. */
/*Автор: Томас Шеи. Дата создания: 18 октября 2002 */
/*Последняя редакция: 4 декабря 2002 */
/********************************************************************/
/* Включенные файлы*/
#include <912b32.h>
#include
/*Пороги датчиков были определены экспериментально*/
#define opto_threshold 0x50 /* порог оптического датчика */
#define hes_threshold 0x80 /* порог датчика Холла */
#define forward 0
#define half_left 1
#define half_right 2
#define left_turn 3
#define right_turn 4
#define back_up 5
/*глобальные переменные*/
unsigned int i=0,j=0; /*переменные для программной задержки */
unsigned char sens[6]={0, 0, 0, 0, 0, 0};/*массив результатов АЦП */
/*прототипы функций*/
void init_adc(void); /*инициализация АЦП */
void read_adc(void); /*считывание значений АЦП */
void decision(void); /*передача решения о повороте, основанного на */
/*данных АЦП* /
void init_pwm(void); /*инициализация ШИМ */
void pwm_motors(const char a); */активация ШИМ для пересылки */
void lcd_init(void); /* инициализация дисплея */
int putchar(char c); /*вывод символа на дисплей */
int putcommand(char с); /*вывод команды на дисплей */
void delay_25(void); /*подпрограмма задержки на 2,5 с */
void lcd_print(char *string); /*вывод строки на ЖК дисплей */
void main() {
asm(".area vectors(abs)\n" /*инициализация вектора сброса МК */
" org 0xFFF8\n"
" .word 0x8000, 0x8000, 0x8000, 0x8000\n"
".text");
lcd_init(); /*инициализация ЖК дисплея */
lcd_print("LCD initialized");
void delay_25(void); /* задержки на 2,5 с */
init_adc(); /*инициализация АЦП */
lcd_print("ADC initialized");
void delay_25(void); /* задержки на 2,5 с */
init_pwm(); /*инициализация ШИМ */
lcd_print("PWM initialized");
void delay_25(void); /* задержки на 2,5 с */
while(1) / *непрерывный цикл */
{
read_adc(); /* считать текущее значение из АЦП */
decision(); /* принять решение о направлении движения */
}
} /*конец программы main*/
********************************************************************/
/*initialize_adc: инициализация АЦП контроллера 68HC12 */
/*******************************************************************/
void init_adc() {
ATDCTL2 = 0x80; /*Установить бит ADPU для подачи питания на АЦП */
ATDCTL3 = 0x00;
ATDCTL4 = 0x7F; /* частоту P_CLK установить на 125 кГц */
/* время преобразования: 32 ATD CLK, */
/*1 считывание каждые 256 мкс /*
for(i=0; i<67; i++) /*задержка 100 мкс при 8 МГц E_CLK */
{
;
}
}
/********************************************************************/
/********************************************************************/
/*read_adc: считывание результатов из АЦП */
/********************************************************************/
void read_adc() {
ATDCTL5 = 0x50; /*Установить АЦП на режим многоканального,*/
/* преобразования 8 каналов */
while((ATDSTAT & 0x8000) == 0)/* проверка бита SCF для окончания */
/*преобразования */
{
;
}
/* сохранения результата в глобальном массиве */
sens[0] = ADR7H; /*дальний левый датчик */
sens[l] = ADR6H; /*средний правый датчик */
sens[2] = ADR5H; /*центральный датчик */
sens[3] = ADR4H; /* средний правый датчик */
sens[4] = ADR3H; /* дальний правый датчик */
sens[5] = ADR2H; /*датчик Холла*/
}
/********************************************************************/
/*decision(): решение о повороте основано на информации, полученной от*/
/* пяти датчиков. Порог датчика Холла (hes_threshold) и порог */
/* оптического датчика (opto_threshold) определяются экспериментально.*/
/********************************************************************/
void decision() {
if (sens[5] < hes_threshold) { /* датчик Холла нашел "мину", */
pwm_motors(back_up); /* робот движется назад и определяются */
/* дальнейшие действия/*
if (sens[0] > opto_threshold) pwm_motors(right_turn);
else pwm_motors(left_turn);
for(i=0; i<0xFFFF; i++){ /*задержка вращения двигателя */
for(j=0; j<15; j++) {
;
}
}
}
/*если обнаруживает три стенки (тупик), то движется назад */
else if((sens[2]>opto_threshold) && (sens[0]>opto_threshold)
&& (sens[4]>opto_threshold)) {
pwm_motors(back_up);
}
/*если стенки спереди и слева, поворачивает направо */
else if((sens[0]>opto_threshold)&&(sens[2]>opto_threshold)) {
pwm_motors(right_turn);
}
/*если стенки спереди и справа, поворачивает налево */
else if((sens[2]>opto_threshold)&&(sens[4]>opto_threshold)) {
pwm_motors(left_turn);
}
/*если стенка спереди справа, делает полуповорот направо*/
else if(sens[1]>opto_threshold) {
pwm_motors(half_right);
}
/*если стенка спереди слева, делает полуповорот налево */
else if(sens[3] > opto_threshold) {
pwm_motors (half_left) ;
}
/*если стенки вблизи нет, продолжает движение вперед */
else {
pwm_motors(forward);
}
}
/********************************************************************/
/*init_pwm(): инициализация ШИМ контроллера 68HС12 */
/********************************************************************/
void init_pwm() {
PWTST= 0x00;
PWCTL= 0x00; /*Режим фронтовой ШИМ */
WCLK= 0x3F; /*Каналы без каскадного соединения, E_CLK/128 */
PWPOL= 0x0F; /*set pins high then low transition */
DDRP = 0xFF; /*Порт PORT T на вывод */
PWEN = 0x0F; /*Активизировать выход ШИМ */
PWPER0 = 250; /*Установить частоту ШИМ 250 Гц */
PWPER1 = 250;
PWPER2 = 250;
PWPER3 = 250;
PWDTY0 = 0; /*начальная установка ШИМ на отсутствие движения*/
PWDTY1 = 0;
PWDTY2 = 0;
PWDTY3 = 0;
}
/********************************************************************/
/*pwm_motors: /*выполнение определенного поворота */
/********************************************************************/
void pwm_motors(const char a) {
for (i = 0;i<2000;i++) /*задержка на 3 мс чтобы позволить двигателю*/
{ /* отреагировать*/
}
switch(a) { /*определение вида поворота */
case 0: /* движение вперед */
PWDTY0 = 200; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 250;
PWDTY2 = 250;
PWDTY3 = 200;
lcd_print("Forward\n");
break;
case 1: /*полуповорот налево */
PWDTY0 = 0; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 250;
PWDTY2 = 250;
PWDTY3 = 125;
lcd_print("Half Left\n");
break;
case 2: /*полуповорот направо*/
PWDTY0 = 125; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 250;
PWDTY2 = 250;
PWDTY3 = 0;
lcd_print("Half Right\n");
break;
case 3: /*поворот налево*/
PWDTY0 = 125; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 250;
PWDTY2 = 0;
PWDTY3 = 125;
lcd_print("Left Turn\n");
break;
case 4: /*поворот направо*/
PWDTY0 = 125; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 0;
PWDTY2 = 250;
PWDTY3 = 125;
lcd_print("Right Turn\n");
break;
case 5: /*задний ход*/
PWDTY0 = 125; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 0;
PWDTY2 = 0;
PWDTY3 = 125;
for(i=0; i<0xFFFF; i++) { /* Задержка в 1,25 с перед движением назад*/
for(j=0; j<15; j++) {
;
}
}
lcd_print("Back Up\n");
break;
default: /*по умолчанию движение вперед, малая скорость */
PWDTY0 = 63; /*регистры коэффициента заполнения ШИМ */
PWDTY1 = 250;
PWDTY2 = 250;
PWDTY3 = 63;
lcd_print("Error\n");
break;
}
}
/********************************************************************/
/*lcd_init(): инициализация режима работы ЖК дисплея */
/*Последовательность команд инициализации определяется изготовителем*/
/*PORTA: магистраль данных, PORTB[2:1]: линия R/S, линия разрешения E*/
/********************************************************************/
void lcd_init() {
DDRA=0xff; /*порт PORTA на вывод */
DDRB=0x06; /* порт PORTB [2:1] на вывод */
/*последовательности команд для инициализации ЖК дисплея */
putcommand(0x38);
putcommand(0x38);
putcommand(0x38);
putcommand(0x38);
putcommand(0x0f);
putcommand(0x01);
putcommand(0x06);
putcommand(0x00);
/*очистка дисплея, возврат курсора */
putcommand(0x00);
}
/********************************************************************/
/*putchar(char c): вывод символа на дисплей */
/********************************************************************/
int putchar(char c) {
PORTA=C;
PORTB= PORTB |0x04;
PORTB= PORTB |0x02;
PORTB= PORTB&0xfd;
for (i=0; i<100; i++); /*задержка на *150 мкс до того, как ЖКД */
/* сможет принять информацию */
return с;
}
/********************************************************************/
/********************************************************************/
/*putcommand(char c): выдача команды управления для ЖК дисплея */
/********************************************************************/
int putcommand(char с) {
PORTA= с;
PORTB= PORTB&0xfb;
PORTB= PORTB|0x02;
PORTB= PORTB&0xfd;
for (i=0; i<100; i++) /* задержка на *150 мкс до того, как ЖКД сможет*/
/*принять информацию */
{
;
}
return c;
}
/********************************************************************/
/*delay_25(): задержка на 2.5 с */
/********************************************************************/
void delay_25() {
for (i=0; i<0xFFFF; i++) {
for (j=0; j<30; j++) {
;
}
}
}
/********************************************************************/
/*lcd_print(): вывод строки символов на дисплей. */
/********************************************************************/
void lcd_print(char *string) {
putcommand(0x02); /*возврат курсора ЖКД */
while (*(string) != '\0') {
putchar(*string);
string++;
}
}
/********************************************************************/
7.2. Лазерный проектор