⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.cpp

📁 SPI驱动:在LPC213X上实现了SPI总线的收发功能
💻 CPP
字号:
#include <stdio.h>
#include <string.h>
#include "SPI.h"


//----------------------------- internal definitions ----------------------


//缓冲区定义
#ifndef COMM_4_XMIT_SIZE
	#define COMM_4_XMIT_SIZE 	128
#endif
#ifndef COMM_4_RCV_SIZE
	#define COMM_4_RCV_SIZE		128
#endif


//---- 查找这个字串来 同步定义 2987947sf2394 --------
//如果收到NULL则丢弃
//如果收到 ESC+ESC_NULL, 则返回 NULL
//如果收到 ESC+ESC_ESC,  则返回ESC
#define SPI_NULL     0XFF
#define SPI_ESC		 0x1C
#define SPI_ESC_NULL '0'
#define SPI_ESC_ESC  '1'

class CSpiComm
{
	static unsigned char spi_rcv_buf[COMM_4_RCV_SIZE];
	static unsigned char spi_send_buf[COMM_4_XMIT_SIZE];

	static void RstDisp(void);
	static void PutChar_NoESC(uint8 c);
public:
	static class CQueue qRcv;
	static class CQueue qSend;
	
	static unsigned long starting_ssp; 
	static unsigned long need_manual_start;
	static unsigned int  rcv_count;
	static unsigned long in_esc;
	static void Init(void);
	static void Recover(void);
	static void PutChar(unsigned char Din);
	static void PutStr(char *s);
};

//------------------------------ code -------------------------

unsigned long CSpiComm::starting_ssp      = 0;
unsigned long CSpiComm::need_manual_start = 1;
unsigned long CSpiComm::in_esc            = 0;
unsigned int  CSpiComm::rcv_count         = 0;


unsigned char CSpiComm::spi_rcv_buf[COMM_4_RCV_SIZE];
class CQueue CSpiComm::qRcv(spi_rcv_buf,COMM_4_RCV_SIZE);
unsigned char CSpiComm::spi_send_buf[COMM_4_XMIT_SIZE];
class CQueue CSpiComm::qSend(spi_send_buf,COMM_4_XMIT_SIZE);


//中断条件:1。 接收半满 2。 接收超时
void __irq SPI_IRQ(void)
{
	//1、RxFIFO is at least half full	
	//2、if RxFIFO isn't empty,no data revieved,no data read,in 32 bit times;
//	EnableIsr(ISN_TIMER0,false);
	uint8 c=0;

	if (SSPMIS & 0x02)			//接收超时中断
	{
		SSPICR  = 0x02;//Clear revieve timeout interrupt 
	}
	while(SSPSR & 0x04)			//RxFIFO 有数据
	{
		c = SSPDR;
		if(CSpiComm::in_esc)
		{
			if(c == SPI_ESC_NULL)
				CSpiComm::qRcv.Add(SPI_NULL);
			else if(c == SPI_ESC_ESC)
				CSpiComm::qRcv.Add(SPI_ESC);
			CSpiComm::in_esc = 0;
		}else if(c == SPI_ESC)
			CSpiComm::in_esc = 1;
		else if(c != SPI_NULL)
		{
			CSpiComm::qRcv.Add(c);
		}
		if(c != SPI_NULL)
			CSpiComm::rcv_count = 0;
	}

	//发生要放在接收的后面,因为发送时引起接收后才会引发中断。
	//如果放在接收之前,那么如果该中断被FIQ 打断,则导致本次的接收中断被清除而无法再次触发中断
//	EnableIsr(ISN_TIMER0,true);
	
	if(CSpiComm::qSend.IsEmpty())
	{			 	
		if(c != SPI_NULL || CSpiComm::rcv_count<10)
		{
			SSPDR = SPI_NULL;
			CSpiComm::rcv_count++;
		}else
		{
			CSpiComm::rcv_count = 0;
			CSpiComm::need_manual_start = 1;//   send_after_32bit = 1;
		}
	}else
	{
		//=====================================================================================
		//不要使用使用发生的FIFO,否则51单片机会来不及接收的
		//=====================================================================================
			//do 
			//{
				SSPDR = CSpiComm::qSend.Get();
			//	c = SSPSR;
				//printk("%x ",c);
			//}while((c & 0x02) && (c & 0x08) == 0 && !CSpiComm::qSend.IsEmpty()) ;
			//printk("2");
		//do
		//{
		//	if(SSPSR & 0x02) 	//TNF: Transmit FIFO Not Full.
		//		SSPDR = CSpiComm::qSend.Get();
		//	else
		//		break;
		//}while(! CSpiComm::qSend.IsEmpty());
	}

	VICVectAddr = 0x00;			// 中断处理结束,等待下次的中断
}


void CSpiComm::RstDisp(void)
{
	IO0CLR |= 0x01 << 16;
	Sleep(100);	
	IO0SET |= 0x01 << 16;
}
	
void CSpiComm::Init(void)
{	
    SSPCPSR = (Fpclk / 2) / 2200000;	// PCLK分频值  2200000
    
    SSPCR0 = (0x01 << 8) |              // SCR  设置SPI时钟分频
             (0x01 << 7) |              // CPHA 时钟相位,仅SPI模式有效,在第2个时钟捕获数据 
             (0x01 << 6) |             	// CPOL 时钟极性,仅SPI模式有效,帧间保持高电平
             (0x00 << 4) |              // FRF  帧格式 00=SPI,01=SSI,10=Microwire,11=保留
             (0x07 << 0);               // DSS  数据长度,0000-0010=保留,0011=4位,0111=8位,1111=16位

    SSPCR1 = (0x00 << 3) |              // SOD  从机输出,0=允许,1=禁止 MISO
             (0x00 << 2) |              // MS   主从选择,0=主机,1=从机
             (0x01 << 1) |              // SSE  SSP使能,1=允许SSP与其它设备通信
             (0x00 << 0);               // LBM  1==:MOSI=MISO
    
    //中断清除寄存器
    SSPICR  = (0x01 << 1) |				//Clean revieve timeout interrupt 
    		  (0x01 << 0);				//Clean revieve overrun interrupt  
    
    // 中断屏蔽寄存器
    SSPIMSC = (0x00 << 3) |				//1=Enable interrup,TxFIFO is at least half empty
    		  (0x01 << 2) |				//1=Enable interrup,RxFIFO is at least half full
    		  (0x01 << 1) |				//1=Enable interrup,if RxFIFO isn't empty,
    		  							//no data revieved,no data read,in 32 bit times;
    		  (0x00 << 0);              //1=Enable interrup,RxFIFO recieve overrun occur;      

	SetIrq((unsigned long)SPI_IRQ, ISN_SPI1,   ISR_SSP_ORDER);
	
	//	RstDisp();
}


void CSpiComm::PutChar_NoESC(uint8 c)
{
	//发送普通字符
	while(!qSend.Add(c))
	{
		Sleep(3);
		printk("SSPCR0=%x,CR1=%x,SR=%x,CPSR=%X,IMSC=%X,RIS=%X,MIS=%X\n",SSPCR0,SSPCR1,SSPSR,SSPCPSR,SSPIMSC,SSPRIS,SSPMIS);
	}
	//检查是否需要启动发送
	starting_ssp = 1;
	if (need_manual_start)
	{
		need_manual_start = 0;
		//if(SSPSR & 0x02) 
		SSPDR = CSpiComm::qSend.Get();
	}
	starting_ssp = 0;
}

void CSpiComm::PutChar(unsigned char Din)
{
	//第归发送转义字符
	if(Din == SPI_NULL)
	{
		PutChar_NoESC(SPI_ESC);
		PutChar_NoESC(SPI_ESC_NULL);
		return;
	}else if(Din == SPI_ESC)
	{
		PutChar_NoESC(SPI_ESC);
		PutChar_NoESC(SPI_ESC_ESC);
		return ;
	}else
		PutChar_NoESC(Din);
}

//每隔8ms接收一次SPI的数据
//接收数据通过发送0来实现. 而接收方受到0 后丢弃它。
int ReceiveSPIByte(void)
{
	if(CSpiComm::starting_ssp)
		return 0;
	if(CSpiComm::need_manual_start)
	{
		CSpiComm::need_manual_start = 0;
		SSPDR = SPI_NULL;
	}
	return 0;
}

void CSpiComm::PutStr(char *s)
{
	while(*s)
		PutChar(*s++);
}


void CSpiComm::Recover(void)
{
	;
}

/*
void ________test_______________()
*/
	  /*
//在主函数中被调用
void Test_Spi()
{
	static unsigned long i = 0;
	while(!CSpiComm::qRcv.IsEmpty())
	{
		
		CSpiComm::qRcv.Get();
//		printk("%c",CSpiComm::qRcv.Get());		
	}
return;	
	if(! uart0_rcv_queue.IsEmpty_2(3))
	{
		char c = uart0_rcv_queue.Get_2(3);
		switch(c)
		{
		case 'R':
			printk("Reset spi port\r\n");
			CSpiComm::Init();
			break;
		case 'S':
			if(i++ >= 9) 
				i=0;
			CSpiComm::PutChar('0'+i);
			CSpiComm::PutStr("!\"#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|};");
			printk("SENT %d\r\n",i);
			break;
		}
	}
}
	  */
	
/*
void ________interface_______________()
*/
int CSpiSerial::PutChar(uint8 c)
{
	CSpiComm::PutChar(c);
	return 1;
};


class CQueue *CSpiSerial::GetRcvQ()
{
	return &CSpiComm::qRcv; 
}

CSpiSerial::CSpiSerial()
{
	CSpiComm::Init();
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -