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

📄 cansoft.c

📁 485信号与can信号间的数据转换
💻 C
字号:
/*------------------------------------------------------------------------------
// file:        CANSOFT.C
// description:	This is the 'C' source code for the spi interface
//		for communicating with the MCP2515 CAN controller
//		chip.
// last update: 12/09/07
------------------------------------------------------------------------------*/

#include <reg51.h>
#include <INTRINS.H>
#include <mcp2515.h>

typedef unsigned char uchar;
typedef unsigned int uint;

/******************************************/
#define baud_rate 9600      //修改波特率
#define reload 256-(unsigned char)((22118400/baud_rate/384)+0.5)
////////////////////////////////////////////

/*****************************************/
#define vaule 0x5A         //异或值,根据需要修改,暂定为0x5A
/////////////////////////////////////////

#define UART_BUFFER_LENGTH 128     //CAN接收的数据缓冲区的长度,先设定为96个字节
/*定义寄存器地址 */
sfr AUXR = 0x8E;
sfr CLK_DIV = 0xC7;
sfr WDT_CONTROL =0xE1;
sfr P1M0 = 0x91;
sfr P1M1 = 0x92;
sfr P3M0 = 0xB1;
sfr P3M1 = 0xB2;
//************************//

bit	 sendpc_ok;		//发送到电脑的数据已准备,需要发送
bit	 Rec232_ok;
bit  canrx0_ok;		//已收到can0数据标志
bit  canrx1_ok;		//已收到can1数据标志
bit	 flag_int;

uchar TxData,Rx0Data,Rx1Data;	//发送和接收数据缓冲区
uchar savepoint,sendpoint;								//发送数据到电脑时缓冲区的两个指针
uchar idata rs232buff[UART_BUFFER_LENGTH];//CAN接收的数据的缓冲区

/* SPI*/
sbit CS=P1^4;       /*片选*/
sbit SO=P1^5;       /*数据输出 */
sbit SK=P1^7;       /* 时钟  */
sbit SI=P1^6;        /* 数据输入*/

sbit RST=P1^3;
sbit RS485=P3^4;
sbit RT=P3^7;
sbit P1_0=P1^0;

//以下是和mcp2510通讯的6种命令
void SPI_Reset(void);											//复位
unsigned char SPI_Stusta(void);
void SPI_BIT(unsigned char cData,unsigned char cAddress,unsigned char cPB);				 //位修改
void SPI_RTS(unsigned char cData);			  //请求发送
void SPI_Write(unsigned char cData,unsigned char cAddress);				 //写单字节数据
unsigned char SPI_Read(uchar cAddress);			//读单字节数据

void CONFIG_2515(void);		//mcp2510初始化
void TxMsg(uchar cData);	//发送数据
unsigned char Rx0Msg(uchar cAddress);		//接收数据0
unsigned char Rx1Msg(uchar cAddress);		//接收数据1

void UART_ISR(void);		//串口中断服务函数
void INT0_ISR(void);
void delay(uint);

void main(void) {
  uchar sendlength;
  uchar i;
  WDT_CONTROL = 0x00;        //禁止看门狗 
  CLK_DIV = 0x00;            //系统时钟为外部时钟,无分频
  P1M0 =0x0;
  P1M1 =0x08;
  P3M0 =0x00;
  P3M1 =0x00;
  P1   =0xFF;
  P3   =0xFF;
  SK=0;  
//  SCON = 0x50;      //8位串口通讯
  SCON=0XD0;          //9位串口通讯  
  TMOD = 0x20;   
  TH1 =  reload;    
  TL1 =  reload;    
  TR1 = 1;
  ET1 = 0;
  ES = 1;
  
  TI=0;
  RI=0;
  EA = 1;

  if(RT == 0)
	  RS485 = 1;
  else
	  RS485 = 0;

  Rec232_ok = 0;
  CONFIG_2515();

  delay(10000);
  IT0 = 1;
  IE0=0;
  EX0 = 1;

  while(1) {
   //接收器0
	sendlength = Rx0Msg(RXB0D0);	//主机接收数据
	if (canrx0_ok) {
		canrx0_ok = 0;				//接收正确
		savepoint++;
		if (savepoint == UART_BUFFER_LENGTH)
			savepoint = 0;
		if (savepoint == 0)
			rs232buff[UART_BUFFER_LENGTH-1] = Rx0Data;
		else
			rs232buff[savepoint-1] = Rx0Data;
		if (!sendpc_ok) {									 //如果缓冲区里有数据就开始发送到电脑
			sendpc_ok = 1;									 //这个前提是原来缓冲区里是没有待发送数据的
			TI = 1;
		}
	}
	//接收器1
	sendlength = Rx1Msg(RXB1D0);	//主机接收数据
	if (canrx1_ok) {
		canrx1_ok = 0;				//接收正确
		savepoint++;
		if (savepoint == UART_BUFFER_LENGTH)
			savepoint = 0;
		if (savepoint == 0)
			rs232buff[UART_BUFFER_LENGTH-1] = Rx1Data;
		else
			rs232buff[savepoint-1] = Rx1Data;
		if (!sendpc_ok) {									 //如果缓冲区里有数据就开始发送到电脑
			sendpc_ok = 1;									 //这个前提是原来缓冲区里是没有待发送数据的
			TI = 1;
		}
	}
	if (Rec232_ok == 1) {
		Rec232_ok = 0;
		TxMsg(TxData);	//发送数据到从机
	}
	if(flag_int == 1){
		flag_int = 0;
		i = SPI_Read(EFLG);
		if(i&0xF8)
 			EX0 = 0;
    		CONFIG_2515();
			delay(10000);
 		    IT0 = 1;
			IE0=0;
		    EX0 = 1;
	}
  }
}

//初始化mcp2510
void CONFIG_2515(void){
	RST = 0;
	delay(60000);
	RST = 1;
	delay(6000);
	SPI_Reset();
    delay(6000);						 //复位
	SPI_Write(0x85,CANCTRL);		 //进入配置模式
	SPI_Write(0x07,CNF1);			 //设置波特率
	SPI_Write(0xc0,CNF2);		 //bps :125k/s
	SPI_Write(0,CNF3);
	SPI_Write(0x0,CANINTF);	 //
	SPI_Write(0x20,CANINTE);	 //设置中断
	SPI_Write(0,TXB0SIDH);
	SPI_Write(0x0,TXB0SIDL);
	SPI_Write(1,TXB0DLC);
	SPI_Write(3,TXB0CTRL);		 //发送优先级0>1>2
	SPI_Write(2,TXB1CTRL);
	SPI_Write(1,TXB2CTRL);
	SPI_Write(0x0,BFPCTRL);
	SPI_Write(0x64,RXB0CTRL);	 //设置接收方式
	SPI_Write(0x60,RXB1CTRL);
	SPI_Write(0x08,RXF0SIDL);	 //设置验收滤波寄存器
	SPI_Write(0x08,RXF1SIDL);
	SPI_Write(0x08,RXF2SIDL);
	SPI_Write(0x08,RXF3SIDL);
	SPI_Write(0x08,RXF4SIDL);
	SPI_Write(0x08,RXF5SIDL);
	SPI_Write(0,RXM0SIDH);			//设置屏蔽寄存器
	SPI_Write(0xe0,RXM0SIDL);
	SPI_Write(0,RXM0EID8);
	SPI_Write(0,RXM0EID0);
	SPI_Write(0,RXM1SIDH);
	SPI_Write(0xe0,RXM1SIDL);
	SPI_Write(0,RXM1EID8);
	SPI_Write(0,RXM1EID0);
	SPI_BIT(0,CANCTRL,0xe0);		//进入正常模式
}

// 发送数据子程序 
void TxMsg(uchar cData){
	uchar temp;
	while (SPI_Stusta() & 0x04);
	SPI_Write(cData,TXB0D0);
	SPI_RTS(0);
	do {
		temp=SPI_Stusta()&0x04;
	}while(temp);	// 确认是否已发送完毕
}

// 接收0数据子程序 
unsigned char Rx0Msg(uchar cAddress) {
	uchar temp;
	temp=SPI_Stusta()&0x01;
	if(temp) { 
		Rx0Data = SPI_Read(cAddress);
		SPI_BIT(0,CANINTF,0x01);
		canrx0_ok = 1;
		return (1);
	}
	return 0;
}

// 接收1数据子程序 
unsigned char Rx1Msg(uchar cAddress) {
	uchar temp;
	temp = SPI_Stusta()&0x02;
	if(temp) { 
		Rx1Data = SPI_Read(cAddress);
		SPI_BIT(0,CANINTF,0x02);
		canrx1_ok = 1;
		return (1);
	}
	return 0;
}

/*spi通讯,读一个字节*/
unsigned char Read8() {
	bit bData;
	uchar cLoop;
	uchar ABC;
	for(cLoop=0;cLoop<8;cLoop++) {
		SK=1;
	    delay(1);
		SK=0;
 	    delay(1);
		bData=SO;
		ABC<<=1;
		if(bData)
			ABC|=0x01;
	}
	return ABC;
}

/*spi通讯,写一个字节*/
void Write8(unsigned char cData) {
	uchar cLoop;
	for(cLoop=0;cLoop<8;cLoop++) {
	SK=0;	
	if((cData&0x80)==0)
			SI=0;
		else
			SI=1;
    delay(1);
	SK=1;
	cData<<=1;
	}
}

/*MCP2515复位*/
void SPI_Reset(void) {
	CS=0;
	Write8(RESET);
	SK=0;
    delay(1);
	CS=1;
}

/* MCP2515读入状态*/
unsigned char SPI_Stusta(void) {
	uchar cData,temp;
	do {
		CS=0;
		Write8(STUSTA);
		cData=Read8();
		temp=cData;
		cData=Read8();
		SK=0;
	    delay(1);
		CS=1;
	} while (cData!=temp);
	return cData;
}

/*MCP2515位修改*/
void SPI_BIT(unsigned char cData,unsigned char cAddress,unsigned char cPB) {
	CS=0;
	Write8(BITM);
	Write8(cAddress);
	Write8(cPB);
	Write8(cData);
	SK=0;
    delay(1);
	CS=1;
}

/*MCP2515请求发送*/
void SPI_RTS(unsigned char cData) {
	uchar temp;
	temp=RTS;
	switch (cData) {
		case 0: temp|=0x1; break;
		case 1: temp|=0x2; break;
		case 2: temp|=0x4; break;
		default: break;
	}
	CS=0;
	Write8(temp);
	SK=0;
    delay(1);
	CS=1;
}

/* 写入一个字节,cData为写入的数,cAddress为写入地址 */
void SPI_Write(unsigned char cData,unsigned char cAddress) {
	CS=0;
	Write8(WRITE);
	Write8(cAddress);
	Write8(cData);
	SK=0;
    delay(1);
	CS=1;
}


/*读出一个字节,cAddress为读出地址*/
unsigned char SPI_Read(uchar cAddress) {
	uchar cData;
	CS=0;
	Write8(READ);
	Write8(cAddress);
	cData=Read8();
	SK=0;
    delay(1);
	CS=1;
	return cData;
}


void delay(uint number){
	for(;number>0;number--){
		_nop_();
		_nop_();
		_nop_();
	}
}



void INT0_ISR(void) interrupt 0{
	flag_int = 1;
}


/*uart 通讯接收中断*/
void UART_ISR(void) interrupt 4{
	if(RI){
		RI = 0;							// clear receive interrupt flag
		TxData = SBUF^vaule;					// copy input buffer to temp
		Rec232_ok = 1;
	}
	if(TI){
		TI = 0;							// clear transmit interrupt flag
		if (sendpoint == savepoint){
			sendpoint = 0;
			savepoint = 0;
			sendpc_ok = 0;
		}
		else {
			SBUF = rs232buff[sendpoint++]^vaule;
			if (sendpoint == UART_BUFFER_LENGTH)
				sendpoint = 0;
		}
	}
}


⌨️ 快捷键说明

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