1.1 SPI协议概括
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。
1.2 接口定义
(1)SDI – SerialData In,串行数据输入;
(2)SDO – SerialDataOut,串行数据输出;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS – Chip Select,从设备使能信号,由主设备控制
1.3 一些要用到的知识点
SPI的本质是数据的交换,也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据。
时钟极性:
SPI时序图详解—SPI接口在模式0下输出第一位数据的时刻。SPI接口有四种不同的数据传输时序,取决于CPOL和CPHL这两位的组合。图1中表现了这四种时序,时序与CPOL、CPHA的关系也可以从图中看出。CPOL是用来决定SCK时钟信号空闲时的电平,CPOL=0,空闲电平为低电平,CPOL=1时,空闲电平为高电平。CPHA是用来决定采样时刻的,CPHA=0,在每个周期的第一个时钟沿采样,CPHA=1,在每个周期的第二个时钟沿采样。
Zigbee cc2530 中SPI的硬件机制与UART是在一起的,合称USART。由数据手册可以看出。我们可以通过设置寄存器来区分使用UART或者SPI。
Zigbee cc2530 SPI的一些信息
在SPI模式中, USART通过3线接口或者4线接口与外部系统通信。 接口包含引脚 MOSI、 MISO、 SCK和SS_N。参见12.1节中有关如何将USART引脚指派到I/O引脚的描述。
SPI模式包含下列特征:
3线(主要)或者4线SPI接口
主和从模式
可配置的SCK极性和相位
可配置的LSB或MSB传送
当UxCSR.MODE设置为0时,选中SPI模式。
在SPI模式中, USART可以通过写UxCSR.SLAVE位来配置SPI为主模式或者从模式
编程所用到的寄存器(因为我配置的是USART1 ,所以寄存器都是USART1,USART0的一样)
U1BUF在手册制作的时候有点问题,程序了的是U1DBUF这个寄存器。
编写代码:
/***************************
时间:2018.8.6
作者:liangjia
函数名:void Spi_Master_Init()
功能:初始化USART的spi模式,开启USART1,为主机模式
****************************/
void Spi_Master_Init()
{
//设置备用引脚2
PERCFG =0x02 ;//0000010
P2DIR =0x60;
//设置P1_5、P1_6、P1_7为外设IO,P1_4为片选引脚
P1SEL|=0xE0; //1110 0000
P1SEL&=~0x10;//1110 1111
P1DIR|=0x10;
//开启初始化相应寄存器
U1CSR &= ~0xA0; //0101 1111 SPI MAster Mode
U1GCR |= 11; //0000 11 00 设置 BAUD_E为10
U1BAUD |= 216; //设置BAUD_M为59 波特率设为 38400
U1GCR|=0xC0;// CPOL = CPHA = 1
U1GCR |= 0x20;//高位先传送
}
编写代码:
/*******************************************
时间:2018.8.6
作者:liangjia
函数名:Spi_Slave_Init()
功能:初始化USART的spi模式,开启USART1,设置为从机模式
*********************************************/
void Spi_Slave_Init()
{
PERCFG =0x02 ;//0000010
P2DIR =0x60;
//设置P1_5、P1_6、P1_7为外设IO,P1_4为片选引脚
P1SEL|=0xF0; //1110 0000
// P1SEL&=~0x10;//1110 1111
//开启初始化相应寄存器
U1CSR &= ~0x80; //0111 1111 SPI Slave Mode
U1CSR |= 0x20; //slave mode
U1GCR |= 11; //0000 11 00 设置 BAUD_E为10
U1BAUD |= 216; //设置BAUD_M为59 波特率设为 115200
U1GCR|=0xC0;// CPOL = CPHA = 1
U1GCR |= 0x20;//高位先传送
}
/*******************************************
时间:2018.8.6
作者:liangjia
函数名:SPI_Slave_SendData(char * buf,int len)
参数:buf 指向数据缓冲区
len 缓冲区长度
功能:从机利用SPI接口进行信息发送
*********************************************/
void SPI_Slave_SendData(char * buf,int len)
{
for(int i=0;i
}
/*******************************************
时间:2018.8.6
作者:liangjia
函数名:void SPI_Master_SendData(char * buf,int len)
参数:buf 指向数据缓冲区
len 缓冲区长度
功能:主机机利用SPI接口进行信息发送
*********************************************/
void SPI_Master_SendData(char * buf,int len)
{
SSN1=LOW;
for(int i=0;i< len;i++)
{
U1DBUF=*buf;
buf++;
while(U1TX_BYTE==0);
DelayMS(10);
U1CSR &= 0xFD;
}
SSN1=HIGH;
}
/*******************************************
时间:2018.8.6
作者:liangjia
函数名:void SPI_Slave_RevData(int len)
参数:len 需要接受的数据长度
功能:从机利用SPI接口进行信息接收
*********************************************/
void SPI_Slave_RevData(int len)
{
U1DBUF =0x00;
while(U1RX_BYTE==0);//等待发送完成
U1CSR &= 0xFD;//清空发送状态
revbuf[buf]=U1DBUF;
buf++;
//达到最大值,自动将数组清零
if(buf == len)
{
UartTX_Send_String(revbuf, 11);
buf=0;
for(int j=0;j < len+1;j++)
revbuf[j] = 0;
}
}
中断接收
/*******************************************
时间:2018.8.6
作者:liangjia
函数名:void Spi_Interrupt_Open()
功能:打开USART1的中断用来实现接收功能
*********************************************/
void Spi_Interrupt_Open()
{
// URX1IF = 0;
URX1IE = 1;
EA=1;
}
中断处理参考
#pragma vector = URX1_VECTOR
__interrupt void UART1_ISR(void)
{
URX1IE = 0;
URX1IF=0;
revbuf[buf]=U1DBUF;
buf++;
// UartTX_Send_String(revbuf, sizeof(revbuf));
//达到最大值,自动将数组清零
if(buf == sizeof(“I am Master”))
{
UartTX_Send_String(revbuf, sizeof(revbuf));
buf=0;
for(int j=0;j< sizeof(“I am Master”);j++)
revbuf[j] = 0;
// SPI_Slave_SendData(“I am Slave#”,sizeof(“I am Slave#”));
}
URX1IE = 1;
} */