В предыдущей части занятия мы познакомились с микросхемой 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
Смотреть ВИДЕОУРОК (нажмите на картинку)
спасибо, все получилось.
Здравствуйте.А каким методом можно зажечь точки на дисплее?