PIC. Урок 16. MSSP. SPI. Светодиодный индикатор MAX7219. Часть 2



В предыдущей части занятия мы познакомились с микросхемой MAX7219, а также написали некоторые служебные функции для работы будущей библиотеки.

 

Далее мы сначала посмотрим, как выглядит наш индикатор

 

 

Мы видим, что вместо восьмиразрядного индикатора в модуле установлены два четырёхразрядных индикатора, что, собственно, не очень тяготит, так как разряды все находятся друг от друга на одинаковом расстоянии, так сказать, без разрывов. Также мы видим, что с обоих сторон к индикатору подключено по 5 контактов. С правой стороны контакты дли сквозного подключения следующего такого индикатора, поэтому мы используем левый разъём и подключаемся именно к нему

 

 

Мы видим ножку для подключения питания (VCC), общего провода (GND), вход информационных данных (DIN), который мы подключаем к ножке SDO нашего контроллера, ножку CS (Chip Select) и ножку синхронизации CLK. Вот таким образом мы подключим индикатор к нашей отладочной плате, воспользовавшись специальным разъёмом на ней

 

 

Теперь вернёмся к документации на микросхему и подумаем, как мы можем её инициализировать.

Сначала посмотрим в даташите таблицу адресов регистров

 

 

Вернёмся к нашей функции инициализации.и включим сначала режим декодирования

 

__delay_ms(500);

Send_7219(0x09,0xFF);//Set Decode mode

 

С девяткой ясно. Разбираемся с 0xFF.

Для этого есть другая таблица с примерами настройки декодирования

 

 

То есть мы видим, что каждому биту в аргументе команды соответствует один разряд, то есть значением 0xFF мы включили декодирование на все разряды нашего индикатора. А, например, если бы передали только 0x0F, то мы бы включили только 4 младших разряда.

Теперь давайте проверим, как передаются данные в нашу микросхему.

Для это сначала создадим в заголовочном файле прототип на функцию инициализации и вызовем её в функции main() в файле main.c

 

unsigned int i=0;

LED7219_init();

 

Подключим логический анализатор к соответствующим ножкам, используя стандартный разъём возле панели контроллера

 

 

Вернемся к проекту.

Питание отдельно мы подводить не будем, питание будет подаваться от программатора, поэтому проверим данные настройки, соберём код и прошьём наш контроллер.

Перейдём в аналитическую программу, включим там три канала, на самый первый установим триггер по возрастающему фронту

 

 

Настроим распознавание протокола SPI следующим образом

 

 

Запустим анализ и перезагрузим контроллер.

Из диаграммы в программе логического анализа мы видим, что байты наши нормально передались и распознались

 

 

Также мы можем видеть, что тактируется наш SPI частотой 1 мегагерц

 

 

Поэтому логический анализатор мы теперь можем смело отключить и продолжить работу с индикатором.

 

 

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

 

 

Здесь мы видим, какие символы мы можем передать с помощью декодера. Вообщем-то, основные все есть. Обидно только, что нет буквы «C«. Ну да ничего. Также мы видим, что код символа передаётся только в четырёх младших разрядах байта данных, следующие три бита вообще не используются, а последний старший бит отвечает за точку.

Следующим шагом нашей инициализации будет настройка количества задействованных разрядов. Для этого у нас есть регистр с адресом 0x0B.

Вот его таблица

 

Здесь схема простая. Значение данному регистру мы передаём, равное количеству задействованных разрядов, уменьшенное на 1.

Поэтому давайте добавим глобальную переменную для количества разрядов и сразу её и инициализируем

 

#define cs RA5

char dg=8;

 

Вернёмся в тело функции инициализации и включим все разряды

 

Send_7219(0x09,0xFF);//Set Decode mode

Send_7219(0x0B,dg-1);//Set ON all digits

 

Теперь займёмся яркостью свечения. Для этого у нас существует отдельный регистр с адресом 0x0A

 

 

 

Так как у нас MAX7219, то для нас первая колонка. Здесь я думаю всё просто. Поэтому зададим желаемую яркость свечения в нашей функции инициализации

 

Send_7219(0x0B,dg-1);//Set ON all digits

Send_7219(0x0A,0x02);//Intensity

 

Ну и последняя настройка — это включение индикатора, также существует отдельный регистр, думаю, показывать его нет смысла, так как у него всего два значения: 0 — отключено, 1 — включено

 

Send_7219(0x0A,0x02);//Intensity

Send_7219(0x0C,0x01);//Set Normal Operation

 

Выше данной функции создадим функцию очистки дисплея, в которой отправим символ пустоты во все разряды

 

//-----------------------------------------------------

void Clear_7219 (void)

{

  char i=dg;

  do

  {

    Send_7219(i,0xF);//Symbol blank

  } while (--i);

}

//-----------------------------------------------------

 

На данную функцию мы создадим прототип, так как она нам потом потребуется.

Также вызовем её в нашей функции инициализации

 

  Send_7219(0x0C,0x01);//Set Normal Operation

  Clear_7219();

}

 

На этом наша инициализация закончена.

 

 

В библиотеке будут ещё некоторые функции, но пока перейдём в файл main.c в функцию main() и попробуем наконец-то что-то отобразить на нашем индикаторе

 

LED7219_init();

Send_7219(1,0x1);//1

Send_7219(2,0x2);//2

Send_7219(3,0x3);//3

Send_7219(4,0x4);//4

Send_7219(5,0x5);//5

Send_7219(6,0x6);//6

Send_7219(7,0x7);//7

Send_7219(8,0x8);//8

 

Мы по очереди послали символы в каждый разряд, начиная справа.

Если собрать код и прошить контроллер, то получится вот такая вот картина

 

 

Отлично! Индикатор работает.

Вернёмся теперь в файл LED7219.c и добавим функцию вывода целого числа на индикатор после функции очистки индикатора Clear_7219

 

//-----------------------------------------------------

void Number_7219 (volatile long n)

{

  unsigned char ng=0; //variable for negative

}

//-----------------------------------------------------

 

Мы создали локальную переменную для флага отрицательного числа.

Дальше добавим условие, при котором мы включим данный флаг и, соответственно, входное значение умножим на -1, чтобы сделать его положительным и в дальнейшем уже работать как с неотрицательной величиной

 

unsigned char ng=0; //variable for negative

if(n<0)

{

  ng=1;

  n*=-1;

}

 

Добавим ещё одну локальную переменную для счёта

 

  n*=-1;

}

unsigned char i=0;

 

Дальше цикл, в котором мы заполним разряды цифрами из нашей величины

 

  unsigned char i=0;

  do

  {

    i++;

    if(n==0)

    {

      if(ng)

      {

        Send_7219(i,0x0A); //symbol negative

        ng=0;

      }

      else Send_7219(i,0xF);

    }

    else

    {

      Send_7219(i,n%10);

      n/=10;

    }

  } while(i<8);

}

 

Мы в данном цикле, если n равен нулю, то есть мы уже достигли последнего разряда проверяем отрицательность числа, если таковая присутствует, то выводим соответствующий символ в нужный разряд, сбросив на всякий случай флаг. А если число неотрицательное, то выводим символ пустоты. Также в цикле мы последовательно выводим каждую цифру числа, применяя деление по модулю на 10 в каждой последующей итерации.

Добавим на нашу функцию прототип, вернёмся в функцию main() файла main.c и, спустя некоторое время, выведем какое-нибудь большое отрицательное число

 

Send_7219(8,0x8);//8

__delay_ms(1000);

Number_7219(-2016);

 

Соберём код, прошьём контроллер и посмотрим результат

 

 

Вернёмся теперь в файл LED7219.c и добавим функцию вывода целого числа только в правую половинку индикатора после функции очистки индикатора Number_7219

 

//-----------------------------------------------------

void NumberR_7219 (volatile int n)

{

  unsigned char ng=0;

  if(n<0)

  {

    ng=1;

    n*=-1;

  }

  unsigned char i=0;

  do

  {

    i++;

    if(n==0)

    {

      if(ng)

      {

        Send_7219(i,0x0A);

        ng=0;

      }

      else Send_7219(i,0xF);

    }

    else

    {

      Send_7219(i,n%10);

      n/=10;

    }

  } while(i<4);

}

//-----------------------------------------------------

 

Функция аналогична предыдущей, только здесь мы используем не все разряды.

Ниже добавим ещё одну аналогичную функцию, которая будет выводить целое число в левую половину нашего индикатора

 

//-----------------------------------------------------

void NumberL_7219 (volatile int n)

{

  unsigned char ng=0;

  if(n<0)

  {

    ng=1;

    n*=-1;

  }

  unsigned char i=4;

  do

  {

    i++;

    if(n==0)

    {

      if(ng)

      {

        Send_7219(i,0x0A);

        ng=0;

      }

      else Send_7219(i,0xF);

      }

    else

    {

      Send_7219(i,n%10);

      n/=10;

    }

  } while(i<8);

}

//-------------------------------------------------------

 

Данная функция также аналогична предыдущей, только вывод здесь начинается с 5 разряда справа.

Добавим на данные функции прототипы и также, спустя некоторое время, вызовем их в функции main() файла main.c

 

Number_7219(-2016);

__delay_ms(1000);

Clear_7219();

NumberR_7219(-125);

__delay_ms(1000);

NumberL_7219(-521);

__delay_ms(1000);

 

Соберём код, прошьём контроллер и посмотрим результат

 

 

Отлично!

Теперь давайте сочиним что-нибудь подинамичнее и в бесконечный цикл добавим код, в котором в правой части значения будут непрерывно инкрементироваться, а в левой — декрементироваться

 

while(1)

{

  NumberR_7219(i);

  NumberL_7219(9999-i);

  i++;

  if(i>9999) i=0;

  __delay_ms(100);

}

 

Соберём код, прошьём контроллер и полюбуемся результатом нашей работы

 

 

Итак, на данном занятии мы закрепили работу модуля MSSP в режиме SPI на практике, подключив к нашему контроллеру очень функциональный 8-разрядный светодиодный индикатор.

Впоследствии нам ещё предстоит поработать с шиной SPI в режиме приёма, а также, возможно в режиме ведомого устройства.

Всем спасибо за внимание!

 

 

Предыдущая часть Программирование МК PIC Следующий урок

 

Исходный код

 

 

Купить программатор (неоригинальный) можно здесь: PICKit3

Купить программатор (оригинальный) можно здесь: PICKit3 original

Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A

Логический анализатор 16 каналов можно приобрести здесь

Индикатор светодиодный семиразрядный с драйвером MAX7219

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

PIC MSSP. SPI. Светодиодный индикатор MAX7219

2 комментария на “PIC. Урок 16. MSSP. SPI. Светодиодный индикатор MAX7219. Часть 2
  1. Dmitrij:

    спасибо, все получилось.

  2. Nikita:

    Здравствуйте.А каким методом можно зажечь точки на дисплее?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*