Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Пример3. Вывод цифр от 0 до 99. Смена разрядов выполняется в прерывании таймера






Пример 1. Вывод цифр от 0 до 9

#define F_CPU 1000000UL

#include < avr/io.h>

#include < avr/iom16.h>

#include < util/delay.h>

 

unsigned char number[] =

{

0x3f, //0

0x06, //1

0x5b, //2

0x4f, //3

0x66, //4

0x6d, //5

0x7d, //6

0x07, //7

0x7f, //8

0x6f //9

};

 

unsigned char count = 0;

int main(void)

{

//порт, к которому подключены Сегменты

PORTA = 0xff;

DDRA = 0xff;

//вывод, к которому подключен Катод

PORTB |= (1< < 0);

PORTB |= (1< < 1);

//DDRB |= (1< < 0);

//DDRB |= (1< < 1);

DDRB = 0xff;

while(1)

{

PORTA = number[count];

count++;

if (count == 10) count = 0;

_delay_ms(1000);

}

return 0;

}

Эта программа каждую секунду выводит значение переменной count на семи сегментный индикатор. Индикация в данном случае - статическая.

Идем дальше – вывод двух цифр. Настройка портов и коды цифр остаются без изменений, но теперь нам нужно добавить кусок кода, который будет зажигать разряды индикатора по очереди. Частота смены разрядов должна быть достаточно высокой, чтобы свечение индикатора воспринималось без мерцания.

Пример 2. Вывод цифр от 0 до 99

#define F_CPU 1000000UL

#include < avr/io.h>

#include < avr/iom16.h>

#include < util/delay.h>

 

unsigned char number[] =

{

0x3f, //0

0x06, //1

0x5b, //2

0x4f, //3

0x66, //4

0x6d, //5

0x7d, //6

0x07, //7

0x7f, //8

0x6f //9

};

 

unsigned char count = 0;

//числа для вывода на индикатор

unsigned char data1 = 2;

unsigned char data2 = 5;

 

int main(void)

{

//порт, к которому подкл. Сегменты

PORTA = 0xff;

DDRA = 0xff;

 

//порт, к которому подкл. Катод

PORTB = 0;

DDRB = (0< < 1)|(0< < 0);

 

while(1)

{

//гасим оба разряда

PORTB & = ~((1< < 1)| (1< < 0));

//выводим в порт код цифры

//и зажигаем следующий разряд

if (count == 0)

{

//PORTA = 0X00;

PORTA = number[data2];

PORTB |= (1< < 0);

}

if (count == 1)

{

//PORTA = 0X00;

PORTA = number[data1];

PORTB |= (1< < 1);

}

count++;

if (count == 2) count = 0;

//частота смены разрядов будет 100 Гц при кварце 8МГц

_delay_ms(500);

}

return 0;

}

 

Эта программа просто выводит любое поразрядно заданное число от 0 до 99.

Частота смены разрядов семисегментного индикатора задается с помощью программной задержки _delay_ms(). Это не самое удачное решение, потому что добавление каких-нибудь других задач в цикл while будет мешать выводу на индикатор. Давайте организуем смену разрядов индикатора с помощью аппаратного таймера/счетчика Т0

 

Пример3. Вывод цифр от 0 до 99. Смена разрядов выполняется в прерывании таймера

#define F_CPU 1000000UL

#include < avr/io.h>

#include < avr/iom16.h>

#include < util/delay.h>

#include < avr/interrupt.h>

 

unsigned char number[] =

{

0x3f, //0

0x06, //1

0x5b, //2

0x4f, //3

0x66, //4

0x6d, //5

0x7d, //6

0x07, //7

0x7f, //8

0x6f //9

};

 

//числа для вывода на индикатор

volatile unsigned char data1 = 0;

volatile unsigned char data2 = 0;

 

int main(void)

{

//порт, к которому подкл. Сегменты

PORTA = 0xff;

DDRA = 0xff;

 

//порт, к которому подкл. Катод

PORTB = 0;

DDRB = (0< < 1)|(0< < 0);

 

//инициализация таймера Т0 частота прерываний 100Гц при кварце 8МГц

TIMSK = (1< < TOIE0);

TCCR0 = (1< < CS02)|(0< < CS01)|(1< < CS00);

TCNT0 = 0xb2;

sei();

 

 

while(1)

{

//программный счетчик секунд

data1++;

if (data1 == 10)

{

data1 = 0;

data2++;

if (data2 == 10) data2 = 0;

}

_delay_ms(500);

}

return 0;

}

 

//прерывания таймера Т0 - вывод на индикатор

ISR(TIMER0_OVF_vect)

{

static unsigned char count = 0;

TCNT0 = 0xb2;

//гасим оба разряда

PORTB & = ~((1< < 1)|(1< < 0));

//выводим в порт код цифры и зажигаем следующий разряд

if (count == 0)

{

PORTA = number[data2];

PORTB |= (1< < 1);

}

if (count == 1)

{

PORTA = number[data1];

PORTB |= (1< < 0);

}

count++;

if (count == 2) count = 0;

}

 

Переменные data1, data2 объявлены с ключевым словом volatile, потому что они используются и в основном коде и в прерывании. В проекте под GCC я забыл поставить его поставить, и компилятор выкинул обе переменные, посчитав их ненужными!

Прерывания таймера происходят параллельно выполнению цикла while. Это позволяет выполнять в цикле какую-нибудь полезную задачу. В данном примере с помощью двух переменных в цикле организован программный счетчик от 0 до 99.

Использовать две восьмиразрядные переменные для организации счетчика от 0 до 99 неудобно и расточительно, ведь такой счетчик можно сделать и на одной переменной типа unsigned char. Хорошо, счетчик мы сделаем, а как вывести его значение на семисегментный индикатор? Нужен код “разбивающий” десятичное число на отдельные разряды и вот как он выглядит:

 

 

//программный счетчик

unsigned char counterProg = 35;

//”разбиваем” значение счетчика на отдельные разряды

data1 = counterProg % 10;

data2 = counterProg/10;

 

data1 = counterProg % 10 – это операция деления по модулю 10 (деление с остатком). Результатом этого выражения будет остаток от деления переменной counterProg на 10, то есть для нашего случая 5.

counterProg/10 – это целочисленное деление на 10. Результатом этого выражения будет число 3.

Таким образом, в переменные data2, data1 будут записаны числа 3 и 5 соответственно, значение счетчика counterProg при этом не изменится.

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.