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

📄 sja.cpp

📁 CAN__组建现场总线系统设计技术(光盘)
💻 CPP
字号:
//sja.cpp

#include "stdafx.h"

#include <afxmt.h>
#include <conio.h>
#include <winioctl.h>

#include "sjamacro.h"

BYTE g_rcbuf[FRAMELEN];//global variable,save frame received.
//---------function declare------------
BOOL LoadVxD(CString vxdpathname);
void ResetEpp();
void SetSJARegs();
BOOL InitializeSJA();

BOOL init(CString vxdname);
void deinit();

BYTE read(BYTE addr);
void write(BYTE addr,BYTE data);
int Receive(BYTE *RCdata);
BOOL Transmit(BYTE* TXdata);

void StartThread(void* r,void* e);
void EndThread();

UINT intHandler(LPVOID p);//中断服务程序

void (CALLBACK *pReceiveHandler)(BYTE* rcframe);//size is FRAMELEN
void (CALLBACK *pErrHandler)(BYTE errcode);


//-------------------------------------
//my code
HINSTANCE  _hKernel32Dll=NULL;
CEvent hEventRing3;
HANDLE hEventRing0, _hVxD=NULL;
int signal;
static BYTE baud=0xc3;//波特率

struct strEPPmode
{
	BYTE modereg;		//SJA1000工作模式,地址0
	BYTE intrenreg;		//中断允许寄存器,地址4
	BYTE bustime0;		//bustime0寄存器,地址6//
	BYTE bustime1;		//bustime1寄存器,地址7
	BYTE outpctr;		//输出控制寄存器,地址8
	BYTE errwarnlmt;	//错误控制限制寄存器,地址13
	BYTE RXerrcon;		//接收错误计数寄存器,地址14
	BYTE TXerrcon;		//发送错误计数寄存器,地址15
	BYTE clkdiv;		//分时寄存器,地址31
	BYTE acptcode0;		//接收码寄存器,地址16~19
	BYTE acptcode1;
	BYTE acptcode2;
	BYTE acptcode3;
	BYTE acptmask0;		//掩码寄存器,地址20~23
	BYTE acptmask1;
	BYTE acptmask2;
	BYTE acptmask3;
} EPPmode;

//------------------------------------------------
//read and write function. not export them.
BYTE read(BYTE addr)
{
	BYTE data;

    //address lock
    _outp(BASE_ADDRESS+2,0xd5);
    _outp(BASE_ADDRESS,addr);
    _outp(BASE_ADDRESS+2,0xd4);
    _outp(BASE_ADDRESS+2,0xd5);
    //read data
    _outp(BASE_ADDRESS+2,0xd7);
    _outp(BASE_ADDRESS+2,0xf7);  //read enable
    data=_inp(BASE_ADDRESS);
    _outp(BASE_ADDRESS+2,0xf5);
    _outp(BASE_ADDRESS+2,0xd5);

    return data;
}
void write(BYTE addr, BYTE data)
{
	//addr is the address of the SJA1000
    _outp(BASE_ADDRESS+2,0xd5); //1101 0101
    _outp(BASE_ADDRESS,addr);
	_outp(BASE_ADDRESS+2,0xd4); //1101 0100
    _outp(BASE_ADDRESS+2,0xd5); //1101 0101

    _outp(BASE_ADDRESS,data);
    _outp(BASE_ADDRESS+2,0xdd); //1101 1101
    _outp(BASE_ADDRESS+2,0xd5); //1101 0101
}

int Receive(BYTE* RCdata)
{	
	BYTE intreg=read(2);	//读出总线状态寄存器
	BYTE addr;
	addr=16;          //接收寄存器的首地址为16
	for(int i=0,j=0;i<11;i++,j++){
		RCdata[j]=read(addr++);
	}
	write(0x01,0x04);    //清空SJA1000的接收寄存器
	
	return intreg;	//返回值为未知错误
}

BOOL Transmit(BYTE* TXdata)
{
	BYTE addr;		
	BYTE reg;

	do{
		reg=read(2);		
	}while(!(reg&0x04));		//输出缓冲是为空则继续发送
	addr=16;		//基地址为16
	for(int j=0;j<FRAMELEN;j++)
		write(addr+j,TXdata[j]);		//送出数据
		
	write(1,0x01);		//送出发送命令

	return TRUE;	
}
//end read and write

//--------------------------------------------------
//(de)initial codes. first 3 functions not export.
BOOL LoadVxD(CString vxdpathname)	//装载VxD\\\\.\\Eppport.vxd
{
	HANDLE     (WINAPI *pfOpenVxDHandle)(HANDLE);
	DWORD      cbByteReturned;

	_hKernel32Dll = LoadLibrary("kernel32.dll");

	if(! _hKernel32Dll ){
		AfxMessageBox("无法加载动态链接库kernel32.dll");
		return FALSE;
	}

	pfOpenVxDHandle = (HANDLE (WINAPI *)(HANDLE))GetProcAddress(_hKernel32Dll,"OpenVxDHandle");
	
	hEventRing0 = (*pfOpenVxDHandle)(hEventRing3);
	
	_hVxD = CreateFile(vxdpathname, 0,0,0,
		              CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0);
	if(_hVxD == INVALID_HANDLE_VALUE){
		AfxMessageBox("Vxd文件加载错。");
		return FALSE;
	}

	if(!DeviceIoControl(_hVxD,VXD_REGISTER,
		            hEventRing0, sizeof(hEventRing0),
					NULL,0,
					&cbByteReturned,0))
					return FALSE; 
	return TRUE;
}
void ResetEpp()
{//初始化PC接口
	BYTE data,reset;

	data=_inp(BASE_ADDRESS+2);
	reset=data&0xfb;      //1111 1011
	_outp(BASE_ADDRESS+2,reset);
	for(int i=0;i<10000;i++);//this code is not stable.
	
	_outp(BASE_ADDRESS+2,data);

	for(i=0;i<10000;i++);//alse not stable.	
}
void SetBaud(BYTE newvalue)
{
	baud = newvalue;
}
void SetSJARegs()
{
	EPPmode.modereg=0x00;	//工作模式:双接受过滤方式
	EPPmode.intrenreg=0xFd; //中断允许位:只允许接收中断
	EPPmode.bustime0=baud;	//总线时钟0
	EPPmode.bustime1=0xa3;	//总线时钟1
	EPPmode.outpctr=0x1a;	//输出控制
	EPPmode.clkdiv=0xc3;	//分时
	EPPmode.acptcode0=0x3f;	//acceptance code位
	EPPmode.acptcode1=0xff;
	EPPmode.acptcode2=0xff;
	EPPmode.acptcode3=0xff;
	EPPmode.acptmask0=0xc0;	//acceptance mask位
	EPPmode.acptmask1=0xff;
	EPPmode.acptmask2=0xff;
	EPPmode.acptmask3=0xff;
}
BOOL InitializeSJA()
{
	/*********************/
	/** SJA1000 INITIAL **/
	/*********************/
	SetSJARegs();
	
   	//wait until the RR bit is set to '1'
	for(int i=0;i<20;i++){
		write(0,0x01);
		Sleep(100);
		if(read(0)&0x01) break;
	}
	if(i==20) return FALSE;
    
    read(3);       //clear the interrupt register
 
	write(6,EPPmode.bustime0);   //bustime0,缺省为0xa3
    write(7,EPPmode.bustime1);   //bustime1,缺省为0xc3
    write(8,EPPmode.outpctr);   //output control
    write(31,EPPmode.clkdiv);   //PeliCAN mode,bypass the input comparator
     
	write(16,EPPmode.acptcode0); //设置接受地址判断,缺省为ffffffff
	write(17,EPPmode.acptcode1);
	write(18,EPPmode.acptcode2);
	write(19,EPPmode.acptcode3);

	write(20,EPPmode.acptmask0);//设置接受时不考虑的地址位,缺省为ffffffff
	write(21,EPPmode.acptmask1);
	write(22,EPPmode.acptmask2);
	write(23,EPPmode.acptmask3);

	write(4,EPPmode.intrenreg);
	write(1,0x04);

	for(i=0;i<20;i++){
		write(0x00,EPPmode.modereg);//
		Sleep(100);
		if( ! (read(0)&0x01) ) break;
	}
	if(i==20) return FALSE;
	
	return TRUE;
}
//the 3-in-1 initial function here.export it.
BOOL init(CString vxdname)
{
	if(!LoadVxD(vxdname))
	{//cannot control io.so free library and vxd handle.
		deinit();
		return FALSE;
	}
	ResetEpp();
	if(!InitializeSJA()){
		AfxMessageBox("初始化SJA1000接口失败!请检查EPP口。");
		return FALSE;
	}
	return TRUE;
}
void deinit()
{
	if(_hVxD)
	{
		CloseHandle(_hVxD);
		_hVxD=NULL;
	}
	if(_hKernel32Dll)
	{
		FreeLibrary(_hKernel32Dll);
		_hKernel32Dll=NULL;
	}
}
//end of (de)initial codes.

//--------------------------------------------------------------
//start communication services.
/*e:point to a function:void CALLBACK errhandler(BYTE errcode)
 *r:point to a function:void CALLBACK rchandler(BYTE* rcframe)
 */
void StartThread(void* r,void* e)
{
	pReceiveHandler=(void (CALLBACK *)(BYTE* rcframe))r;
	pErrHandler=(void (CALLBACK *)(BYTE errcode))e;

	CWinThread *pThread =	AfxBeginThread(intHandler,e,THREAD_PRIORITY_ABOVE_NORMAL); 
}


UINT intHandler(LPVOID p)
{
	int intrkind;
	signal=NOUSRSIG;

	while(TRUE)
	{
		::WaitForSingleObject(hEventRing3,INFINITE);

		intrkind=read(3);
		if(intrkind != 1)//some error occurred
			(*pErrHandler)(intrkind);

		switch(signal){
		case NOUSRSIG://signal不是主线程设置,则为硬件中断
			Receive(g_rcbuf);
			(*pReceiveHandler)(g_rcbuf);
			break;
		case ENDSIG://是结束线程的信号
			write(4,0x00);	//中断允许寄存器全置零,避免有未完成操作
			write(1,0x20);	//放弃发送
			return 0;
		default:			//其他,返回错误值
			intrkind=-1;
		}

		signal=NOUSRSIG;	//signal和hEventRing3复位
		//恢复中断响应
	}
	
	return 0;
}

void EndThread()
{
	signal=ENDSIG;	//给signal置结束线程标志
	hEventRing3.SetEvent();
}
//end of communication services

BYTE ReadSJAReg(BYTE addr)
{
	return read(addr);
}

⌨️ 快捷键说明

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