В предыдущей части урока мы познакомились с режимом SLAVE SPI, собрали схему для нашего урока и создали проект для ведущего устройства.
Теперь перейдём к ведомому устройству.
Проект за основу для него был взят из прошлого урока с именем MCP3201 и проекту было присвоено имя SPI_SLAVE.
Откроем наш проект в MPLAB X, сделаем его главным, зайдём в настройки и убедимся, что контроллер будет питаться от программатора.
Отключим от проекта файлы led.h и led.c, затем их удалим из него физически.
Перейдём в файл main.c и уберём также подключение библиотеки индикатора
#include "led.h"
Также удалим из файла все глобальные переменные и функции, кроме main, из которой также удалим весь код, оставив лишь пустой бесконечный цикл
void main()
{
while(1)
{
}
}
Добавим глобальную переменную
#include "main.h"
//------------------------------------------------
unsigned char bt=0;
//------------------------------------------------
В функции main() проинициализируем порт B для работы со светодиодами, а также настроим регистр ADCON1, с помощью битов которого мы настроим все ножки порта A как цифровые, иначе у нас рискует не заработать ножка CS.
void main()
{
TRISB = 0x00;
PORTB = 0xFF;
ADCON1 = 0x07;
Настроим ножки для шины SPI
ADCON1 = 0x07;
TRISC3 = 1;// RC3 (SCLK) AS INPUT
TRISC4 = 1;//RC4 (MOSI) AS INPUT
PORTCbits.RC5 = 1;
TRISC5 = 0;//RC5 (MISO) AS OUTPUT
Мы включили на вход ножку тактирования, так как тактирование происходит от ведущего устройства, а также ножку MOSI.
Сначала отключаем SPI
TRISC5 = 0;//RC5 (MISO) AS OUTPUT
SSPEN = 0; // SPI Disabled
Разрешим глобальные, а также периферийные прерывания
SSPEN = 0; // SPI Disabled
GIE = 1;
PEIE = 1;
Настроим SPI
PEIE = 1;
SMP = 0; // SMP=1 (Input data sampled at middle data output time)
// SKE=1, SKP=0 (SPI_MODE0)
CKP = 0;
CKE = 1;
// SSPM3:SSPM0 = 0101 (SPI Slave mode, clock = SCK pin. SS pin control disabled. SS can be used as I/O pin.)
SSPM3 = 0;
SSPM2 = 1;
SSPM1 = 0;
SSPM0 = 1;
SSPIF = 0; //No SSP interrupt condition has occurred
SSPIE = 1; //SSP interrupt Enabled
SSPEN = 1; //SPI Enabled
Все биты я описал в комментариях, какие чем занимаются.
Тело бесконечного цикла будет символическое — только задержка
while(1)
{
__delay_ms(5);
}
Над функцией main() добавим функцию ожидания освобождения шины SPI
//--------------------------------------------
static void SpiReceiveWait()
{
while ( !SSPSTATbits.BF ); // Wait for Buffer Empty
}
//--------------------------------------------
Ниже добавим функцию приёма байта
//--------------------------------------------
char SpiRead()
{
SpiReceiveWait();
return(SSPBUF);
}
//--------------------------------------------
Также добавим ниже функцию обработчика прерываний от шины SPI
//--------------------------------------------
void interrupt isr(void)
{
if(SSPIF)
{
}
}
//--------------------------------------------
В теле условия обработки включения флага прерывания от SPI добавим следующий код
if(SSPIF)
{
bt = SpiRead();
if(bt) PORTB = bt;
SSPBUF = 255-bt;
SSPIF = 0;
}
Мы сначала читаем из шины байт. Затем, если он не равен нулю, передаём его в порт B, зажигая соответствующие светодиоды. Затем мы, вычтя значение данного байта из 255, отправляем полученное значение назад ведущему устройству. И, соответственно, обнуляем флаг, так как это делается именно программно.
Таким образом, если нам приходит ноль, а это именно запрос информации от нас, то мы её уже не отображаем на дисплее, а только передаём то, что у нас в буфере, а в буфере у нас значение, которое мы туда послали в предыдущем цикле обработчика. Вот так и происходит обмен информацией. Получается, что мы с ведущего передаём сначала полезное значение, а потом ноль для того, чтобы, наоборот, получить значение от ведомого.
Попробуем собрать наш код и прошить контроллер ведомого устройства.
У нас должна получиться вот такая картина
Здесь у нас цифра на индикаторе ведущего устройства постоянно убавляется на 1, так как это число приходит с ведомого устройства, а на ведомом светодиоды показывают число которое, приходит с ведущего. Число отображается с помощью светодиодов в двоичном виде, причём слева младший бит. В данный момент получается, что ведомый получил от ведущего число 11001001, что в десятичном виде составляет 201. А с ведомого в ответ ведущий получил число 54, что и отобразилось на индикаторе. В сумме эти два числа дают 255, что и доказывает правильность процесса обмена данными.
Также мы правильность передачи данных можем проверить и в программе логического анализа.
Включим 4 канала и настроим режим SPI в данной программе следующим образом
Запустим захват и получим слеующий результат
Также посмотрим график, там ещё более наглядно видна передача (нажмите на картинку для увеличения изображения)
Таким образом, сегодня нам удалось научить наш модуль MSSP работать в режиме SPI в качестве ведомого устройства, что позволило нам организовать обмен данными между двумя контроллерами PIC.
Всем спасибо за внимание!
Предыдущая часть Программирование МК PIC Следующий урок
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Семисегментный чертырехразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий