PIC Урок 22. MSSP. I2C. Slave. Соединяем два микроконтроллера. Часть 2



В предыдущей части занятия мы познакомились с ведомым режимом I2C в модуле MSSP, подключили нашу схему и создали проекты.

Отключим от проекта файлы led.h и led.c, затем их удалим из него физически.

Перейдём в файл main.c и уберём также подключение библиотеки индикатора

#include "led.h"

Также удалим вот эти макросы

#define DEV_ADDR 0xAE
#define address 0x0A

Удалим глобальные массивы

unsigned int TIM1_Count=0;
const unsigned char at24c_data_write[]={0x14,0x13,0x12,0x11,0x10,
0x0F,0x0E,0x0D,0x0C,0x0B,
0x0A,0x09,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x01};
unsigned char at24c_date[20];

Также удалим все функции вместе с телами, кроме функции main(), в которой также сначала удалим переменную

int i;

Удалим инициализацию порта A и регистра OPTION_REG

TRISA = 0x00;
PORTA = 0x00;
OPTION_REG=0b00000010; //Prescaler

Значение регистра INTCON изменим на 0, нам не нужно там никаких включенных битов

 

Удалим инициализацию таймера

TMR0=0;

Включим цифровой режим ножек

 

После инициализации регистра TRISC удалим весь код до бесконечного цикла.

Затем добавим инициализацию шины

 

Немного расскажу о настройках, так как они отличаются от настроек ведущего режима.

Мы включили соответствующие биты регистра SSPCON1 для работы в режиме SPI SLAVE в режиме 7-битной адресации. Также мы отключили CKE для отключения поддержки спецификации SMBUS. Ещё мы включили бит SKP для освобождения шины SCL (таким образом она становится никуда не притянутой) и включили соответствующий скоростной режим работы шины за счёт регистра SMP. Также затем мы в регистр SSPADD занесли значение адреса, отключили бит SSPIF, иначе не начнут работать прерывания, также включили прерывания с помощью бита SSPIE, ну и соответственно с помощью битов GIE и REIE включили глобальные прерывания. Обнулили регистр SSPCON2, чтобы там не были заранее включены никакие биты, а также включили бит SSPEN, который нам и включил задействование нашего модуля MSSP.

Ну и, раз уж мы работаем с прерываниями, то добавим для этого над функцией main() обработчик, в котором мы и будем дожидаться данных от ведущего устройства

 

И сразу в теле условия мы сбросим соответствующий флаг, чтобы нам не пропустить следующее прерывание

 

Добавим две глобальные переменные

 

 

Вернёмся в наш обработчик прерывания от шины. У нас будет несколько вариантов появления данных от ведущего устройства. И во всех этих случаях у нас сработают различные биты регистров, поэтому добавим три условия пока с пустыми телами

 

В комментариях написано — какие это именно варианты данных.

Первое условие — это когда сработало прерывание с режимом чтения, то есть мы уже всю информацию прочитали из шины. Второй случай — это какое-то из прерываний, не связанное ни с чтением, ни с записью, возможно это пришел какой-то управляющий бит (бит подтверждения либо стартовый или стоповый бит). Третий случай или третье условие — это условие, возникшее тогда, когда к нам из шины пришел байт.

В первом условии мы отправим в ответ ведущему устройству байт, значение которого — значение пришедшего байта, отнятое из числа 255. Аналогично мы делали и с шиной SPI

 

Также мы включили бит CKP для того, чтобы отпустить шину SCL, чтобы ведущий понял, что ведомый контроллер свободен для общения. По окончанию мы выходим из обработчика

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

 

Третий случай у нас в свою очередь разветвится ещё на два варианта, говорящих нам о том, какой именно по качественной характеристике к нам от ведущего пришел байт — байт данных или ещё какой-то (например байт адреса)

 

В случае, если у нас пришли не данные, мы просто очищаем буфер от данных, а в случае если пришли данные, мы их для дальнейшего использования сохраняем в глобальную переменную, а затем присваиваем регистру порта B, чтобы тот, в свою очередь, нам показал двоичное число пришедшего байта с помощью светящихся и несветящихся светодиодов. Затем мы независимо от типа байта освобождаем (отпускаем) шину SCL и выходим из обработчика.

 

 

Выйдя из данного условия, мы также ещё раз очистим буфер, так как вдруг возникнут ещё какие-то варианты, которых мы, возможно, не предусмотрели

 

Ну вот, в принципе, и всё. Если мы всё сделали правильно, то у нас пойдёт обмен данным. Соберём проект, прошьём наш контроллер, чтобы в этом убедиться воочию

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

Посмотрим ещё напоследок, как наши данные передаются, в программе логического анализа.

Для этого мы включим вот эти две ножки на приём данных

Включим режим I2C и оставим всё по умолчанию

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

Вот так передаются данные с ведущего на ведомый

Здесь данные передаются с подтверждением.

А вот так данные идут от ведомого к ведущему

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

Также мы можем посмотреть протокол передаваемых байтов

 

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

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

 

 

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

 

 

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

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

 

 

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

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

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

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

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

 

 

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

 

PIC I2C. Slave. Соединяем два микроконтроллера

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

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

*