赞
踩
C8051F340单片机的增强型串行外设接口(SPI0)提供访问一个全双工同步串行总线的能力。SPI0 可以作为主器件或从器件工作,可以使用 3 线或 4 线方式,并可在同一总线上支持多个主器件和从器件。
本文展示配置为主器件模式。主出从入(MOSI)信号是主器件的输出和从器件的输入,用于从主器件到从器件的串行数据传输。当 SPI0 作为主器件时,该信号是输出;当 SPI0 作为从器件时,该信号是输入。数据传输时最高位在先。当被配置为主器件时,MOSI 由移位寄存器的 MSB 驱动。
#include <C8051F340.h> #define SYSCLK 12000000 #define SPI_CLOCK 250000 #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}; bit Error_Flag = 0; unsigned char Command = 0x00; void PCA0_Init (void); void Oscillator_Init (void); void Port_Init (void); void SPI0_Init (void); void Init_Device (void); void SPI_LED_On (void); void SPI_LED_Off (void); void SPI_Byte_Write (void); void SPI_Byte_Read (void); void SPI_Array_Write (void); void SPI_Array_Read (void); void Delay(void);
void main (void) { unsigned char test_value = 0x55; unsigned char test_array[MAX_BUFFER_SIZE] = {1,2,3,4,5,6,7,8}; unsigned char i; Init_Device (); //设备初始化 EA = 1; //允许中断 LED = 0; SPI_Data = test_value; SPI_Byte_Write (); //SPI写一个值 while (!NSSMD0); //等待传输结束 SPI_Data = 0x00; SPI_Byte_Read (); //SPI读 while (!NSSMD0); //等待传输完成 if (SPI_Data != test_value) { Error_Flag = 1; } for (i = 0; i < MAX_BUFFER_SIZE; i++) { SPI_Data_Array[i] = test_array[i]; //把测试数据给SPI } SPI_Array_Write (); //数据发给从器件 while (!NSSMD0); //等待写完成 for (i = 0; i < MAX_BUFFER_SIZE; i++) { SPI_Data_Array[i] = 0; } SPI_Array_Read (); //从从器件读数据 while (!NSSMD0); // 等待读取完成 for (i = 0; i < MAX_BUFFER_SIZE; i++) { if (SPI_Data_Array[i] != test_array[i]) //检查读取是否正确 { Error_Flag = 1; } } while (1) { if (Error_Flag == 0) { LED = 1; SPI_LED_On (); while (!NSSMD0); Delay (); SPI_LED_Off (); LED = 0; while (!NSSMD0); Delay (); } }; }
void PCA0_Init (void)
{
PCA0MD &= ~0x40; //关闭看门狗
PCA0MD = 0x00;
}
void Oscillator_Init (void)
{
OSCICN = 0x83; // 设置内部12M晶振
}
void PORT_Init (void)
{
P0MDOUT = 0x0D; // 设置SCK, MOSI,NSS为推挽输出
P2MDOUT = 0x04; //设置LED驱动为推挽输出
P2SKIP = 0x04; //跳过LED (P2.2)
XBR0 = 0x02;
XBR1 = 0x40; pull-ups
}
void SPI0_Init()
{
SPI0CFG = 0x40; //配置SPI为主器件
SPI0CN = 0x0D; // 允许SPI
SPI0CKR = (SYSCLK/(2*SPI_CLOCK))-1; //SPI时钟频率
ESPI0 = 1; //允许SPI中断
}
void Init_Device (void)
{
PCA0_Init (); // 关看门狗
Oscillator_Init ();
Port_Init ();
SPI0_Init ();
}
void SPI_ISR (void) interrupt 6 { static unsigned char array_index = 0; static char state = 0; if (WCOL == 1) { WCOL = 0; //清标志 Error_Flag = 1; } else { if (SPI0DAT == ERROR_OCCURRED) { Error_Flag = 1; } if (state == 0) { switch (Command) { case SLAVE_LED_ON: case SLAVE_LED_OFF: NSSMD0 = 1; break; case SPI_WRITE: SPI0DAT = SPI_Data; state = 2; break; case SPI_READ: SPI0DAT = 0xFF; state = 2; break; case SPI_READ_BUFFER: array_index = 0; SPI0DAT = 0xFF; state = 1; break; default: state = 2; } } else if (state == 1) { switch (Command) { case SPI_READ_BUFFER: SPI_Data_Array[array_index] = SPI0DAT; SPI0DAT = 0xFF; array_index++; if (array_index == (MAX_BUFFER_SIZE-1)) { state = 2; } break; default: state = 2; } } else if (state == 2) { switch (Command) { case SPI_READ: SPI_Data = SPI0DAT; break; case SPI_READ_BUFFER: SPI_Data_Array[array_index] = SPI0DAT; break; } NSSMD0 = 1; state = 0; } SPIF = 0; } }
void SPI_LED_On (void)
{
while (!NSSMD0);
NSSMD0 = 0;
Command = SLAVE_LED_ON;
SPI0DAT = Command;
}
void SPI_LED_Off (void)
{
while (!NSSMD0);
NSSMD0 = 0;
Command = SLAVE_LED_OFF;
SPI0DAT = Command;
}
void SPI_Byte_Write (void)
{
while (!NSSMD0);
NSSMD0 = 0;
Command = SPI_WRITE;
SPI0DAT = Command;
}
void SPI_Byte_Read (void)
{
while (!NSSMD0);
NSSMD0 = 0;
Command = SPI_READ;
SPI0DAT = Command;
}
void SPI_Array_Write (void) { unsigned char array_index; while (!NSSMD0); // 等待SPI空闲 ESPI0 = 0; //禁止SPI中断 NSSMD0 = 0; SPI0DAT = SPI_WRITE_BUFFER; // 加载值 while (TXBMT != 1) //等待命令进入XMIT缓存 { } for (array_index = 0; array_index < MAX_BUFFER_SIZE; array_index++) { SPI0DAT = SPI_Data_Array[array_index]; // 加载数据到缓存 while (TXBMT != 1) // 等待数据进入XMIT缓存 { } } SPIF = 0; while (SPIF != 1) //等待最后一字节数据进入从器件 { } SPIF = 0; NSSMD0 = 1; //禁止从器件 ESPI0 = 1; // 打开SPI中断 }
void SPI_Array_Read (void)
{
while (!NSSMD0); // 等待SPI空闲
NSSMD0 = 0;
Command = SPI_READ_BUFFER;
SPI0DAT = Command;
}
void Delay (void)
{
unsigned long count;
for (count = 100000; count > 0; count--);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。