Попытаемся теперь настроить наш модуль MSSP в режиме SPI, но уже в качестве ведомого устройства. Возможно, что это вряд ли понадобится, но для общего развития считаю это необходимым, так как такая возможность у контроллера есть и надо её использовать. Благодаря этому мы организуем обмен данными между двумя контроллерами. Один из контроллеров будет работать в режиме ведущего устройства на шине SPI, а другой — ведомого.
В качестве ведомого устройства (SLAVE) у нас будет использоваться наш постоянный контроллер PIC16F877A, расположенный на плате от Waveshare, а в качестве ведущего (MASTER) — контроллер PIC17F876A, с которым мы работали раньше, находящийся на макетной плате вместе с четырехразрядным индикатором, с которым мы последний раз работали, когда изучали таймеры. Я данную плату не разбирал, и, оказывается, что не зря. Вот она и пригодилась.
Давайте с неё и начнём.
Для того, чтобы ножки, работающие с шиной SPI были свободными, пришлось ножку RC3, которая у нас отвечала за управление старшим разрядом индикатора, отключить от соответствующей базы транзистора, так как она нам потребуется для ножки SCK, которую переопределить невозможно, и подключить базу данного транзистора к ножке RC7, которая у нас на данный момент свободна (соединение обозначено красной линией)
Теперь можно подключить провода для соединения по шине SPI к соответствующим ножкам контроллера. Ножки мы используем эти
Так как нам ещё необходимо соединить и общие провода контроллеров, то возьмём шлейф из 5 проводов и подключим его к соответствующим контактам нашей макетной платы
Подключим теперь противоположные контакты наших проводов к другому контроллеру, тем самым мы обеспечим соединение наших контроллеров по шине SPI (нажмите на картинку для увеличения изображения)
Не забываем, что ножка SDO ведущего устройства соединяется с ножкой SDI ведомого и наоборот, ножка SDI ведущего с ножкой SDO ведомого, так как в случае ведомого устройства входом становится MOSI.
Я не стал снимать перемычки для светодиодов на плате с контроллером 877A, так как на данной плате мы будем мониторить данные именно с помощью восьми светодиодов, не подключая никаких светодиодных индикаторов. И индикатор от WavеShare мы уже подключить не сможем через стандартный разъём, так как ножку RA5, предназначенную для CS мы уже не переопределим из-за её аппаратной работы в режиме SLAVE.
Также подключим логический анализатор к шине SPI платы от Waveshare и соединим его с ПК с помощью кабеля USB
Теперь ещё подключим к каждой плате программаторы. К ведущей — PICkit 2, а к ведомой — PICkit 3
Начнём с ведущего устройства. Проект мы возьмём из урока 7 по динамической индикации с именем LED_DYN и присвоим ему имя SPI_MASTER.
Откроем наш проект в MPLAB X и сделаем его главным.
Откроем файл led.c и исправим ножку порта сначала в младшем разряде, где мы старший разряд гасим
if(n_count==0)
{
PORTCbits.RC7 = 0;
И теперь также исправим там, где мы его включаем
else if(n_count==3)
{
PORTCbits.RC2 = 0;
segchar(R4);
PORTCbits.RC7 = 1;
Соберём код, прошьём контроллер в программе PICkit 2, чтобы убедиться, что индикатор у нас работает
Всё нормально, значит можно продолжать дальше.
Откроем файл main.c и напишем макрос для ножки выбора устройства
#include "main.h"
//--------------------------------------------------------------
#define cs RA5
//--------------------------------------------------------------
Ниже функции interrupt isr добавим функцию инициализации шины SPI аналогично, как мы делали на 877 контроллере
//--------------------------------------------
void SPI_init(void)
{
TRISC|=0x10; //MISO IN
TRISC&=~0X28; //MOSI,SCK OUT
TRISA&=~0X20; //SS OUT
PORTA&=~0X20; //SS 0
// SSPM3:SSPM0 = 0000 (SPI Master mode, clock = 1 MHz)
// SKE=1, SKP=0 (SPI_MODE0)
// SMP=1 (Input data sampled at end of data output time)
// SSPEN= 1 (SPI Enabled)
SSPCON=0x20;
SSPSTAT=0xC0;
}
//--------------------------------------------
Используем режим 0.
Ниже добавим функцию передачи байта в шину
//--------------------------------------------
void SPI_SendByte(char data)
{
SSPBUF=data;
while(!SSPIF) ;
SSPIF=0;
}
//--------------------------------------------
Далее добавим функцию приёма байта из шины
//--------------------------------------------
static unsigned char SPI_Receive_byte(unsigned char data)
{
unsigned char temp;
SSPBUF=data;
while(!SSPIF);
SSPIF=0;
temp=SSPBUF;
return temp;
}
//--------------------------------------------
Функция также аналогична той, которую мы использовали на прошлом уроке.
В функции main() добавим переменную
unsigned int i;
unsigned char bt;
Ввызовем функцию инициализации шины
TMR0=0;
SPI_init();
Из бесконечного цикла удалим весь код и вставим следующий
while(1)
{
for(i=1;i<256;i++)
{
cs=0;
SPI_SendByte(i);
__delay_us(100);
bt = SPI_Receive_byte(0);
cs=1;
ledprint(bt);
__delay_ms(200);
}
}
Тут, вообщем-то, тоже всё просто. Мы передаём ведомому устройству байт, ждём около 100 микросекунд, пока ведомый его считает и затем мы запросим у ведомого в ответ другой байт, который затем отобразим на дисплее. Соответственно, до всей нашей операции мы опускаем шину выбора, а по окончанию — поднимаем.
Соберём код и прошьём контроллер. Пока интересного мы ничего не увидим, так как наш SLAVE ещё не умеет откликаться.
В следующей части урока мы создадим проект для ведомого устройства, настроим его, напишем ряд функций и проверим работу нашего кода на практике.
Предыдущий урок Программирование МК PIC Следующая часть
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Семисегментный чертырехразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий