?? spi_receive.c
字號:
// ========SPI_CAN通信程序=======
#include <usart.h>
#include <spi.h>
#include <p18f8680.h>
//#include <can2510.h>
#include <mcp2510.h>
//void InterruptHandlerHigh(void);
// =========常數和變量定義=========
#define READ 0x03 // 讀MCP2510指令代碼
#define WRITE 0x02 // 寫MCP2510指令代碼
#define RESET 0xC0 // 復位MCP2510指令代碼
#define RTS 0x80 // MCP2510請求發送指令代碼 nnn=000該指令無效
#define STA2510 0xA0 // 讀MCP2510狀態指令代碼
#define BITMOD 0x05 // MCP2510位修改指令代碼
int a[12]; // SPI發送或接收數據寄存器
int b[8]; // 發送或接收的數據
int c[8]; // 發送或接收的數據
int i; // 臨時變量
int count; // 發送接收計數器
int count1=0; // for test
int RecID_H=0;
int RecID_L=0;
int DLC=8;
int data;
//---------------------------------------------------------------
void SPIINT(void);
void RS232_initial(void);
void RS232_send(int RS232_date);
void SPIEXCHANGE(int count); //SPI傳送
void WAIT_SPI(void);
void RESET2510(void);
int RD2510(int adress,int n);
void WR2510(int adress,int n);
void RTS2510(int RTSn);
//int GETS2510();
void BM2510(int adress,int mask,int data);
void SETconfigure(void);
void SETNORMAL(void);
void TXCOMPLETE(int adress);
void TXMSG(int DLC);
int RXMSG(void);
void INIT2510(void);
void INIT8680(void);
void INITSPI(void);
int SPIIN(void);
/*中斷入口
#pragma code InterruptVectorHigh=0x08
void InterruptVectorHigh(void)
{
_asm
goto InterruptHandlerHigh
_endasm
}
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh()
{
// di();
// if(TMR1IF) TMR1INT(); // 定時器TMR1中斷
// else if(CCP1IF) CCP1INT(); // 電壓過零捕捉中斷1
// else if(CCP2IF) CCP2INT(); // 電壓過零捕捉中斷2
// else if(SSPIF) SPIINT(); // SPI接口中斷
// ei();
SPIINT();
}
// SPI中斷服務子程序
void SPIINT(void)
{
PIR1bits.SSPIF=0;
a[i++]=SSPBUF; // 數據暫存a[]中
count-=1;
if(count>0) SSPBUF=a[i];// 未發送完,繼續
else PORTE=0x04; // 否則,片選信號置高電平
return;
}*/
//初始化PIC16F8680芯片
void INIT8680(void)
{
// PORTA=0;
// PORTB=0;
// PORTC=0;
// PORTD=0;
// PORTE=0;
// TRISA=0xff;
// TRISB=0xfd;
TRISC=0x97; // SCK, SDO:輸出,SDI:輸入
//TRISD=0;
// TRISE=0x03;
TRISB&=0XEF; // 片選CS信號輸出
TRISB|=0X02;
// TRISBbits.RB4=0;
// TRISBbits.RB1=1;
// PORTA=0xff;
// PORTB=0x03; // RST=1
TRISG=0X04;
PORTG=0x20; // RST=1
// PORTC=0;
// PORTD=0xff;
// PORTE=0x04; //cs禁止
PORTBbits.RB4=1;
return;
}
// 初始化SPI接口
void INITSPI(void)
{
SSPCON1=0x11; //在通信的空閑狀態下時鐘處于高電平;SPI主模式,時鐘=fosc/16
SSPCON1bits.SSPEN=1; // SSP使能
SSPSTAT=0; //定義發送、采樣時間點。
return;
}
//啟動SPI傳送
void SPIEXCHANGE( int count)
// int count;
{
if(count>0) { // 有數據可送?
// i=0;
PORTBbits.RB4=0; // 片選位置低電平
for(i=0;i<count;i++)
{
SSPBUF=a[i]; // 送數
RS232_send(a[i]);
do
{;}
while(PIR1bits.SSPIF==0); //等待發送完畢
//RS232_send(SSPBUF);
a[i]=SSPBUF;
PIR1bits.SSPIF=0;
}
PORTBbits.RB4=1; // 片選位置高電平
}
else
; // 否則,空操作,并返回
return;
}
// 等待SPI傳送完成
void WAIT_SPI(void)
{
do{
count-=1;
}while(count>0); // 當count!=0時,等待 to add "CLRWDT"
return;
}
/*-------------------------------------------------------------------
void RESET2510(void)
{
a[0]=RESET; //RESET 0xC0
count=1;
SPIEXCHANGE(count); // 送復位指令
WAIT_SPI();
return;
}*/
//-------------------------------------------------------------------------------------------
void INIT2510(void)
{
RESET2510(); // 使芯片復位
// SETconfigure();
b[0]=0x02;
b[1]=0x90;
b[2]=0x07;
// b[0]=0x07;
// b[1]=0xF8;
// b[2]=0xC7;
// WR2510(CNF3,3); //???????????????????????? // 波特率為 125 kbps Tq=16/fosc
WR2510(0X28,3);
b[0]=0x00;
b[1]=0x00;
//WR2510(RXM0SIDH,2);
WR2510(0X20,2);
b[0]=0x00;
b[1]=0x00;
// WR2510(RXF0SIDH,2); // RX0接收,屏蔽位為0,過濾器為0
WR2510(0X00,2);
b[0]=0x00;
// WR2510(CANINTE,1); //???????????????????????// CAN中斷不使能
WR2510(0X2B,1);
SETNORMAL(); // 設置為正常操作模式
return;
}
// 對MCP2510芯片進行復位
void RESET2510(void)
{
a[0]=RESET; //RESET 0xC0
count=1;
SPIEXCHANGE(count); // 送復位指令
WAIT_SPI();
return;
}
// 設置MCP2510芯片為配置操作模式
void SETconfigure(void)
{
int h=1;
// BM2510(CANCTRL,0xe0,0x00);
BM2510(0X0F,0xe0,0x80); //?????????????????????????// 設置為正常操作模式
do {
RD2510(0X0e,1);
//RD2510(CANSTAT,1);
// RD2510(0X0E,1);
// RS232_send(b[0]);
h=b[0]&0xE0;
// h=a[2]&0xE0;
}while(h!=0x80); // 確認已進入正常操作模式
return;
}
// 向從地址"adress"開始的寄存器寫入數據,共n個,數據存放數組b[n]中
void WR2510( int adress, int n)
//int adress;
// int n;
{
int j;
a[0]=WRITE; //WRITE=0x02
a[1]=adress;
for(j=0;j<n;j++) a[j+2]=b[j];
count=n+2; // 指令、地址和要寫入的數據量n
SPIEXCHANGE(count);
WAIT_SPI();
return;
}
// 設置MCP2510芯片為正常操作模式
void SETNORMAL(void)
{
int k=1;
// BM2510(CANCTRL,0xe0,0x00);
BM2510(0X0F,0xe0,0x00); //?????????????????????????// 設置為正常操作模式
do {
RD2510(0X0e,1);
//RD2510(CANSTAT,1);
// RD2510(0X0E,1);
// RS232_send(b[0]);
k=b[0]&0xE0;
// k=a[2]&0xE0;
}while(k!=0); // 確認已進入正常操作模式
return;
}
// 對MCP2510芯片進行位修改子程序
void BM2510( int adress, int mask, int data)
//int adress;
//int mask;
//int data;
{
a[0]=BITMOD; // 位修改指令
a[1]=adress; // 位修改寄存器地址
a[2]=mask; // 位修改屏蔽位
a[3]=data; // 位修改數據
count=4;
SPIEXCHANGE(count);
WAIT_SPI();
return;
}
// 讀取從地址"adress"開始的寄存器中的數據,共n個,存放在數組b[n]中
int RD2510( int adress, int n)
//int adress;
//int n;
{
int j;
a[0]=READ;
a[1]=adress;
for(j=0;j<n;j++) a[j+2]=3;
count=n+2; // 指令、地址和要得到的數據量n
SPIEXCHANGE(count);
WAIT_SPI();
for(j=0;j<n;j++)
{
b[j]=a[j+2];// 數據存到數組b[]中
RS232_send(b[j]);
}
return 1;
}
/*int SPIIN(void)
{
do{
;
}while(PIR1bits.SSPIF==0); //查詢數據接收完畢否?
PIR1bits.SSPIF=0;
data=SSPBUF;
return(data);
}*/
//------------------------------------------------------------------------------------------
void main(void)
{
// int l,detect=0;
PIE1bits.SSPIE=1;
// TMR1IE=1;
// CCP1IE=1;
// CCP2IE=1;
RS232_initial();
RCONbits.IPEN=0;
INTCONbits.GIE=1;
INTCONbits.PEIE=1;
// ei(); // 開中斷
INIT8680(); // 初始化PIC16F8680芯片
INITSPI(); // 初始化SPI接口
INIT2510(); // 初始化MCP2510芯片
// flag1=0;
// flag2=0;
// CCP1CON=0x05;
// CCP2CON=0x04;
// while(1)
// {
RXMSG();
// TXMSG(8);
// }
}
// 發送數據子程序
void TXMSG(int DLC)
{
for(i=0;i<DLC;i++) b[i]=c[i];
// WR2510(TXB0D0,DLC);
WR2510(0X36,DLC);
b[0]=DLC;
WR2510(0X35,1);
// WR2510(TXB0DLC,1);
b[0]=0x03;
b[1]=RecID_H;
b[2]=RecID_L;
WR2510(0X30,3); //??????????????????????????
// WR2510(TXB0CTRL,3);
RTS2510(0x01); // 請求發送
// TXCOMPLETE(TXB0CTRL); //???????????????????? //等待發送完畢
TXCOMPLETE(0X30);
return;
}
// MCP2510芯片請求發送程序
void RTS2510(int RTSn)
//int RTSn;
{
//a[0]=RTS;
a[0]=RTS^RTSn;
count=1;
SPIEXCHANGE(count); // 發送MCP2510芯片,請求發送指令
WAIT_SPI();
return;
}
// MCP2510芯片發送完成與否判斷,郵箱號為adress
void TXCOMPLETE(int adress)
//int adress;
{
int k=1;
do {
RD2510(adress,1);
k=b[0]&0x08;
}while(k); // 確認是否已發送完畢 to add CLRWDT
return;
}
// 接收數據子程序
int RXMSG(void)
{
int k;
// RD2510(CANINTF,1);
do
{
RD2510(0x2c,1); //??????????????????
k=b[0]&0x01;
}
while(k!=1) ;
BM2510(0x2c,0x01,0x00);
RD2510(0x61,2);
RecID_H=b[0];
RecID_L=b[1]&0xe0;
RD2510(0x65,1);
DLC=b[0]&0x0f;
RD2510(0x66,DLC);
for(i=0;i<DLC;i++)
{
c[i]=b[i];
RS232_send(c[i]);
}
return 1;
}
/* 接收數據子程序
int RXMSG(void)
{
int k;
// RD2510(CANINTF,1);
RD2510(0x2c,1); //??????????????????
k=b[0]&0x01;
if(k==1) {
BM2510(0x2c,0x01,0x00);
RD2510(RXB0SIDH,2);
RecID_H=b[0];
RecID_L=b[1]&0xe0;
RD2510(RXB0DLC,1);
DLC=b[0]&0x0f;
RD2510(RXB0D0,DLC);
for(i=0;i<DLC;i++) c[i]=b[i];
return 1;
}
return 0;
}*/
//-------------------串口初始化、發送----------------------------
void RS232_initial(void)
{
TRISC = 0X80;//c對應口input
TXSTA = 0X04;//設定TXSTA寄存器。高速
SPBRG = 64;//10MHZ, BRGH=1, 9600BPS.
PIE1 = 0X10;//清除PIE1所有中斷使能。
RCSTA = 0X80;//禁止接收。
INTCON = 0XC0;//清中斷
}
void RS232_send(int RS232_date)
{
TXREG = RS232_date;
TXSTAbits.TXEN=1;//啟動發送,TSR開始移位操作。
while (PIR1bits.TXIF==0);//等待中斷,在此為查詢方式。
while (TXSTAbits.TRMT==0);//判斷是否TSR發送完畢,未完等待。
TXSTAbits.TXEN=0;//關發送功能,防止TXREG空時,TXIF產生置位。
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -