7-и сегментный ЖК-индикатор. Пример использования.
Cемисегментные ЖК дисплеи (индикаторы) очень древние существа. Но даже в мире символьных, графических и цветных дисплеев у них есть свое место. Они особо полезны для обеспечения отличной видимости при ярком освещении (на солнце). Имеют мизерное энергопотребление.
Дисплеи могут быть с электроникой и без. Именно о них (без электроники) и пойдет речь.
Как правило, у таких дисплеев один вывод общий, и по выводу на каждый сегмент. В управлении такими дисплеями нет ничего сложного. Но есть две особенности:
- Для управления таким дисплеем требуется много выводов микроконтроллера, по одному на каждый сегмент. Для 3 разрядного индикатора 24 вывода.
- Контрастность может падать, если постоянное напряжение приложено в течение долгого времени. В этом случае жидкокристаллическая структура деградирует из-за миграции ионов.
Для подключения 3-х разрядного семисегментного индикатора я использовал микросхемы сдвиговых регистров 74HC/HCT164. Это позволяет управлять любым количеством разрядов индикатора, задействовав только 3 ноги контроллера.
Схема для 3-х разрядного ЖКИ (LCD3.0-13): 
Схему можно наращивать до нужного количества выводов добавляя микросхемы 74HC/HCT164. Эту схему можно использовать и для семисегментных светодиодных индикаторов и для работы с другими индикаторами, где требуется много ног.
Схема подключена к микроконтроллеру следующим образом:
DSA -> PINC5
CP -> PINC4
MR -> PINC3
Распиновка LCD3.0-13:
Теперь займемся программной частью.
#include "stdio.h";
#include "avr/io.h";
#include "util/delay.h";
// Настраиваем порты для DSA, DSA, RESET
#define LCD_DSA_PORT PORTC
#define LCD_DSA_PORT_DDR DDRC
#define LCD_DSA PINC5
#define LCD_CLK_PORT PORTC
#define LCD_CLK_PORT_DDR DDRC
#define LCD_CLK PINC4
#define LCD_RESET_PORT PORTC
#define LCD_RESET_PORT_DDR DDRC
#define LCD_RESET PINC3
uint8_t LCDFlag;
//1 - точка
//2 - нижний левый
//4 - нижний
//8 - нижний правый
//16 - верхний правый
//32 - верхний
//64 - верхний левый
//128- середина
#define LCD_NULL 0
#define LCD_DOT 1
#define LCD0 2+4+8+16+32+64
#define LCD1 8+16
#define LCD2 32+16+128+2+4
#define LCD3 32+16+128+8+4
#define LCD4 64+128+16+8
#define LCD5 32+64+128+8+4
#define LCD6 64+128+2+4+8+32
#define LCD7 32+16+8
#define LCD8 2+4+8+128+64+16+32
#define LCD9 64+32+16+128+8+4
const uint8_t NSymbol[] = {LCD0, LCD1, LCD2, LCD3, LCD4, LCD5, LCD6, LCD7, LCD8, LCD9};
// Функция выводит на семисегментный LCD целое число от 0 до 999
void LCD7_Show_Int(int value) {
uint8_t byte[3];
uint8_t b,n;
byte[2] = value/100;
byte[1] = (value-byte[2]*100)/10;
byte[0] = (value - byte[2]*100 - byte[1]*10);
// Сброс сдвиговых регистров
LCD_RESET_PORT &= ~(1< LCD_RESET_PORT |= (1< // Разряд 3
if (byte[2] > 0)
byte[2] = NSymbol[byte[2]];
else
byte[2] = LCD_NULL;
// Разряд 2
if ((byte[1] > 0) || (byte[2] > 0))
byte[1] = NSymbol[byte[1]];
else
byte[1] = LCD_NULL;
// Разряд 1
byte[0] = NSymbol[byte[0]];
// Переворачивает уровни для поддержания контрастности
if (LCDFlag == 0) {
byte[2] &= 254;
LCDFlag = 1;
}
else {
byte[0] = ~byte[0];
byte[1] = ~byte[1];
byte[2] = ~byte[2] | 1;
LCDFlag = 0;
}
// Задвигаем данные в сдвиговые регистры
for(b=0; b<3; b++) {
for(n=0; n<8; n++) {
if ((0x01 & (byte[b]>>n)) == 1)
LCD_DSA_PORT |= (1 << LCD_DSA);
else
LCD_DSA_PORT &= ~(1 << LCD_DSA);
LCD_CLK_PORT &= ~(1 << LCD_CLK);
LCD_CLK_PORT |= (1 << LCD_CLK);
}
}
}
int main( void )
{
// Настраиваем порты для DSA, DSA, RESET
LCD_DSA_PORT_DDR |= (1 << LCD_DSA);
LCD_CLK_PORT_DDR |= (1 << LCD_CLK);
LCD_RESET_PORT_DDR |= (1 << LCD_RESET);
while(1) {
LCD7_Show_Int(123); // Выводим значение от 0 до 999
_delay_us(100);
}
}
Печатную плату, схему и пример на GCC можно качайте здесь.
Смотри так же: Использование cимвольных жидкокристаллических LCD дисплеев. Пример на GCC (WinAVR) для Atmega 8
Спасибо за хорошую идею. Но есть небольшая просба для неопытных. Можно ли добавить статью следующими моментами. 1. Соответствие выводов регистров выводам дисплея. Например Q1-a1, Q2-b1. Хотя бы для одного сегмента. Потому как пока непонятно как его вообще подключить? Например с какой ноги регистра подается питание на общий вывод? 2. Описать логику работы - что бы можно было понимать как все-таки происходит засвечивание сегмента. Не совсем понятно - каким образом подается разнополярное питание и прочее. С какой частотой меняется полярность? Понимаю что вопросы может и простецкие, но думаю, что многие Вам их еще будут задавать. Заранее спасибо.
Подскажите, а есть ли такой пример подключения к микроконтроллеру AVR?
Это и есть пример подключения к ATmega8
А без использования сдвиговых регистров? Напрямую, к выводам микроконтроллера.
И еще с использованием динамической индикации
Tags
bme280 bmp280 gps mpu-6050 options stm32 ssd1331 ssd1306 eb-500 3d-printer soldering tim mpu-9250 dma watchdog piezo exti web raspberry-pi docker ngnix solar bluetooth foc html css brushless flask dc-dc capture gpio avr rs-232 mpx4115a atmega mongodb st-link barometer pwm nvic git java-script programmator dht11 hih-4000 pmsm encoder max1674 smd sensors rtc adc lcd motor timer meteo examples i2c usb flash sms rfid python esp8266 servo books bldc remap eeprom bkp battery ethernet uart usart displays led websocket nodemcu wifi
Архіви

