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

📄 can_232.c

📁 本程序是一个将CanOpen协议的通讯转换为TTL串口通讯(9600,e,7,1),CANOPEN的站号是9
💻 C
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------
//创建日期:	2006年3月17日
//文件名称:	can_232.c
//作    者:	边国利

//说    明:	1.本程序是用STC89C52RC芯片的串口接收FT025发送的数据,再将其用CAN
//			总线发送出去,另一方面将从CAN总线上的数据通过串口发送到FT025中
//			(CAN总线是用52 CPU外扩SJA1000实现的)
//			2.利用T0的计数器功能将一个1024Hz的方波信号分频为2Hz的方波信号
//			通过一个I/O输出
//			3.利用T1的计数器功能将另一个1024Hz的方波信号分频为2Hz的方波信
//			号通过一个I/O输出
//---------------------------------------------------------------------

#include	"Can_232.H"

//#define		JINGZHEN_11M
//分频因子:FenPin=(65536-FenPinH*256-FenPinL)*2
//分频公式:fO=fI/FenPin
//512分频
#define FenPinL	0
#define FenPinH	0xFF
//#define CPU_CLK6		//单片机工作于6时钟,如果不声明此变量,则工作于12时钟
//2048分频
//#define FenPinL	0
//#define FenPinH	0xFC

//读取Flash的特殊功能寄存器
sfr	WDTRST		=	0xE1;
sfr ISP_DATA	=	0xE2;
sfr ISP_ADDRH	=	0xE3;
sfr ISP_ADDRL	=	0xE4;
sfr ISP_CMD		=	0xE5;
sfr ISP_TRIG	=	0xE6;
sfr ISP_CONTR	=	0xE7;

extern void _nop_(void);
#define ISP_BYTE_READ	1	//字节读
#define ISP_BYTE_WRITE	2	//字节写
#define ISP_ERASE		3	//扇区擦除
#define ISP_WAIT_TIME	1	//设置等待时间,40MHz以下0,20MHz以下1,10MHz以下2,5MHz以下3

#define EEP_Start	0x2000	//Stc89c51和Stc89c52芯片的EEPROM起始地址是2000H
#define EEP_Offset	0x0200	//存储最后一次设置标志量

//#define EEP_Start	0x8000	//Stc89c54,Stc89c55和Stc89c58芯片的EEPROM起始地址是8000H
typedef union _I2C_
{
	unsigned short i;
	unsigned char c[2];
}I2C;

unsigned short	OffsetAddr;
I2C	OffsetFlag;
unsigned short	usTmp;
unsigned char	RunStatus;//运行状态

//---------------------------------------------------------------------
//函数名称:	EEP_BYTE_READ
//功    能:	从EEPROM中读取一个字节
//参    数:	EEP_ADDR:读取地址
//返 回 值:	读回的数据
//作    者:	边国利
//日    期:	2006年7月18日
//---------------------------------------------------------------------
unsigned char EEP_BYTE_READ(unsigned short  EEP_ADDR)
{
	I2C x;
	bit tmpBit;
	//字节地址
	x.i=EEP_ADDR;
	ISP_ADDRH=x.c[0];
	ISP_ADDRL=x.c[1];
	tmpBit=EA;
	EA=0;//关总中断
	ISP_CONTR=(0x80|ISP_WAIT_TIME);//允许ISP操作,并设置等待时间

	ISP_CMD=ISP_BYTE_READ;

	//触发命令
	ISP_TRIG=0x46;
	ISP_TRIG=0xB9;

	_nop_();
	ISP_CONTR=0;//出于安全考虑(可以不加)
	ISP_CMD=0;//出于安全考虑(可以不加)
	EA=tmpBit;//开总中断
	return ISP_DATA;
}

//---------------------------------------------------------------------
//函数名称:	EEP_BYTE_WRITE
//功    能:	向EEPROM中写一个字节
//参    数:	EEP_ADDR:写入地址,c:写入数据
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年7月18日
//---------------------------------------------------------------------
void EEP_BYTE_WRITE(unsigned short EEP_ADDR,unsigned char c)
{
	I2C x;
	bit tmpBit;
	x.i=EEP_ADDR;
	//字节地址
	ISP_ADDRH=x.c[0];
	ISP_ADDRL=x.c[1];

	ISP_DATA=c;
	tmpBit=EA;
	EA=0;//关总中断
	ISP_CONTR=(0x80|ISP_WAIT_TIME);//允许ISP操作,并设置等待时间

	ISP_CMD=ISP_BYTE_WRITE;

	//触发命令
	ISP_TRIG=0x46;
	ISP_TRIG=0xB9;

	_nop_();
	ISP_CONTR=0;//出于安全考虑(可以不加)
	ISP_CMD=0;//出于安全考虑(可以不加)
	EA=tmpBit;
}

//---------------------------------------------------------------------
//函数名称:	EEP_ERASE
//功    能:	扇区擦除
//参    数:	SectorNo:扇区号,Stc89c51和Stc89c52是1~8,Stc89c54,Stc89c55和Stc89c58是1~58
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年7月18日
//---------------------------------------------------------------------
void EEP_ERASE(unsigned char SectorNo)
{
	I2C x;
	bit tmpBit;
	if(SectorNo>58) return;
	SectorNo--;
	x.i=EEP_Start+SectorNo*512;
	//字节地址
	ISP_ADDRH=x.c[0];
	ISP_ADDRL=x.c[1];
	tmpBit=EA;
	EA=0;//关总中断
	ISP_CONTR=(0x80|ISP_WAIT_TIME);//允许ISP操作,并设置等待时间

	ISP_CMD=ISP_ERASE;

	//触发命令
	ISP_TRIG=0x46;
	ISP_TRIG=0xB9;

	_nop_();
	ISP_CONTR=0;//出于安全考虑(可以不加)
	ISP_CMD=0;//出于安全考虑(可以不加)
	EA=tmpBit;
}

//---------------------------------------------------------------------
//函数名称:	InitCan
//功    能:	初始化Can控制器
//参    数:	无
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年3月20日
//---------------------------------------------------------------------
void InitCan(void)
{
	//进入复位模式;
	while((ModeControlReg & RM_RR_Bit)==0)
	{
		ModeControlReg =RM_RR_Bit;
	}
#ifdef CPU_CLK6
	ClockDivideReg=CANMode_Bit|CBP_Bit;	//CLKOUT引脚输出时钟且2分频,工作模式设
												//为PeliCan模式(支持2.0A和2.0B)
#else
	ClockDivideReg=CANMode_Bit|CBP_Bit|DivBy1;	//CLKOUT引脚输出时钟且不分频,工作模式设
												//为PeliCan模式(支持2.0A和2.0B)
#endif
	InterruptEnReg=ClrIntEnSJA;		//禁止所有中断
	//Can_IR=0;		//清除中断标志

	AcceptCode0Reg=0;		//验收代码0
	AcceptCode1Reg=0;		//验收代码1
	AcceptCode2Reg=0;		//验收代码2
	AcceptCode3Reg=0;		//验收代码3
	AcceptMask0Reg=0xFF;	//验收屏蔽0
	AcceptMask1Reg=0xFF;	//验收屏蔽1
	AcceptMask2Reg=0xFF;	//验收屏蔽2
	AcceptMask3Reg=0xFF;	//验收屏蔽3
#ifdef JINGZHEN_11M
	switch(btr)
	{
	case btr_10k:
		//通讯速率设为10K,SJW=1,BTL=19,Sampling point=89.5%
		BusTiming0Reg=0x1C;
		BusTiming1Reg=0x1F;
		break;
	case btr_20k:
		//通讯速率设为20K,SJW=1,BTL=12,Sampling point=83.3%
		BusTiming0Reg=0x16;
		BusTiming1Reg=0x18;
		break;
	case btr_50k:
		//通讯速率设为50K,SJW=1,BTL=11,Sampling point=81.8%
		BusTiming0Reg=0x09;
		BusTiming1Reg=0x17;
		break;
	case btr_125k:
		//通讯速率设为125K,SJW=1,BTL=11,Sampling point=81.8%
		BusTiming0Reg=0x03;
		BusTiming1Reg=0x17;
		break;
	case btr_250k:
		//通讯速率设为250K,SJW=1,BTL=11,Sampling point=81.8%
		BusTiming0Reg=0x01;
		BusTiming1Reg=0x17;
		break;
	default:
		//通讯速率设为500K,SJW=1,BTL=11,Sampling point=81.8%
		BusTiming0Reg=0x00;
		BusTiming1Reg=0x17;
	}
#else
	switch(btr)
	{
	case btr_10k:
		//通讯速率设为10K,SJW=1,BTL=21,Sampling point=81.0%
		BusTiming0Reg=0x25;
		BusTiming1Reg=0x3F;
		break;
	case btr_20k:
		//通讯速率设为20K,SJW=1,BTL=21,Sampling point=81.0%
		BusTiming0Reg=0x12;
		BusTiming1Reg=0x3F;
		break;
	case btr_50k:
		//通讯速率设为50K,SJW=1,BTL=20,Sampling point=85.0%
		BusTiming0Reg=0x07;
		BusTiming1Reg=0x2F;
		break;
	case btr_125k:
		//通讯速率设为125K,SJW=1,BTL=16,Sampling point=87.5%
		BusTiming0Reg=0x03;
		BusTiming1Reg=0x1C;
		break;
	case btr_250k:
		//通讯速率设为250K,SJW=1,BTL=16,Sampling point=87.5%
		BusTiming0Reg=0x01;
		BusTiming1Reg=0x1C;
		break;
	case btr_500k:
		//通讯速率设为500K,SJW=1,BTL=16,Sampling point=87.5%
		BusTiming0Reg=0x00;
		BusTiming1Reg=0x1C;
		break;
	case btr_800k:
		//通讯速率设为800K,SJW=1,BTL=10,Sampling point=80.0%
		BusTiming0Reg=0x00;
		BusTiming1Reg=0x16;
		break;
	case btr_1M:
		//通讯速率设为1M,SJW=1,BTL=8,Sampling point=75.0%
		BusTiming0Reg=0x00;
		BusTiming1Reg=0x14;
		break;
	}
#endif

	//TX0悬空,TX1推挽,TX1的输出极性控制位置1,正常输出模式
	OutControlReg = Tx1Float|Tx0PshPull|NormalMode;
	//OutControlReg = Tx1PullDn|Tx0PullUp|ClkOutMode;//NormalMode;
	//OutControlReg = Tx1PullDn|Tx0PullUp|OCPOL0_Bit|NormalMode;

	//RxBufstartAdr=0;					//RX缓冲器起始地址
	//TxErrCountReg=0x88;					//TX错误计数器
	//ErrCodeCapReg=0x0D;					//错误代码捕捉

	//允许数据超载中断,错误警告中断,发送中断,接收中断
	//InterruptEnReg=RIE_Bit|TIE_Bit;
	InterruptEnReg=/*DOI_Bit|EI_Bit|*/RIE_Bit|TIE_Bit;


	//退出复位模式
	while((ModeControlReg & RM_RR_Bit) != ClrByte)
	{
		ModeControlReg = ClrByte;
	}
	//释放接收缓冲区,清除数据超载位
	CommandReg=RRB_Bit|CDO_Bit;
}
//---------------------------------------------------------------------
//函数名称:	ReadCanID
//功    能:	读取Can通讯数据帧的11位标志符的低三位
//参    数:	无
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年3月21日
//---------------------------------------------------------------------
//void ReadCanID(void)
//{
//	unsigned char i=0;
//	Can_ID=P1&0xFC;
//	while(i!=Can_ID)
//	{
//		i=Can_ID;
//		_nop_();
//		_nop_();
//		_nop_();
//		_nop_();
//		Can_ID=P1&0xFC;
//	}
//    Can_ID=~Can_ID;
//    Can_ID>>=2;
//	Can_ID|=BIT6;
//}
//---------------------------------------------------------------------
//函数名称:	GetEven
//功    能:	求一个字节的偶校验
//参    数:	待处理的字节
//返 回 值:	处理后的字节
//作    者:	边国利
//日    期:	2006年3月20日
//---------------------------------------------------------------------
unsigned char GetEven(unsigned char a)
{
	//偶校验,求校验位
	bitChar=a;
	B_7=0;
	B_7^=B_6;
	B_7^=B_5;
	B_7^=B_4;
	B_7^=B_3;
	B_7^=B_2;
	B_7^=B_1;
	B_7^=B_0;
	return bitChar;
}
//---------------------------------------------------------------------
//函数名称:	SendData_Can
//功    能:	通过Can总线向外发送数据
//参    数:	BlockIndex,要发送的块索引
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年3月27日
//---------------------------------------------------------------------
void SendData_Can(unsigned char data * data BlockIndex)
{
	unsigned char i,j;
	unsigned char k,tmpBlk;//数据长度;

	//中止发送
	//CommandReg=AT_Bit;
	tmpBlk=*BlockIndex;
    (*BlockIndex)++;
	i=tmpBlk*8;
	j=i+8;
	//求数据长度
	k=8;
	if(j>CAN_SendLen)
	{
		j=CAN_SendLen;
		k=j-i;
		*BlockIndex=5;
	}

	//将数据写到CAN控制器
    tmpBlk++;
	tmpBlk<<=1;
	tmpBlk++;
#ifdef KuoZhan
	TxFramInFo=0x80+k;	//TX 帧信息,最高位是扩展帧标志,低四位是数据长度
	TxBuffer[0]=0;//TX 识别码1,
    TxBuffer[1]=0;//TX 识别码2,
	TxBuffer[2]=(tmpBlk<<2)|((Can_ID>>5)&3);//TX 识别码3,,高四位是命令识别码,低四位是地址的高四位
	TxBuffer[3]=Can_ID<<3;//TX 识别码4,高五位是地址的低五位,低三位无意义
#else
	tmpBlk<<=4;
	TxFramInFo=k;		//TX 帧信息,高四位保持全0,低四位是数据长度
	TxBuffer[0]=tmpBlk|Can_ID_H;//TX 识别码1,高四位是命令识别码,低四位是地址的高四位
	//TX 识别码2,高三位是地址的低三位,低五位无意义
	TxBuffer[1]=Can_ID_L;
#endif


	k+=StartNo;
	for(j=StartNo;j<k;j++,i++)
	{
		TxBuffer[j]=CAN_SendBuf[i];
	}

	//请求发送
	CommandReg=AT_Bit|TR_Bit;
}
//---------------------------------------------------------------------
//函数名称:	WDT_RST
//功    能:	复位并启动WDT
//参    数:	无
//返 回 值:	无
//作    者:	边国利
//日    期:	2006年3月21日
//---------------------------------------------------------------------
void WDT_RST(void)
{
	WDTRST=0x35;
}
//---------------------------------------------------------------------
//函数名称:	ReadCanID
//功    能:	读取Can通讯数据帧的11位标志符的低三位
//参    数:	无
//返 回 值:	执行结果
//			0:成功
//			1:不是本机数据
//			2:错误命令
//			3:目前不支持的命令
//			4:出错
//			5:修改CAN波特率,要求重新初始化CAN控制器
//作    者:	边国利
//日    期:	2006年3月21日
//---------------------------------------------------------------------
unsigned char ReadCan(void)
{
    unsigned char j,x;
	bit aa,bb,cc;
	union
	{
		unsigned long l;
        unsigned int mn[2];
        //unsigned int mn;
		struct
		{
			unsigned char i;
			unsigned char k;
			unsigned char m;
			unsigned char n;
		}yy;
	}xx;

	//读取中断源
	xx.yy.i=InterruptReg;
	InterruptReg=0;//清除中断标志
	aa=xx.yy.i&RI_Bit;
	bb=xx.yy.i&TI_Bit;
//#ifdef KuoZhan
	if((!aa)&&(!bb))
		bb=1;
//#endif
	if(aa)
	{//接收到数据
		xx.yy.i=RxFramInFo;//读取信息

		//帧长度

⌨️ 快捷键说明

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