一、前言
C8051F340单片机的增强型串行外设接口(SPI0)提供访问一个全双工同步串行总线的能力。SPI0 可以作为主器件或从器件工作,可以使用 3 线或 4 线方式,并可在同一总线上支持多个主器件和从器件。
本文展示配置为从器件模式。主入从出(MISO)信号是从器件的输出和主器件的输入,用于从从器件到主器件的串行数据传输。当 SPI0 作为主器件时,该信号是输入;当 SPI0 作为从器件时,该信号是输出。数据传输时最高位在先。当 SPI 被禁止或工作在 4 线从方式而未被选中时, MISO 引脚被置于高阻态。当作为从器件工作在 3 线方式时,MISO 由移位寄存器的 MSB 驱动。
二、程序展示
1、头文件部分
#include <C8051F340.h>
#define SYSCLK 12000000
#define MAX_BUFFER_SIZE 8
#define SLAVE_LED_ON 0x01
#define SLAVE_LED_OFF 0x02
#define SPI_WRITE 0x04
#define SPI_READ 0x08
#define SPI_WRITE_BUFFER 0x10
#define SPI_READ_BUFFER 0x20
#define ERROR_OCCURRED 0x40
sbit LED = P2^2;
unsigned char SPI_Data = 0xA5;
unsigned char SPI_Data_Array[MAX_BUFFER_SIZE] = {0};
void PCA0_Init (void);
void Oscillator_Init (void);
void Port_Init (void);
void SPI0_Init (void);
void Init_Device (void);
2、主程序
void main (void)
{
Init_Device ();
EA = 1;
LED = 0;
while (1);
}
3、PCA0初始化程序
void PCA0_Init (void)
{
PCA0MD &= ~0x40; //关闭看门狗
PCA0MD = 0x00;
}
4、振荡器初始化程序
void Oscillator_Init (void)
{
OSCICN = 0x83; // 使用内部12M晶振
}
5、端口初始化程序
void PORT_Init (void)
{
P0MDOUT = 0x02; // 设置MISO推挽输出
P2MDOUT = 0x04; // 设置P2.2推挽输出
P2SKIP = 0x04; //跳过P2.2
XBR0 = 0x02; //允许配置SPI
XBR1 = 0x40;
}
6、SPI0初始化程序
void SPI0_Init()
{
SPI0CFG = 0x00; // 配置为从器件模式
SPI0CN = 0x05; //允许SPI为4线从模式
ESPI0 = 1; //允许SPI中断
}
7、设备初始化程序
void Init_Device (void)
{
PCA0_Init ();
Oscillator_Init ();
Port_Init ();
SPI0_Init ();
}
8、SPI中断程序
void SPI_ISR (void) interrupt 6
{
static unsigned char command;
static unsigned char array_index = 0;
static unsigned char state = 0;
unsigned char dummy_byte;
if (WCOL == 1)
{
// Write collision occurred
SPI0DAT = ERROR_OCCURRED;
WCOL = 0;
}
else if (RXOVRN == 1)
{
SPI0DAT = ERROR_OCCURRED;
RXOVRN = 0;
}
else
{
if (state == 0)
{
command = SPI0DAT; // 读命令
array_index = 0;
switch (command)
{
case SLAVE_LED_ON:
LED = 1;
state = 0; // 传输结束
break;
case SLAVE_LED_OFF:
LED = 0;
state = 0; //传输结束
break;
case SPI_WRITE:
state = 1;
break;
case SPI_READ:
SPI0DAT = SPI_Data;
state = 0; // 结束传输
break;
case SPI_WRITE_BUFFER:
state = 1;
break;
case SPI_READ_BUFFER:
SPI0DAT = SPI_Data_Array[array_index];
array_index++;
state = 1;
break;
default:
state = 0;
}
}
else if (state == 1)
{
switch (command)
{
case SPI_WRITE:
SPI_Data = SPI0DAT;
state = 0; // 传输结束
break;
case SPI_WRITE_BUFFER:
SPI_Data_Array[array_index] = SPI0DAT; // 接收下一字节
array_index++;
if (array_index == MAX_BUFFER_SIZE) //是否最后一字节
{
state = 0;
}
else
{
state = 1;
}
break;
case SPI_READ_BUFFER:
SPI0DAT = SPI_Data_Array[array_index];
dummy_byte = SPI0DAT;
array_index++;
if (array_index == MAX_BUFFER_SIZE)
{
state = 0;
}
else
{
state = 1;
}
break;
default:
state = 0;
}
}
SPIF = 0;
}
}