кто то не помню на форуме просил программный SPI для СЛЕЙВА, на циклах ожидания написал, не камильфо, но может сгодится
Спойлер
Код:
/*
* GccApplication12.c ---------- программный SPI. MODE 0 ----- на циклах ожидания ----------
*
* Created: 26.02.2021 0:33:56
* Author : Сергейда
*/
// ПРОГА для прошивки мега168р в режиме SLAVE---------------------------------------------------------------------------------
// отправляем мастеру бегущий огонек
//
//
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
//---------- НАСТРОЙКА НАПРАВЛЕНИЯ ПОРТА (SPI) ----------
#define DDR_SPI DDRB // обзовем порт (DDRB) удобным именем (DDR_SPI)
#define DD_MISO DDB4 // обзовем пин (DDB4) удобным именем (MISO_SS)
//---------- (SPI), НАСТРОЙКА РАБОЧИХ ПИНОВ ----------
#define PORT_SPI PORTB // обзовем порт (PORTB) удобным именем (PORT_SPI)
#define PORT_MISO PORTB4 // обзовем пин (PB4) удобным именем (PB_MISO)
//---------- (SPI), ПИНЫ ДЛЯ ПРОВЕРКИ-----------------------------------------------------------
#define PIN_SPI PINB // PINB обзавем PIN_SPI ( тут буит проверка бита и все таккое)))
#define PIN_MOSI PINB3 // обзовем пин (PIN3) удобным именем (PIN_MOSI)
#define PIN_SS PINB2 // обзовем пин (PINB2) удобным именем (PIN_SS)
#define PIN_SCK PINB5 // обзовем пин (PINB5) удобным именем (PINB_SCK)
//----------
#define PORT_LED PORTD // PORTD обзавем PORT_LED ( тут индикация будет и все такое))))
#define DDR_LED DDRD // DDRD обзавем DDR_LED ( тут настройка порта на выход буит и все таккое)))
//----------
void SPI_SlaveInit(void) // инициализация и настройка модуля SPI МК в режиме (Slave)
{
DDR_SPI |= (1<<DD_MISO); // MISO установим на выход так как у нас МК в режиме SLAVE
// MOSI, SCK и SS на вход , по умолчанию инициализируется нулем
}
//----------
uint8_t running_light(void) // функция передает в вызывающюю функцию через return бегущий огонек
{
uint8_t data = 0; // создаем и задаем значение переменной (data),
static uint8_t a = 0; // создаем и задаем значение статической переменной (a), она у нас будет номером бита в нашем байте данных (data)
if (a>7) a=0; // защита от переполнения, как только (а) станет =8 она обнулится , что бы не вылезти за размер байта
data = (1 << a); // установка еденицы в бит (а) байта (data) с затиранием остальных битов, например было (0b00000001) потом стало (0b00000010)
a++ ; // инкрементируем наш номер бита в байте)))
return (data); // передаем в вызывающюю функцию наш байт
}
//----------
uint8_t SPI_Bitbang_mode0 ( uint8_t data) // программный SPI. MODE 0
{
uint8_t b = 7; // (b) номер бита байта (out_bytes) и байта (data). прием и передача байта начинаем с 7 старшего бита
uint8_t out_bytes = 0; // (out_bytes), через нее будем возвращать принятый байт в вызывающюю функцию
for (uint8_t i = 0; i < 8; i++) // цикл "для", повторяющийся 8 раз
{
while (PIN_SPI & (1 << PIN_SCK)); // ждем пока (PIN_SCK) = 1
// ---------- (PIN_SCK) = 0, НИЗКИЙ ПОЛУПЕРИОД (записываем бит в (MISO) на передачу МАСТЕРУ
if (data & (1 << b)) // проверяем бит (a) переменной (data), если этот бит = 1, то выполняется (выражение в скобках)
{ PORT_SPI |= (1<<PORT_MISO); // устанавливаем пин (PORT_MISO) в 1
}
else // иначе если (a) бит = 0 , то выполняем КОД 2.
{ PORT_SPI &= ~(1 << PORT_MISO); // сбрасываем пин (PORT_MISO) в 0
}
while (~PIN_SPI & (1<<PIN_SCK)); // ждем пока (PIN_SCK) = 0
// ---------- (PIN_SCK) = 1, ВЫСОКИЙ ПОЛУПЕРИОД (считываем бит из (MOSI) принятый от МАСТЕРА
if (PIN_SPI & (1 << PIN_MOSI)) // проверяем бит (PIN_MOSI), если этот бит = 1, (выражение в скобках)
{ out_bytes |= (1<<b); // устанавливаем бит (b) байта (out_bytes) в 1.
}
else // иначе если бит (PB_MOSI) = 0 , то выполняем КОД 2.
{ out_bytes &= ~(1 << b); // сбрасываем пин (b) байта (out_bytes) в 0.
}
b-- ; // декрементируем номер бита (b) байта
}
return (out_bytes); // возвращаем значение полученого байта от слейва в вызывающюю функцию
}
//----------
int main(void)
{
DDR_LED = 0b11111111; // на выход ( на нем наши индикаторные светодиодики)))
SPI_SlaveInit (); // инициализация и настройка модуля SPI МК в режиме (Slave)
SPDR = 0b11110000; // запишем в регистр данных (SPDR) число 0, его считает мастер при первом обмене байтами по SPI
uint8_t received_byte =0; // полученый байт от слейва
uint8_t send_byte = 0; // передаваемый байт модулю (SPI)
while (1) // Основной цикл программы
{
if (~PIN_SPI & (1<<PIN_SS)) // Проверка пина (PIN_SS) на 0, если (PIN_SS)=0, то МАСТЕР выбрал нас для приема и передачи байта
{
send_byte = running_light (); // в переменную (send_byte) на отправку МАСТЕРУ загоняем бегущий огонек из ф-ии (running_light)
received_byte = SPI_Bitbang_mode0 (send_byte); // (SPI) модуль
PORT_LED = received_byte ; // отправим полученый байт в порт индикации
}
}
}