📄 spi.c
字号:
#include <avr/io.h>
#include <avr/eeprom.h>
#include "spi.h"
#include "tools.h"
#include "extern_vars.h"
static unsigned char use_sw_spi = 0;
#define MOSI_SET PORTB|=BIT3_POS
#define MOSI_CLEAR PORTB&=BIT3_NEG
#define MISO_IN PINB&BIT4_POS
void spi_enable(void)
{
unsigned char i;
R_RES_ON;
wait_ms(2);
PORTB &= BIT3_NEG & BIT5_NEG; //MOSI and SCK low
DDRB |= BIT3_POS | BIT5_POS; //MOSI and SCK als Ausgang
if (eeprom_read_byte(&eeprom_sck_period) > 64)
{
use_sw_spi = 1; //使用模拟SPI
SPCR=0x00;
}
else
{
use_sw_spi = 0; //使用硬件SPI
SPCR = 0x51; //SPI Master /16
spi_set_speed(eeprom_read_byte(&eeprom_sck_period));
}
R_RES_OFF;
for (i=0;i<200;i++) asm("nop");
R_RES_ON;
wait_ms(2);
}
void spi_disable(void)
{
SPCR=0x00; //SPI aus
DDRB &= BIT3_NEG & BIT5_NEG; //MOSI und SCK als Eingang (hochohmig)
R_RES_OFF;
}
void spi_reset(void)
{
R_RES_OFF;
wait_ms(2);
R_RES_ON;
}
/**
Stellt die Geschwindigkeit des SPI-Busses ein (bei f=8MHz)
0: /2 4MHz --SPI2X
1 /4 2MHz
2: /8 1MHz --SPI2X
3 /16 500kHz
4: /32 250kHz --SPI2X
5 /64 125kHz
6: /128 62,5kHz
weitere Geschwindigkeiten geplant
-> dann per Software-SPI
*/
void spi_set_speed(unsigned char s)
{
if ((s==0)||(s==2)||(s==4)) SPSR|=1;
else SPSR&=0xFE;
switch (s)
{
case 0:
case 1:
SPCR&=0xFC;
break;
case 2:
case 3:
SPCR&=0xFC;
SPCR|=0x01;
break;
case 4:
case 5:
SPCR&=0xFC;
SPCR|=0x02;
break;
case 6:
SPCR|=0x03;
break;
default: //Wenn Wert ung黮tig ganz langsam
SPCR|=0x03;
break;
}
}
void spi_clock_pulse(void) //模拟SPI时钟
{
if (!use_sw_spi)
{
SPCR&=BIT6_NEG; //SPI 使能关闭
}
PORTB|=BIT5_POS; //SPI SCK impuls
wait_ms(2);
PORTB&=BIT5_NEG;
if (!use_sw_spi)
{
SPCR|=BIT6_POS; //SPI 使能
}
}
/**
Does a 8 bit transfer over the SPI-Interface
and gives back the byte received
@param d the byte to be transmitted
@return the byte received
*/
unsigned char spi_transfer_8(unsigned char d)
{
if (!use_sw_spi)
{
SPDR=d;
while (!(SPSR&0x80));
return SPDR;
}
else
{
unsigned char result=0,i;
volatile unsigned int j;
for (i = 0; i < 8; i++)
{
if (d&0x80)
{
MOSI_SET;
}
else
{
MOSI_CLEAR;
}
d<<=1;
result<<=1;
for (j = 0; j < 18; j++) asm volatile("nop");
PORTB|=BIT5_POS; //sck
if (MISO_IN)
{
result|=1;
}
for (j = 0; j < 18; j++) asm volatile("nop");
PORTB&=BIT5_NEG;
}
MOSI_CLEAR;
return result;
}
}
/**
Does a 16 bit transfer over the SPI-Interface
and gives back the last byte received
@param d the int to be transmitted
@return the last byte received
*/
unsigned char spi_transfer_16(unsigned int d)
{
spi_transfer_8((d>>8)&0xFF);
return spi_transfer_8(d&0xFF);
}
/**
Does a 32 bit transfer over the SPI-Interface
and gives back the last byte received
@param d the long to be transmitted
@return the last byte received
*/
unsigned char spi_transfer_32(unsigned long d)
{
spi_transfer_8((d>>24)&0xFF);
spi_transfer_8((d>>16)&0xFF);
spi_transfer_8((d>>8)&0xFF);
return spi_transfer_8(d&0xFF);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -