PIC. Урок 18. MSSP. SPI. SLAVE. Соединяем два контроллера. Часть 2

 

 

 

В предыдущей части урока мы познакомились с режимом 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 Следующий урок

 

Исходный код MASTER

Исходный код SLAVE

 

 

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

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

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

Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт

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

 

 

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

 

PIC Урок 18. MSSP. SPI. SLAVE. Соединяем два контроллера

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

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

*