Программное управление технологическим оборудованием
.pdf
|
SEG_A + SEG_B + |
#define N7 |
SEG_C |
|
SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + |
#define N8 |
SEG_F + SEG_G |
|
SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + |
#define N9 |
SEG_G |
#define DIP |
SEG_DP |
#define |
|
MINUS |
SEG_G |
|
0x0 |
#define OFF |
0 |
// массив кодов цифр
char DIGITS[] = {N0, N1, N2, N3, N4, N5, N6, N7, N8, N9};
_FOSCSEL(FNOSC_FRC) // настройка работы микроконтроллера
|
|
// от внутреннего тактового генератора |
// Инициализация таймера |
|
|
T1 |
|
|
void Init_Timer1() |
|
|
{ |
|
|
T1CON = 0; |
// сброс таймера |
|
IFS0bits.T1IF = 0; |
// сброс флага прерывания таймера |
|
|
|
// разрешение прерывания от |
IEC0bits.T1IE = 1; |
таймера |
|
TMR1 |
|
// обнуление текущего значения |
= |
0x0000; |
таймера |
PR1 = 0x0E65; |
// задание периода таймера |
|
|
|
// разрешение работы таймера и его |
T1CONbits.TON = 1; |
запуск |
|
} |
|
|
char _ind = 0; // номер активного индикатора
char _data[8]; // буфер индикации - массив кодов символов
// Отправление данных в регистр
MBI5168 void Ind_Send(char digit)
{
char c;
501
for (c = 0; c < 8; c++)
{
//установка требуемого логического уровня
//на последовательном входе SDI драйвера
MBI5168 if ((digit & (1 << c)) != 0)
{
LATCbits.LATC3 = 1;
}
else
{
LATCbits.LATC3 = 0;
}
//формирование синхроимпульса на входе SCK
LATCbits.LATC 4 = 1; LATCbits.LATC 4 = 0;
}
// формирование синхроимпульса на входе LE
LATBbits.LATB5 = 1; LATBbits.LATB5 = 0;
}
// Инициализация линий портов |
|
|
|
void Ind_Init() |
|
|
|
{ |
|
|
|
|
|
|
(RB |
TRISBbits.TRISB6 = 0; |
// Выход |
A |
6) |
|
|
|
(RB |
TRISBbits.TRISB7 = 0; |
// Выход |
B |
7) |
|
|
|
(RB |
TRISBbits.TRISB8 = 0; |
// Выход |
C |
8) |
|
|
|
(RB |
TRISBbits.TRISB9 = 0; |
// Выход |
D |
9) |
|
|
|
(RC |
TRISCbits.TRISC3 = 0; |
// Выход |
SDI |
3) |
|
|
SC |
(RC |
TRISCbits.TRISC4 = 0; |
// Выход |
K |
4) |
|
|
|
(RB |
TRISBbits.TRISB5 = 0; |
// Выход |
LE |
5) |
} |
|
|
|
// Разбитие числа на цифры |
|
|
|
void Ind_Show(unsigned int a, unsigned |
|
|
|
502
int b)
{
_data[3] = DIGITS[a % 10]; a /= 10;
_data[2] = DIGITS[a % 10]; a /= 10;
_data[1] = DIGITS[a % 10]; a /= 10;
_data[0] = DIGITS[a % 10];
_data[7] = DIGITS[b % 10]; b /= 10; _data[6] = DIGITS[b % 10]; b /= 10; _data[5] = DIGITS[b % 10]; b /= 10; _data[4] = DIGITS[b % 10];
}
// Прерывание таймера T1 по совпадению
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt()
{
Ind_Send(OFF); // Отключение индикатора LATB &= ~(0x07 << 6);// Переключение на следующий
LATB |= (_ind << 6); |
// индикатор |
Ind_Send(_data[_ind]); |
// Отправка кода цифры |
_ind++; |
// переход к след. индикатору |
if (_ind == 8) |
|
{ |
|
_ind = 0; |
|
} |
|
IFS0bits.T1IF = 0; // Сброс флага прерывания таймера
TMR1 |
= 0; |
// Перезапуск таймера |
} |
|
|
void main() |
|
|
{ |
|
|
Init_Timer1(); |
// Инициализация таймера |
|
Ind_Init(); |
|
// Инициализация индикации |
Ind_Show(0, 0); |
// Обнуление индикации |
|
unsigned int seconds = 0; while (1)
{
Ind_Show(0, seconds); __delay32(FCY); // пауза 1 сек seconds++;
}
}
503
4 Варианты индивидуальных заданий к лабораторной работе
Разработать программу для учебного стенда, позволяющую выполнить следующие действия:
1.Отобразить на LED количество включённых тумблеров SA1..SA10 в десятичной форме.
2.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти их сумму и результат вывести на LED в десятичной форме.
3.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти их разность и результат вывести на LED в десятичной форме.
4.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти их произведение и результат вывести на LED в десятичной форме.
5.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти результат поразрядного логического ИЛИ и результат вывести на LED в двоичной форме.
6.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти результат поразрядного логического И и результат вывести на LED в двоичной форме.
7.Рассматривая состояние дискретных датчиков SA3..SA10 как два четырёхразрядных двоичных числа, найти результат поразрядного логического ИСКЛЮЧАЮЩЕГО ИЛИ и результат вывести на LED в двоичной форме.
8.Отобразить на LED поразрядно состояние тумблеров SA3..SA10, отображая включённый SA единицей, а отключённый SA отключённым символом.
5 Контрольные вопросы
1.Как организуется вывод информации в микроконтроллерных системах?
2.Как устроен светодиодный семисегментный индикатор.
3.Расскажите принцип построения и алгоритм работы статической индикации.
4.Расскажите принцип построения и алгоритм работы динамической индикации.
504
Лабораторная работа 10
Исследование ввода информации при помощи клавиатуры
Цель работы:
Изучить алгоритм, принцип работы и схему электрическую принципиальную матричной клавиатуры. Разработать и отладить программу ввода информации в микроконтроллер с помощью клавиатуры.
Порядок выполнения работы:
1.Изучить теоретические вопросы, связанные с вводом информации с помощью клавиатуры.
2.Изучить принципиальную электрическую схему к лабораторной работе.
3.Разработать программу в соответствии с индивидуальным заданием.
4.Отладить программу в среде MPLAB IDE.
5.Загрузить программу в учебный стенд.
6.Исследовать работу устройства динамической индикации.
7.Оформить отчёт по лабораторной работе.
8.Ответить на контрольные вопросы.
1 Краткие теоретические сведения
1.1 Устройство матричной клавиатуры
Клавиатура предназначена для ввода информации в микроконтроллерное устройство. Фактически, клавиатура представляет собой набор дискретных переключателей. В случае большого количества таких переключателей требуется использовать большое количество линий ввода.
Одним из наиболее распространённых способов уменьшения требуемых линий для подключения клавиатуры является организация клавиатуры по принципу матричного шифратора, в узлах которого расположены переключатели (рис. 1.1).
505
Рис. 1.1. Матричная организация клавиатуры
Кнопки включены таким образом, что при нажатии кнопка замыкает строку на столбец. Часть линий матрицы используется в качестве сканирующих (строки), а часть в качестве считывающих (столбцы). Количество кнопок, подключенных таким образом, определяется как количество сканирующих линий, умноженное на количество считывающих. Отсюда следует, что использование матричной клавиатуры для случая, когда кнопок меньше или равно четырем, не имеет смысла, так как понадобятся те же четыре линии, а схема и алгоритм опроса клавиш усложняются.
1.2 Алгоритм работы матричной клавиатуры
Работает матричная клавиатура следующим образом. На одну их линий R1..R4 подаётся сигнал, т.е. происходит сканирование одного из рядов клавиатуры. Если ни одна из клавиш не нажата, то сигнал на линиях C1..C4 отсутствует. Если клавиша на сканирующем ряду нажата, то на соответствующей линии C1..C4 появляется сигнал. Таким образом, зная какой ряд в данный момент сканируется и на какой из линий C1..C4 появился сигнал, можно определить, какая клавиша зажата в данный момент.
2 Электрическая принципиальная схема к лабораторной работе
На рис.2.1 приведена электрическая принципиальная схема к лабораторной работе.
506
Рис. 2.1. Электрическая принципиальная схема к лабораторной работе
Для выбора строки матричной клавиатуры используются выводы D8..D11 дешифратора DD150 HC154. На вход дешифратора подаются сигналы
A, B, C, D с линий портов RB6, RB7, RB8, RB9.
Для сканирования столбцов используется восьмиканальный мультиплексор DD140 HCF4051B. Выбор активного входа мультиплексора происходит сигналами A, B, C с линий RС6, RС7, RС8 микроконтроллера. Выход мультиплексора подаётся на вход RC9 микроконтроллера.
507
3 Пример выполнения работы
Задача: Разработать программу для учебного стенда, отображающую на LED строку и столбец нажатой клавиши матричной клавиатуры.
Анализ задачи: Для хранения символов индикации используется массив _ind[8], каждый элемент которого представляет собой код символа, отображаемого на соответствующей позиции индикатора LED. Для хранения активного в данный момент вывода дешифратора используется переменная _i. Переключение активного вывода дешифратора происходит по прерыванию таймера T1, настроенного таким образом, что прерывания генерируются с частотой 1 кГц. В случаях, когда активный вывод дешифратора соединён со строкой матричной клавиатуры, запускается процедура опроса состояний столбцов. Состояние клавиш сохраняется в двумерном массиве _keys[4][3], первый индекс которого является номером строки, второй – номером столбца.
Листинг программы: |
|
|
|
|
#include <P33FJ32MC204.h> |
|
|
|
|
#define FOSC |
|
|
|
|
7370000 #define |
|
|
|
|
FCY (FOSC / 2) |
|
|
|
|
// объявление кодов сегментов |
|
|
|
|
#define SEG_A |
0x08 |
// |
--- SEG_A --- |
|
#define SEG_B |
0x01 |
// |
| |
| |
#define SEG_C |
0x20 |
// |
SEG_F SEG_B |
|
#define SEG_D |
0x04 |
// |
| |
| |
#define SEG_E |
0x80 |
// |
--- SEG_G --- |
|
#define SEG_F |
0x10 |
// |
| |
| |
#define SEG_G |
0x40 |
// |
SEG_E SEG_C |
|
#define SEG_DP |
0x02 |
// |
| |
| |
|
|
// |
--- SEG_D --- SEG_DP |
|
// объявление кодов цифр |
|
|
|
|
|
SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + |
|||
#define N0 |
SEG_F |
|
|
|
#define N1 |
SEG_B + SEG_C |
|
|
|
#define N2 |
SEG_A + SEG_B + SEG_G + SEG_E + SEG_D |
|||
#define N3 |
SEG_A + SEG_B + SEG_G + SEG_C + SEG_D |
|||
#define N4 |
SEG_F + SEG_G + SEG_B + SEG_C |
|||
#define N5 |
SEG_A + SEG_F + SEG_G + SEG_C + SEG_D |
|||
|
SEG_A + SEG_F + SEG_G + SEG_C + SEG_D + |
|||
#define N6 |
SEG_E |
|
|
|
|
SEG_A + SEG_B + |
|
|
|
#define N7 |
SEG_C |
|
|
|
508
|
SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + |
#define N8 |
SEG_F + SEG_G |
|
SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + |
#define N9 |
SEG_G |
#define DIP |
SEG_DP |
#define MINUS |
SEG_G |
#define OFF |
0x00 |
// массив кодов цифр
char DIGITS[] = {N0, N1, N2, N3, N4, N5, N6, N7, N8, N9};
// настройка работы
_FOSCSEL(FNOSC_FRC) микроконтроллера
//от внутреннего тактового генератора
//номер активного вывода
char _i = 0; |
|
дешифратора |
|
|
|
|
// буфер индикации - массив кодов |
||
char _ind[8]; |
|
символов |
|
|
char _keys[4][3]; |
|
// буфер клавиатуры |
|
|
// Инициализация таймера |
|
|
|
|
T1 |
|
|
|
|
void |
|
|
|
|
Init_Timer1() |
|
|
|
|
{ |
|
|
|
|
|
|
// сброс |
|
|
T1CON |
= 0; |
таймера |
|
|
IFS0bits.T1 |
|
|
|
|
IF |
= 0; |
// сброс флага прерывания таймера |
||
IEC0bits.T1IE = 1; |
// разрешение прерывания от таймера |
|||
|
|
// обнуление текущего значения |
||
TMR1 |
= 0x0000; |
таймера |
|
|
PR1 |
= 0x0E65; |
// задание периода таймера |
||
|
|
// разрешение работы таймера и его |
||
T1CONbits.TON = 1; |
запуск |
|
|
|
} |
|
|
|
|
// Инициализация линий |
|
|
|
|
портов |
|
|
|
|
void Ind_Init() |
|
|
|
|
{ |
|
|
|
|
TRISBbits.TRISB6 = |
|
|
|
|
0; |
|
// Выход |
A |
(RB6) |
TRISBbits.TRISB7 = |
// Выход |
B |
(RB7) |
|
509
0; |
|
|
|
TRISBbits.TRISB8 = |
|
|
|
0; |
// Выход |
C |
(RB8) |
TRISBbits.TRISB9 = |
|
|
|
0; |
// Выход |
D |
(RB9) |
TRISCbits.TRISC3 = |
|
|
|
0; |
// Выход |
SDI |
(RC3) |
TRISCbits.TRISC4 = |
|
SC |
|
0; |
// Выход |
K |
(RC4) |
TRISBbits.TRISB5 = |
|
|
|
0; |
// Выход |
LE |
(RB5) |
} |
|
|
|
// Отправление данных в регистр |
|
|
|
MBI5168 void Ind_Send(char digit) |
|
|
|
{ |
|
|
|
char c; |
|
|
|
for (c = 0; c < 8; c++) |
|
|
|
{ |
|
|
|
1.установка требуемого логического уровня
2.на последовательном входе SDI драйвера MBI5168 if ((digit & (1 << c)) != 0)
{
LATCbits.LATC3 = 1;
}
else
{
LATCbits.LATC3 = 0;
}
// формирование синхроимпульса на входе SCK
LATCbits.LATC4 = 1; LATCbits.LATC4 = 0;
}
// формирование синхроимпульса на входе LE
LATBbits.LATB5 = 1;
LATBbits.LATB5 = 0;
}
void Ind_Show(char a, char b)
{
_ind[3] = DIGITS[a];
_ind[7] = DIGITS[b];
}
// Инициализация линий портов
void Kbd_Init()
{
510
