MAX7219 /MAX7221 — это драйвер 7 сегментного светодиодного индикатора, с общим катодом способный вывести 8 разрядов. Управление им производится по SPI интерфейсу.
В моем случае используется модуль с Aliexpress.

Пример кода написан для микроконтроллера Atmel Atmega8. SPI интерфейс реализован программным методом. Код простой как 3 рубля потому как писался по быстрому.
max7219.h
#define DIN PB0
#define CS PB1
#define CLK PB2
#define PORTLED PORTB
#define DDRLED DDRB
#define BIT(bit) (1<<(bit))
unsigned char digit[] = {
0xFE, // 0 ABCDEFG
0x30, // 1 0123456
0x6D, // 2
0x79, // 3
0x33, // 4
0x5B, // 5
0x5F, // 6
0x70, // 7
0x7F, // 8
0x7B, // 9
0x01 // -
};
void send_byte(unsigned char byte)
{
for(unsigned char i = 0; i < 8; i++)//в цикле посылаем побитно
{
if(byte & 0x80)//если бит=1 посылаем 1
{
PORTLED|=BIT(DIN);
PORTLED|=BIT(CLK);
_delay_us(1);
PORTLED&=~BIT(CLK);
}
else//иначе посылаем 0
{
PORTLED&=~BIT(DIN);
PORTLED|=BIT(CLK);
_delay_us(1);
PORTLED&=~BIT(CLK);
}
byte = (byte<<1);
}
}
void init() //Инициализация
{
PORTLED&=~BIT(CS);
//Тест индикатора выключен
send_byte(0x0F); //Адресс
send_byte(0x00); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
//Выйти из сна
send_byte(0x0C); //Адресс
send_byte(0x01); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
//Кол-во задействованных символов
send_byte(0x0B); //Адресс
send_byte(0x07); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
//Дешифраторы отключены
send_byte(0x09); //Адресс
send_byte(0x00); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
//Интенсивность свечения
send_byte(0x0A); //Адресс
send_byte(0x56); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
PORTLED&=~BIT(DIN);
}
void clear() //Очищение дисплея
{
PORTLED&=~BIT(CS);
send_byte(0x01); //Адресс
send_byte(0x00); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x02);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x03);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x04);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x05);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x06);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x07);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
send_byte(0x08);
send_byte(0x00);
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
PORTLED&=~BIT(DIN);
}
main.c
#define F_CPU 1000000UL // 1 MHz
#include <avr\io.h>
#include <util\delay.h>
#include <stdio.h>
#include "max7219.h"
unsigned char data,adress;
int main (void){
DDRLED=(1<<DIN)|(1<<CS)|(1<<CLK);// настраиваем нужные выводы порта на выход
PORTLED=(0<<DIN)|(0<<CS)|(0<<CLK);
data = 1;
adress = 0x0F;
init();
clear();
while(1){
for(unsigned char i = 0; i < 10; i++)//в цикле посылаем побитно
{
PORTLED&=~BIT(CS);
send_byte(0x4); //Адресс
send_byte(digit[i]); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
PORTLED&=~BIT(DIN);
_delay_ms(1000);
}
for(unsigned char i = 0; i < 10; i++)//в цикле посылаем побитно
{
PORTLED&=~BIT(CS);
send_byte(0x5); //Адресс
send_byte(digit[i]); // Данные
PORTLED|=BIT(CS);
PORTLED&=~BIT(CS);
PORTLED&=~BIT(DIN);
_delay_ms(1000);
}
clear();
}
}