7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | - | - | - | - | CS02 | CS01 | CS00 |
R | R | R | R | R | R/W | R/W | R/W |
Рис. 3.3 – Регистр управления таймером/счетчиком0 TCCR0
Биты 7…3 зарезервированы и всегда читаются как 0.
Биты 2, 1, 0 – выбор коэффициента деления предварительного делителя.
CS02 | CS01 | CS00 | Значение |
0 | 0 | 0 | Стоп |
0 | 0 | 1 | СК |
0 | 1 | 0 | СК/8 |
0 | 1 | 1 | СК/64 |
1 | 0 | 0 | СК/256 |
1 | 0 | 1 | СК/1024 |
1 | 1 | 0 | Вн. Сигнал Т0, нар. фронт |
1 | 1 | 1 | Вн. Сигнал Т0, спад. фронт |
Рис. 3.4–Выбор коэффициента деления предварительного делителя.
TCNT0 – данный регистр служит для загрузки и считывания показаний счетчика/таймера0.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
MSB | LSB | ||||||
R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
Рис. 3.5 – регистр текущего значения счетчика TCNT0
TIMSK – данный регистр служит для установки и сброса флагов разрешения работы прерываний таймеров.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
OCIE2 | TOIE2 | TICIE1 | OCIE1A | OCIE1B | TOIE1 | OCIE0 | TOIE0 |
R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
Рис. 3.6 – регистр масок прерываний таймеров
TOIE1 – разрешение прерывания по переполнению таймера/счетчика 0
OCIE1A - разрешение прерывания по совпадению таймера/счетчика 1
TIFR - данный регистр содержит флаги прерываний таймеров
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
OCF2 | TOV2 | ICF1 | OCF1A | OCF1B | TOV1 | OCF0 | TOV0 |
R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
Рис. 3.7 – регистр флагов прерываний таймеров.
TOV1 – флаг переполнения таймера/счетчика 0. 1 – произошло переполнение
OCF1A – флаг выхода совпадения 1А. 1 – произошло совпадение значения таймера/счетчика 1 и данных в регистре OCR1A.
3.2.2 Инициализациятаймера/счетчика1
16-разрядный таймер/счетчик может получать импульсы тактовой частоты – СК с предварительного делителя (СК/8, СК/64, СК/8256, СК/1024), импульсы с внешнего вывода или быть остановлен соответствующими установками регистра TCCR1B. Флаги состояния таймера (переполнения, совпадения и захвата) и управляющие сигналы находятся в регистре TIFR. Разрешение и запрещение прерываний от таймера управляется регистром TIMSK.
Таймер/счетчик1 поддерживает функцию совпадения, используя регистр совпадения OCR1A в качестве источника для сравнения с содержимым счетчика. Функция совпадения поддерживает очистку счетчика по совпадению.
TCNT1 - данный регистр служит для загрузки и считывания показаний счетчика/таймера.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
MSB | |||||||
LSB | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Рис. 3.8 – регистр текущего значения счетчика TCNT1
TCCR1B – регистр управления таймером/счетчиком1
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ICNC1 | ICES1 | - | WGM13 | WGM2 | CS12 | CS11 | CS10 |
R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
Рис. 3.9 – Регистр управления таймером/счетчиком1 TCCR1B
Биты 2, 1, 0 – выбор коэффициента деления предварительного делителя.
CS02 | CS01 | CS00 | Значение |
0 | 0 | 0 | Стоп |
0 | 0 | 1 | СК |
0 | 1 | 0 | СК/8 |
0 | 1 | 1 | СК/64 |
1 | 0 | 0 | СК/256 |
1 | 0 | 1 | СК/1024 |
1 | 1 | 0 | Вн. Сигнал Т1, нар. фронт |
1 | 1 | 1 | Вн. Сигнал Т1, спад. фронт |
Рис. 3.10–Выбор коэффициента деления предварительного делителя.
Инициализация таймера/счетчика1 происходит только при вызове функции Time wate (), которая устанавливается делитель частоты на 1024, путем записи значения PrescalerTmr1= 5 в регистр TCCR1B.
OCR1A – регистр совпадения А таймера/счетчика1. В этом регистре хранятся данные, которые непрерывно сравниваются с текущим значением таймера/счетчика1. Действие по совпадению задается регистрами управления таймером/счетчиком1 и регистром состояния.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
MSB | |||||||
LSB | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Рис. 3.11 - регистр совпадения А таймера/счетчика1 OCR1A
Рассчитаем значение, которое необходимо занести в OCR1A для сравнения с содержимым таймера/счетчика1.
Количество тактовых импульсов, которые приходят на таймер/счетчик1 за 1 секунду, рассчитывается по формуле:
, гдеК – значение делителя частоты
f – значение частоты генератора
Выбираем значение делителя частоты 1024, т.к. это максимально возможный коэффициент деления/задержки. Частота генератора задается путем подключения кварцевого резонатора к соответствующим выводам контроллера. В данном случае был выбран кварц на 7, 3728*106 Гц.
Т.к. необходима выдержка в 5 секунд то:
7200*5=36000
Т.к. прерывание по совпадению таймера/счетчика1 происходит только на следующий такт после совпадения, необходимо от значения 36000 вычесть 1. Это значение присваивается переменной comp_t1=35999, которая заносится в OCR1A.
voidTime_wate(void)
{#asm("cli")
TCCR1B = PrescalerTmr1;
OCR1A = comp_t1;
#asm("sei")
while (Tmr1Flag == 0)
}
3.3 Процедура обработки нажатия кнопки Пуск
Процедура обработки нажатия кнопки Пуск, вызывается при переполнении таймера/счетчика0. Использование таймера для проверки состояния порта через заданные интервалы времени является некоторой защитой от импульсных помех. Еще более повысить устойчивость приема сигнала от датчика импульсов в условиях помех можно за счет использования мажоритарного элемента. Если известно текущее состояние входного сигнала и два его предшествующих состояния, то значение сигнала определяется по следующему принципу:
OldOldPortSignal | OldPortSignal | NewPortSignal | RealSignal | Comment |
0 | 0 | 0 | 0 | НОЛЬ! |
0 | 0 | 1 | 0 | Кажется, ноль |
0 | 1 | 0 | 0 | Кажется, ноль |
0 | 1 | 1 | 1 | Кажется, единица |
1 | 0 | 0 | 0 | Кажется, ноль |
1 | 0 | 1 | 1 | Кажется, единица |
1 | 1 | 0 | 1 | Кажется, единица |
1 | 1 | 1 | 1 | ЕДИНИЦА! |
void CheckButton (void)
{
unsigned char b;
static char OldPortSignal;
static char OldOldPortSignal;
NewPortSignal = PINC&1; //select PC0 - START_button
b = PINC&7; //select PC1,PC2 - bunker sensors
if((NewPortSignal != OldPortSignal) & (NewPortSignal != 0)) // Positive front found
{ RealSignal = (NewPortSignal ^ OldPortSignal) ^ OldOldPortSignal;
OldOldPortSignal = OldPortSignal;
OldPortSignal = RealSignal;
if(b) //bunker CLOSED!
{
PORTA=0x01; //PA0 - transporter ON!
Time_wate(); //wate 5 sec!
Tmr1Flag = 0;
PORTA=0x03; //PA0&PA1 - bunker OPEN!
}
}
}
3.4 Процедураиндикации
Выводит на на 4х разрядный 7-ми сегментный индикатор количество совершенных отгрузок. Индикатор подключен к порту В микроконтроллера. Управление разрядами индикатора осуществляется через порт D.
В процедуре используются 3 функции.
Первая Bin2BCD_4Digit выполняет преобразование числа отгрузок, представленных в двоичном виде, в BCD число и поразрядно заносит его в массив BufBCD:
void Bin2BCD_4Digit (unsigned int data)
{
unsigned char i;
for(i=0;i<4;i++)
{
BufBCD[i] = data % 10;
data /= 10;
}
Вторая функция Bin2Seg_4Digit преобразовывает полученное BCD число в семисегментный эквивалент (путем вызова функции Bin2Seg) и заносит результаты в массив BufSeg. Семисегментные эквиваленты представлены в виде заранее определенных значений
#define Dig0 SegA + SegB + SegC + SegD + SegE + SegF + 0
#define Dig1 0 + SegB + SegC + 0 + 0 + 0 + 0
#define Dig2 SegA + SegB + 0 + SegD + SegE + 0 + SegG
#define Dig3 SegA + SegB + SegC + SegD + 0 + 0 + SegG
#define Dig4 0 + SegB + SegC + 0 + 0 + SegF + SegG
#define Dig5 SegA + 0 + SegC + SegD + 0 + SegF + SegG
#define Dig6 SegA + 0 + SegC + SegD + SegE + SegF + SegG
#define Dig7 SegA + SegB + SegC + 0 + 0 + 0 + 0
#define Dig8 SegA + SegB + SegC + SegD + SegE + SegF + SegG
#define Dig9 SegA + SegB + SegC + SegD + 0 + SegF + SegG
#define DigMinus 0 + 0 + 0+ 0 + SegЕ +0 + 0
unsigned char Bin2Seg (unsigned char data)
{
switch(data)
{
case 0: return Dig0;
case 1: return Dig1;
case 2: return Dig2;
case 3: return Dig3;
case 4: return Dig4;
case 5: return Dig5;
case 6: return Dig6;
case 7: return Dig7;
case 8: return Dig8;
default: return Dig9;
}
}
//== Convert 4 digits from BinBuf[] into SegBuf[] ==========
void Bin2Seg_4Digit (void)
{
unsigned char i;
for(i=0;i<4;i++)
{
BufSeg[3-i] = Bin2Seg(BufBCD[i]);
}
Третья функция выполняет собственно индикацию, выводя через порт В полученный семисегментный эквивалент числа отгрузок.
void Ind (void)
{
unsigned char i;
for(i=0;i<4;i++)
{
PositionPort = AllDigitsOFF;
SymbolPort = BufSeg(i);
PositionPort = DigitNmb(i)
}
4.Листингпрограммы
Файл ind.h
//== Include files =================================
#include <mega16.h>
#define PortBMask 0xFF
//== Common declarations ============================
#define SymbolPort PORTB
#define SegA 1 // aa
#define SegB 2 // f b
#define SegC 4 // f b
#define SegD 8 // gg
#define SegE 16 // e c
#define SegF 32 // e c
#define SegG 64 // dd
#define Dig0 SegA + SegB + SegC + SegD + SegE + SegF + 0
#define Dig1 0 + SegB + SegC + 0 + 0 + 0 + 0
#define Dig2 SegA + SegB + 0 + SegD + SegE + 0 + SegG
#define Dig3 SegA + SegB + SegC + SegD + 0 + 0 + SegG
#define Dig4 0 + SegB + SegC + 0 + 0 + SegF + SegG
#define Dig5 SegA + 0 + SegC + SegD + 0 + SegF + SegG
#define Dig6 SegA + 0 + SegC + SegD + SegE + SegF + SegG
#define Dig7 SegA + SegB + SegC + 0 + 0 + 0 + 0
#define Dig8 SegA + SegB + SegC + SegD + SegE + SegF + SegG
#define Dig9 SegA + SegB + SegC + SegD + 0 + SegF + SegG
#define DigMinus SegA + SegB + SegC + SegD + 0 + SegF + SegG
#define PositionPort PORTD
#define Position0 0
#define Position1 1
#define Position2 2
#define Position3 3
#define AllDigitsOFF 4
#define DigitNmb = [254, 253, 251, 247]
//== Global Variables =========================
unsigned char BufSeg[4];
unsigned char BufBCD[4];
void Bin2BCD_4Digit (unsigned int data);
//== Convert binary char into 7 Segment Code =============
unsigned char Bin2Seg (unsigned char data)