Главная » Статьи » Как подключить

Когда не хватает ног. Часть 3. Драйвер индикаторов MAX7221
  Сегодня будет представлен еще один способ сэкономить кучу ножек микроконтроллера в тех случаях когда нужно подключить семисегментные светодиодные индикаторы. Речь пойдет о использовании специализированного драйвера MAX7221 - это драйвера позволяют управлять семисегментными индикаторами (с общим катодом), светодиодными линейками или же с помощью него можно рулить до 64 светодиодами одновременно. Сами драйвера управляются по SPI интерфейсу, с максимальной поддерживаемой частотой работы интерфейса до 10 МГц.


 Распиновка ножек микросхемы:

 

     1 - DIN. Последовательный ввод данных. Данные загружаются в 16-ти разрядный сдвиговый регистр по переднему фронту тактового сигнала.

2,3,5-8,10,11 - DIG0-DIG7. Выводы для подключения общих катодов индикаторов.

4,9 - GND. Выводы для подключения земли

12 - LOAD (CS)  в MAX7221 данные загружаются в приёмный сдвиговый регистр только когда сигнал CS находится в состоянии низкого уровня (то есть только когда микросхема "выбрана", если говорить в терминах интерфейса SPI). Запоминаются и поступают к обработке также последние 16 принятых бит, происходит это также по переднему фронту сигнала CS.

13 - CLK. Вход сигнала тактирования, по которому происходит запись данных.

14-17, 20-23 - SEG A-SEG G, DP. Выводы для подключения сегментов семисегментных индикаторов. 

18 - ISET. К этому выводу подключается резистор (вторая нога резистора - к плюсу), позволяющий задавать пиковый ток сегмента и таким образом устанавливать яркость свечения сегментов. Минимальное сопротивление этого резистора должно быть 9,53 кОм, что примерно соответствует току сегмента 40мА.

19 - V+. Сюда подключается "+" питания.

24 - DOUT. Последовательный вывод данных. Эта нога понадобится если нужно будет соединить вместе два или более драйвера.



 Принцип работы с микросхемой MAX7221

 По сути MAX7221 (и его аналог MAX7219) по принципу работы схож с регистром 74HC595, с той лишь разницей что в микросхему загружается 16 бит данных. Первые загружаемые 8 бит необходимы для выбора регистра, в который нужно записать данные. Следующие 8 бит - те данные которые нужно записать в регистр. Говоря проще, сначала сообщаем микросхеме куда записать данные, а затем записываем нужные данные по выбранному адресу. 
 
 Чем интересен этот драйвер, так это тем, что он имеет два режима  работы.  Первый - работа в режиме обычного буфера с прямым управлением каждого сегмента. 
 Второй режим, так называемый BCD code B, который позволяет упростить вывод информации на индикатор за счет встроенного декодера символов. Символов кстати совсем немного, всего 16 - это цифры 0-9, знак "-", пустой символ и 4 быквы - "E", "H", "L", "P" (интересно какое слово можно составить?:)). Например, для того чтобы вывести во второй разряд цифру 2, нам нужно будет отправить адрес второго разряда (8 бит) и затем просто отправить двойку (еще 8 бит). Об этом режиме работы поговорим в следующей статье, сейчас же будет рассмотрен пример как работать с драйвером в режиме без декодирования.
 
 Для того чтобы управлять драйвером в первую очередь нужно ознакомится с картой адресов регистров. 
 
 
 
 

 

 Регистр No Op понадобится при совместном подключении нескольких драйверов. Для того, чтобы обратиться, например, к третьему драйверу в цепочке, не влияя на работу первых двух, - нужно для первых двух обратиться к регистру "No-op". Поскольку адрес этого регистра равен нулю, то сделать это очень просто: сначала за 16 тактов отправляем данные для третьего регистра, потом устанавливаем линию данных в ноль и отщёлкиваем ещё 2 раза по 16 тактов. В результате первый отправленный пакет будет загружен в третий регистр, а следующие два пакета (загруженные в первый и второй регистры) будут иметь адрес ноль, то есть будут обращаться к регистру "No-op".

 Digit 0-7 регистры, отвечающие за управление разрядами индикатора. Нумерация разрядов идет слева направо. Это очень удобно, например чтобы сменить одну цифру на индикаторе обращаемся по адресу регистра отвечающего за разряд, тем самым не трогая все остальные разряды.
 

 Регистр Decode Mode отвечает за режимы работы драйвера, о которых говорилось чуть выше: им можно выставить режим декодирования символов BCD code B и режим без декодирования No decode. 

 

 
 Через регистр Intensity осуществляется программная(!) настройка яркости свечения индикатора. Удобная штука на разные случаи, от возможности энергосбережения до индикации разных режимов работы девайса. Всего можно выбрать один из 16 уровней яркости.
 
 Регистром Scan Limit устанавливается число используемых разрядов индикатора. Если планируется использовать не все 8, а меньше, то рекомендуется отключать неиспользуемые. От этого будет зависеть частота обновления индикатора, а также пиковый ток через сегменты. Когда задействованы все 8 разрядов, частота обновления составляет около 800 Гц. При уменьшении количества разрядов частота возрастает, ее можно определить по формуле 8*800/N  (где N - число разрядов). Пиковый ток через сегменты также возрастает при отключении неиспользуемых разрядов.
 
 Через регистр Shutdown можно включить режим энергосбережения, при котором все индикаторы гаснут, данные и состояние регистров при этом не теряются. Режим энергосбережения включается записью нуля в регистр shutdown. При записи туда единицы драйвер выходит из энергосбережения. 
Энергопотребление в этом режиме падает до 150 мкА.
 
 Display Test используется для проверки подключенного индикатора, в тестовом режиме включаются все сегменты индикатора. Даже если драйвер находится в режиме энергосбережения, режим тестирования включит сегменты. 
 
 После запитывания все регистры драйвера сброшены, поэтому в первую очередь нужно провести настройку. Настройки драйвера (запись нужных значений в регистры Decode Mode, Intensity, Scan Limit, Shutdown и Display Test) необходимо производить каждый раз после подачи питания, эти значения не сохраняются. 
 
 
 
 Работа с драйвером в режиме No-decode

 

 В режиме No decode мы можем управлять каждым сегментом любого разряда напрямую. Соответствие сегментов индикатора битам в регистре Digit представлено на картинке ниже и  для того чтобы зажечь определенный сегмент необходимо записать в соответствующий бит единицу.




 
 
 Для примера: нам нужно вывести в первый разряд 8-и разрядного индикатора цифру 1. Сначала отправляем первые 8 бит адреса регистра соответствующего первому разряду (см. таблицу с картой адресов регистров). Нумерация разрядов индикатора идет слева направо (вот таким образом 0.1.2.3.4.5.6.7.), поэтому первый справа разряд (Digit 7), будет иметь адрес &h08, это значение и отправляем. Затем отправляем данные которые должны включить сегменты В и С, по таблице соответствия (см. выше) за эти сегменты отвечают биты D5 и D4. Таким образом следующие 8 бит которые мы должны отправить будут такие: 00110000, или если в шестнадцатеричном представлении - &h48. Подобным образом можем управлять и другими разрядами и сегментами индикатора. Ничего сложного, правда? ;)
 
 
 
 
 А теперь небольшой рабочий пример. У меня оказался только четырехразрядный индикатор, для демонстрации возможностей вполне сгодится. Соединил по схеме ниже. Неиспользуемые выводы можно оставлять болтаться в воздухе. Микроконтроллер Attiny2313 тактируется от внутреннего генератора на 8 МГц, напряжение питания схемы 5 вольт.






 демо код в Bascom-AVR
 
$regfile = "attiny2313.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 10
$framesize = 40

Config Portd = Output

Cs Alias Portd.1
Ser_clk Alias Portd.2
Ser_data Alias Portd.3

Dim A As Word
Dim Digit(8)as Byte
Dim Y As Byte
Dim Disp_num As Byte
Dim Disp_data As Byte
Dim Digit_str As String * 4
Dim Temp_str As String * 3
Gosub Max7219_setup

Digit_str = "Good"           'строка которую выведем на дисплей
Gosub Prepare                'вызываем подпрограмму подготовки и отправки данных

Wait 3

Do                           'в главном цикле просто выводим увеличивающее на 1 число
Waitms 200
Incr A                       'переменная значение которой выводим на индикатор
Digit_str = Str(a)
Digit_str = Format(digit_str , "0000")
Gosub Prepare
Loop

End



'Подготовка данных для передачи
Prepare:
Do
For Y = 1 To 4
   Temp_str = Mid(digit_str , Y , 1)
   Select Case Temp_str
      Case "0" : Temp_str = "126"                           '&b01111110
      Case "1" : Temp_str = "48"                            '&b00110000
      Case "2" : Temp_str = "109"                           '&b01101101
      Case "3" : Temp_str = "121"                           '&b01111001
      Case "4" : Temp_str = "51"                            '&b00110011
      Case "5" : Temp_str = "91"                            '&b01011011
      Case "6" : Temp_str = "95"                            '&b01011111
      Case "7" : Temp_str = "112"                           '&b01110000
      Case "8" : Temp_str = "127"                           '&b01111111
      Case "9" : Temp_str = "123"                           '&b01111011
      Case "." : Temp_str = "128"                           '&b10000000
      'можно и самостоятельно ввести нужные символы
      Case "A" : Temp_str = "119"                           '&b01110111
      Case "C" : Temp_str = "78"                            '&b01001110
      Case "E" : Temp_str = "79"                            '&b01001111
      Case "G" : Temp_str = "94"                            '&b01011110
      Case "o" : Temp_str = "29"                            '&b00011101
      Case "d" : Temp_str = "61"                            '&b00111101
      Case " " : Temp_str = "0"                             '&b00000000
      'и так далее...
   End Select
   Digit(y) = Val(temp_str)

      Disp_num = Y             'знакоместо (разряд) на который выводим текущую цифру

      Disp_data = Digit(y)     'данные которые отправляем на выбранный разряд
      Gosub Disp_write
Next Y
Loop Until Y = 5    'когда вывели данные на все 4 разряда возвращаемся в главный цикл
Return



'Передаем данные в max7221
Disp_write:
Ser_data = 0
Ser_clk = 0
Cs = 0
Shiftout Ser_data , Ser_clk , Disp_num , 1   'отправляем номер разряда
Shiftout Ser_data , Ser_clk , Disp_data , 1  'отправляем данные в этот разряд
Cs = 1
Return


'инициализации и настройка регистров max7221
Max7219_setup:
Disp_num = &H0C : Disp_data = 0     'режим Shutdown (0-включен, 1-выключен)
Gosub Disp_write
Disp_num = &H09 : Disp_data = 0     'режим прямого управления сегментами индикатора
Gosub Disp_write
Disp_num = &H0A : Disp_data = 10    'уровень свечения сегментов (0-минимум, 15-максимум)
Gosub Disp_write
Disp_num = &H0B : Disp_data = 3     'число используемых разрядов (счет от 0)
Gosub Disp_write
Disp_num = &H0F : Disp_data = 0     'тестовый режим выключен (0-выключен, 1-включен)
Gosub Disp_write
Disp_num = &H0C : Disp_data = 1        
Gosub Disp_write
Return


 Код хорошо прокомментирован, поэтому дополнительного пояснения надеюсь приводить не нужно. А ниже результат работы 

 

 
 
 
 Далее будет описана работа с драйвером в режиме BCD code B ( вторая часть )
 
 
 
 
 И напоследок отдельное спасибо нашему камраду Максиму (известного под ником max) за то, что подкинул мне эти замечательные микрухи. 
 
 
 
 
Категория: Как подключить | Добавлено: 31.05.2013
Просмотров: 40140 | Комментарии: 26 | Теги: MAX7221, ATtiny2313, bascom-avr, индикатор | Рейтинг: 4.7/10
Всего комментариев: 26
26 max   (08.03.2018 14:02) [Материал]
Не за что.

25 Dmitriy   (08.03.2018 09:25) [Материал]
Максим, спасибо, оказывается там нужно было войти на форум, чтобы увидеть материал, буду разбираться. "Чем больше узнаешь, тем больше понимаешь, как мало знаешь!" - Сократ

24 max   (08.03.2018 07:48) [Материал]
Да, на соседнем форуме есть: http://bascomavr.3bb.ru/viewtopic.php?id=1073

23 Dmitriy   (08.03.2018 00:39) [Материал]
Доброго времени суток господа, вопрос, есть ли наработки по управлению матрицами 8*8 в комплекте с MAX7219 ? Решил поиграться с модулем из четырех матриц. Делаю вывод построчно, каждая строка четыре раза по 8 байт и так 8 строк.Сейчас на этапе создания таблицы символов. Занятная штуковина вообще, можно буковки писать и смайлики рисовать.

22 deadik   (28.01.2015 01:00) [Материал]
С Bascom-AVR к сожалению не знаком, может кто переписывал это под AVR-GCC на C?

21 sany2   (15.05.2014 23:55) [Материал]
marss70 , страница 13 Datasheet MAX7219/7221

20 marss70   (14.05.2014 21:15) [Материал]
Кто подскажет, как соединить каскадом несколько MAXов для индикации более 8 знаков?
Желательно с примером

19 SAnEK_Bo   (13.02.2014 03:30) [Материал]
Здравствуйте. Спасибо за хороший урок. Я учусь программировать на си и знаю самую малость. Не могли бы вы написать такую же программу на си. Очень хочется освоить эту микросхему. Весь гугл перелазил, не нашел такой программы. А разбираться по шагам мне проще, когда есть готовая программа. Спасибо заранее, надеюсь спецам не составит труда написать для меня небольшую программу.

18 marss70   (24.09.2013 12:54) [Материал]
Вопрос закрыл, вместо
Disp_num = Y
Вставил
Select Case Y
Case 1 : Disp_num = 8
Case 2 : Disp_num = 7
Case 3 : Disp_num = 6
Case 4 : Disp_num = 5
Case 5 : Disp_num = 4
Case 6 : Disp_num = 3
Case 7 : Disp_num = 2
Case 8 : Disp_num = 1
End Select

Всё заработало отлично, спасибо автору!

17 marss70   (23.09.2013 22:11) [Материал]
При использовании готового модуля http://www.aliexpress.com/item/MAX7219-Digital-Tube-Display-Module-Free-Shipping-Wholesale/725507051.html выявлен эффект переворота вывода информации задом-на-перёд ,т.е. в программе задано
Digit_str = "12345678", а на дисплее "87654321"... Вопрос, как перевернуть информацию?

+2   Спам
16 sany2   (03.06.2013 20:19) [Материал]
Так же слежу за всеми проектами(спасибо этому сайту).Сегодня для приколу решил поучаствовать в аукционе на Ebay-и умудрился даже выиграть-5PCS MAX7221CNG за 2,5 бакса(в итоге 80 руб.).Мелочь-а приятная.

+3   Спам
15 Петр   (03.06.2013 16:15) [Материал]
>>А какие еще есть варианты?

Деление по модулю (в баскоме это MOD) позволит разделить число составляющие.
Привожу код для компа. На байском не составит труда его переписать.

Dim Out.a(3)
x=1234

For i=0 To 3
Out(i) = x % 10 ; В баскоме, "%" заменить на MOD.
x / 10
Next i

For i=0 To 3
Debug Out(i)
Next i

14 max   (03.06.2013 15:19) [Материал]
>exersizze
>да, лучше эту микруху сразу брать у китайцев
Это точно. Подключил плату, как у Valera18 в ссылке, все заработало, подключил свой дисплей - ни фига не работает. Поменял микры - обе работают. Несколько раз передернул питание - завелся и мой дисплей.
>Петр
>Я конечно извиняюсь, но зачем нужна эта "игра со строками"?
А какие еще есть варианты?

13 Петр   (02.06.2013 23:52) [Материал]
Я конечно извиняюсь, но зачем нужна эта "игра со строками"? Это же "раздует" прошивку.

+2   Спам
12 exersizze   (02.06.2013 22:39) [Материал]
да, лучше эту микруху сразу брать у китайцев, у нас в магазинах цена на нее 520 руб wacko
http://voltmaster-samara.ru/search/?q=7221

11 Valera18   (02.06.2013 15:26) [Материал]
Для amv2000

Например: здесь, вместе с Led матрицей, за 120 рублей:
http://www.aliexpress.com/item/MAX7219-dot-matrix-module-module-DIY-kit-module-MCU-control-module/654788720.html

или тут:
http://www.ebay.com/sch/i.html?_trksid=m570.l1313&_nkw=MAX7219&_sacat=0&_from=R40

10 amv2000   (01.06.2013 19:15) [Материал]
Где и за сколько приобретали MAX7219?

9 max   (01.06.2013 08:13) [Материал]
Хорошо.

8 Bonio   (01.06.2013 00:48) [Материал]
Почитал даташит, в общем то ничто не мешает повесить несколько max7219, даже с другими spi устройствами на один порт.
Вся разница в том, что в max7221 16 бит захватываются пока CS на нуле, а по восходящему фронту защелкиваются. В max7219 захватываются все биты, но по восходящему фронту на LOAD защелкиваются последние 16.
Плюс в max7221 на сегментных выходах более плавные фронты, что снижает уровень помех в схеме.

7 exersizze   (31.05.2013 21:22) [Материал]
Макс глянь личку, скинул туда исходник для проверки.

6 max   (31.05.2013 21:06) [Материал]
Посадить на разные ножки LOAD можно и у MAX7219. Есть пример: http://www.elektronik-web.de/htm/projekt2.htm Но это не интересно - использовать лишние порты.

5 exersizze   (31.05.2013 20:41) [Материал]
MAX7221 в плане расширения гораздо удобней, проще работать. Регистр no-ор вообще тогда можно не трогать, а посадить ножки CS каждого драйвера на отдельную ножку микроконтроллера и выбирать тот драйвер в который надо вывести данные подачей на CS нуля. Это как раз то отличие о котором писал ниже. Но тогда проигрываем в количестве при увеличении числа драйверов.
Попробую сейчас набросать код для вывода на 16 разрядов согласно "Figure 3. Cascading MAX7219/MAX7221s to Drive 16 Seven-Segment LED Digits"

4 max   (31.05.2013 19:31) [Материал]
Меня смущает описание из даташита: "No-Op Register
The no-op register is used when cascading MAX7219s or MAX7221s. Connect all devices’ LOAD/CSinputs together and connect DOUT to DIN on adjacent devices. DOUT is a CMOS logic-level output that easily drives DIN of successively cascaded parts. (Refer to the Serial Addressing Modessection for detailed information on serial input/output timing.) For example, if four MAX7219s are cascaded, then to write to the fourth chip, sent the desired 16-bit word, followed by
three no-op codes (hex 0xXX0X, see Table 2). When LOAD/CSgoes high, data is latched in all devices. The first three chips receive no-op commands, and the
fourth receives the intended data."
и
"Figure 3. Cascading MAX7219/MAX7221s to Drive 16 Seven-Segment LED Digits"
Везде фигурирует MAX7219. Нужно проверить.

exersizze, можешь поправить код для подключения нескольких микросхем? У меня индикаторы есть.

3 exersizze   (31.05.2013 16:24) [Материал]
max,  есть за что, если бы не ты фиг бы когда я бы с ними связался))
Bonio, отличия незначительны, max7221 для того чтобы записать данные в буфер должен иметь на входе CS всегда низкий уровень. Тогда как для 7219 неважно какой уровень на этой ножке. Поэтому 7221 полностью соответствует стандарту SPI, так как можно работать с отдельными драйверами в каскаде не мешая работе других. Представленный код, кстати, работает и с max7219.

2 Bonio   (31.05.2013 15:45) [Материал]
А в чем отличие MAX7219 от MAX7221?

1 max   (31.05.2013 15:39) [Материал]
Было бы за что.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]






авторизация