Индикатор на TM1638

Вот такой индикатор, на базе TM1638. Собран аккуратно, в пакетике были даже провода доя подключения.

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

Видимо, для упрощения разводки платы  получилось, что внутренняя память чередуется – байт – семисегментный индикатор, байт (мл. бит) – одиночный светодиод. Поэтому по времени вышло неоптимально – нельзя использовать автоинкремент адреса. Впрочем, при тех микросекундах, наверное, не имеет особого значения.

Да, еще – регулировка яркости заметна на глаз – первые 4 градации.  Видимо, это особенность самой 1638 – по даташиту, градации заполнения – 1,2,4,10,11,12,13,14

Собственно текст модуля:

//______________________________________________________________________________
//
// Класс для платки LED-KEY на TM1638
// 8 7-ми сегментных, 8 LED, 8 key
// Должны быть определены дефайнами :
// TM1638_STB, TM1638_CLK, TM1638_DI, TM1638_DO, TM1638_OUTPUT
// Например:
//
//#define TM1638_STB PORTA_Bit0
//#define TM1638_CLK PORTA_Bit1
//#define TM1638_DO PORTA_Bit2
//#define TM1638_DI PINA_Bit2
//#define TM1638_OUTPUT DDRA_Bit2
//
// И еще должна быть определена тактовая, в мегагерцах, 8 МГц = 8
//
//#define MHZ 8
//
// TM1638_STB и TM1638_CLK должны быть настроены на ВЫВОД
// Структура памяти у этой платы странная – байт – индикатор,
// байт (точнее мл.бит) – свектодиод над ним. Потому автоинкрементная
// запись не годится. Хотя тут не структура памяти 1638, а схема платы виновата
//
// ____________________СИСТЕМА КОМАНД 1638______________________________________
//
// Address Command Set (1100.aaaa) a-dress
// Display Control Command Set (1000.PBBB) P-ower,B-right
// Data Command Set (0100.0fR0) f-ixed,R-ead
//______________________________________________________________________________
//
class LED_KEY_TM1638
{
private:

void write(char B);
char read();

public:

void init();

void clear(char fill); // очистка 7-сегментных (0) ну или заполнение
void off(); // выключить всё
void on(char bright); // ВКЛ. с опред. яркостью (8 градаций, 0=MIN)
void prints(char * str); // Вывести на 7-сегм. 8 байт из буфера, невзирая на 0
void printx(char sym,char X); // Вывести на 7-сегм. 1 байт в позицию X
void led_on(char num); // включить-выключить 1 светодиод
void led_off(char num);
void leds(char mask); // вывод всех 8-ми светодиодов, мл.бит=левый
char getkeys(); // вернет байт состояния кнопок, мл.бит = левый
};

// _____________________________________________________________________________
//
// Вывод байта SPI
// STB должен быть установлен ДО того
// _____________________________________________________________________________
void LED_KEY_TM1638::write(char B)
{
for (char i=8; i>0; i–)
{
TM1638_CLK = 0;
TM1638_DO = (B & 0×01);
TM1638_CLK = 1;
B = B >> 1;
}
}

// _____________________________________________________________________________
//
// STB должен быть установлен ДО того
// _____________________________________________________________________________
char LED_KEY_TM1638::read()
{
char B = 0;
for (char i = 8; i > 0; i–)
{
B = B >> 1;
TM1638_CLK = 0;
__delay_cycles(MHZ*1); // 1 uS
if (TM1638_DI) B |= 0×80;
TM1638_CLK = 1;
}
return(B);
}

// _____________________________________________________________________________
//
// очистка-заполнение
// LED не трогаем, только 7-сегментные
// _____________________________________________________________________________

void LED_KEY_TM1638::clear(char fill)
{
TM1638_OUTPUT = 1;

TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×42); // запись, НЕ авто++!
TM1638_STB = 1;
__delay_cycles(MHZ*1);

TM1638_STB = 0;
for (char i = 0; i < 8; i++)
{
write(0xC0+i+i); // address
write(fill);
}
TM1638_STB = 1;

TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Начальное состояние линий и очистка индикатора (но не включение! см. on() )
// _____________________________________________________________________________
void LED_KEY_TM1638::init()
{
TM1638_OUTPUT = 0;
TM1638_STB = 1;
TM1638_CLK = 1;
__delay_cycles(MHZ*1); // 1 uS
clear(0×00);
}

// _____________________________________________________________________________
//
// Выключить индикацию
// _____________________________________________________________________________
void LED_KEY_TM1638::off()
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
write(0×80); // OFF display
TM1638_STB = 1;
__delay_cycles(MHZ*1);
TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Включить индикацию, 8 уровней яркости
// _____________________________________________________________________________
void LED_KEY_TM1638::on(char bright)
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
write(0×88 | (bright & 0×07));
TM1638_STB = 1;
__delay_cycles(MHZ*1);
TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Вывод 8 -ми байт из буфера. Должно уже быть перекодировано в 7-сегм
// Например по таблице
// char decode0F[]={0x3F,0×06,0x5B,0x4F,0×66,0x6D, 0x7D,0×07,0x7F,0x6F,0×77,0x7C,0×39,0x5E,0×79,0×71};
// _____________________________________________________________________________
void LED_KEY_TM1638::prints(char * str)
{
TM1638_OUTPUT = 1;

TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×44); // запись, авто++
TM1638_STB = 1;
__delay_cycles(MHZ*1);

for (char i = 0; i < 8; i++)
{
TM1638_STB = 0;
write(0xC0+i+i); // address
write(*(str)++);
TM1638_STB = 1;
}

TM1638_OUTPUT = 0;

}

// _____________________________________________________________________________
//
// Вывод байта sym на индикатор X (без проверки границ, однао)
// Не забыть что 0 это код 0x3F
// _____________________________________________________________________________

void LED_KEY_TM1638::printx(char sym, char X)
{
TM1638_OUTPUT = 1;

TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×44); // запись, авто++
TM1638_STB = 1;
__delay_cycles(MHZ*1);

TM1638_STB = 0;
write(0xC0+X+X); // address
write(sym);
TM1638_STB = 1;

TM1638_OUTPUT = 0;

}

// _____________________________________________________________________________
//
// Зажечь одиночный светодиод сверху
// _____________________________________________________________________________
void LED_KEY_TM1638::led_on(char num)
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×44); // fixed write
TM1638_STB = 1;
__delay_cycles(MHZ*1);

TM1638_STB = 0;
write(0xC1+num+num); // address
write(0×01);
TM1638_STB = 1;

TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Погасить одиночный светодиод сверху
// _____________________________________________________________________________
void LED_KEY_TM1638::led_off(char num)
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×44); // fixed write
TM1638_STB = 1;
__delay_cycles(MHZ*1);

TM1638_STB = 0;
write(0xC1+num+num); // address
write(0×00);
TM1638_STB = 1;

TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Вывести сразу 8 одиночных индикаторов
// _____________________________________________________________________________
void LED_KEY_TM1638::leds(char mask)
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
__delay_cycles(MHZ*1); // 1 uS
write(0×44); // fixed write
TM1638_STB = 1;
__delay_cycles(MHZ*1);

for (char i=0; i<8; i++)
{
TM1638_STB = 0;
write(0xC1+i+i); // address
write(mask & 0×01);
TM1638_STB = 1;
mask>>=1;
}

TM1638_OUTPUT = 0;
}

// _____________________________________________________________________________
//
// Вернет состояние кнопок (нажато = 1)
// _____________________________________________________________________________
char LED_KEY_TM1638::getkeys()
{
TM1638_OUTPUT = 1;
TM1638_STB = 0;
__delay_cycles(MHZ*8);

write(0×42); // чтение, авто++
TM1638_OUTPUT = 0;
TM1638_DO = 1; // подпорка О.К.
__delay_cycles(MHZ*10);

char result = 0;
char T;
T = read(); //
if (T & 0×01) result |= 0×01;
if (T & 0×10) result |= 0×10;
T = read(); //
if (T & 0×01) result |= 0×02;
if (T & 0×10) result |= 0×20;
T = read(); //
if (T & 0×01) result |= 0×04;
if (T & 0×10) result |= 0×40;
T = read(); //
if (T & 0×01) result |= 0×08;
if (T & 0×10) result |= 0×80;

TM1638_STB = 1;
return(result);
}

}

Вот и всё. Вставляете это в текст или по include, не забыв предварительно определить пины (см. в шапке текста) и тактовую частоту МК . Потом объявляете

LED_KEY_TM1638 display;

При инициализации программы вызывваете display.init() – и можно работать. Так, чтобы зажечь первый одиночный светодиод – вызываете display.led_on(0). Да, еще надо “включить” весь блок индикатора вызвав display.on(яркость)