програмный SPI

Обсуждаем контроллеры компании Atmel.
Ответить
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Нет, вы правы, цикл будет.
Я думал сначала - зачем сдвигать, когда надо просто обнулить регистр и выставить в 1 в нем определенный бит. Но у SBI тоже 2ой аргумент константа только может быть. Перепроверил, думал компилятор как-то выкрутится, но на выхлопе gcc есть цикл сдвига и правда. Извиняюсь за введение в заблуждение.
Реклама
Вымогатель припоя
Сообщения: 615
Зарегистрирован: Вс дек 28, 2014 21:54:05

Сообщение dgrett »

SBR
Я всё-всё узнAю и стану профессором.
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 113
Зарегистрирован: Пт апр 04, 2014 09:34:08
Откуда: Санкт-Петербург

Сообщение sergo80zxc »

кто то не помню на форуме просил программный 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 ;                      // отправим полученый байт в порт индикации				
		}	
	}
}
глаза боятся, а руки что то не делают))
Ответить

Вернуться в «AVR»