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