📄 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 + -