При подключении к микроконтроллеру светодиодных семисегментных индикаторов малой мощности использовать управляющие транзисторы нет необходимости, т.к. при использовании динамической индикации ток потребления сегмента уменьшается. Можно обойтись лишь использованием токоограничительных резисторов, а общие аноды/катоды подключать напрямую к контроллеру. Другое дело если используются индикаторы с большим током потребления, например с высотой цифр более 30 мм. Ток потребления таких индикаторов более 30мА, а макс. ток для ножки контроллера 20мА, поэтому такие индикаторы подключают через управляющие транзисторы(ключи). В основном используются биполярные транзисторы для общего анода pnp-структура, для общего катода npn - структура, также можно использовать полевые транзисторы или транзисторные сборки типа ULN2003 и т.п.

Подключение индикаторов с общим катодом

Схема подключения стандартная, все номиналы резисторов подобраны по средним значениям. При проверке в Протеусе и в железе внутренний генератор Atmega8 использовал на 1МГц.

Подключение индикаторов с общим катодом

NPN транзисторы открываются при подаче на базу положительного напряжения, т.е. если подаем на базу лог. единицу транзистор откроется, если лог. ноль транзистор закроется. В программе это действие выполняет такой код:

PORTB = (1 << segcounter); // Подаем лог. 1

Ниже представлен код программы, при включении контроллера на индикаторе высвечивается надпись "Test", далее по разрядам бегут цифры 1-2-3-4.

// Подключение семисегментных индикаторов(ОК) к AVR через транзисторные ключи
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Массив комбинаций сегментов
unsigned char SEGMENTE[] = 
{
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
0x78, // t
0x79, // E
0x6D, // S
0x00  // blank
};
volatile unsigned char segcounter = 0;
volatile unsigned char display_1, display_2, display_3, display_4;
// Прерывание по переполнению T2, динамическая индикация
ISR (TIMER2_OVF_vect)
{	
PORTD = 0x00; // Гасим все сегменты
PORTB = (1 << segcounter); // Засвечиваем общий катод, подаем лог. 1
	
switch (segcounter)
{	
case 0:
PORTD = SEGMENTE[display_1];
break; 
case 1:
PORTD = SEGMENTE[display_2];
break; 
case 2:
PORTD = SEGMENTE[display_3];
break;	
case 3:
PORTD = SEGMENTE[display_4];
break;		
}
if(segcounter++> 2) segcounter = 0;	
}
// Главная функция
int main (void) 
{ 
DDRB = 0xFF; // Порт B выход
PORTB = 0x00; // Лог. нули чтобы индикатор не засвечивался при первом включении 
DDRD = 0xFF; // Порт D выход
PORTD = 0x00;
TCCR2 |= (1 << CS21);  // Предделитель на 8 
TIMSK |= (1 << TOIE2); // Разрешение прерывания по Т2
sei(); // Глобально разрешаем прерывания
// Выводим надпись Test 
display_1 = 10; display_2 = 11; display_3 = 12; display_4 = 10;
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
while(1)
{ 
// Поочередно выводим 1234
display_1 = 1; display_2 = 13; display_3 = 13; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 2; display_3 = 13; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 13; display_3 = 3; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 13; display_3 = 13; display_4 = 4;
_delay_ms(250);
}
}

Подключение индикаторов с общим анодом

Подключение индикаторов с общим анодом

Для управления общими анодами индикаторов будем использовать биполярные транзисторы PNP структуры типа BC557. Как известно PNP транзисторы открываются при подаче на базу отрицательного напряжения, т.е. если подаем на базу лог. ноль транзистор откроется, если лог. единицу транзистор закроется. В программе это действие выполняет такой код:

PORTB = ~(1 << segcounter); // Подаем лог. 0

Также необходимо инвертировать комбинации сегментов:

PORTD = ~(SEGMENTE[display_1]);

или же записать эти комбинации с учетом использования индикатора с общим анодом, например если "0" - 0x3F - для общего катода, то для общего анода будет 0xC0.

// Подключение семисегментных индикаторов(ОА) к AVR через транзисторные ключи
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Массив комбинаций сегментов
char SEGMENTE[] = 
{
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
0x78, // t
0x79, // E
0x6D, // S
0x00  // blank
};
volatile unsigned char segcounter = 0;
volatile unsigned char display_1, display_2, display_3, display_4;
// Прерывание по переполнению T2, динамическая индикация
ISR (TIMER2_OVF_vect)
{	
PORTD = 0xFF; // Гасим все сегменты
PORTB = ~(1 << segcounter); // Засвечиваем общий анод, подаем лог. 0
	
switch (segcounter)
{	
case 0:
PORTD = ~(SEGMENTE[display_1]);
break; 
case 1:
PORTD = ~(SEGMENTE[display_2]);
break; 
case 2:
PORTD = ~(SEGMENTE[display_3]);
break;	
case 3:
PORTD = ~(SEGMENTE[display_4]);
break;		
}
if(segcounter++> 2) segcounter = 0;
}
// Главная функция
int main (void) 
{ 
DDRB = 0xFF; // Порт B выход
PORTB = 0xFF; // Лог. единицы чтобы индикатор не засвечивался при первом включении 
DDRD = 0xFF; // Порт D выход
PORTD = 0x00;
TCCR2 |= (1 << CS21);  // Предделитель на 8 
TIMSK |= (1 << TOIE2); // Разрешение прерывания по Т2
sei(); // Глобально разрешаем прерывания
// Выводим надпись Test 
display_1 = 10; display_2 = 11; display_3 = 12; display_4 = 10;
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
while(1)
{ 
// Поочередно выводим 1234
display_1 = 1; display_2 = 13; display_3 = 13; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 2; display_3 = 13; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 13; display_3 = 3; display_4 = 13;
_delay_ms(250);
display_1 = 13; display_2 = 13; display_3 = 13; display_4 = 4;
_delay_ms(250);
}
}

При симулировании программы в Протеусе могут быть проблемы в правильном отображении. Для этого колекторы NPN транзисторов необходимо подтянуть через резисторы 10кОм на плюс питания, а коллекторы PNP транзисторов на минус питания.

Комментарии  

0 #1 Дядя Вася 16.07.2017 07:27
А какой сакральный смысл в добавленном два раза в массив 0x6D ?
Сообщить модератору

Последние комментарии

Сейчас на сайте

Сейчас на сайте 73 гостя и нет пользователей