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