자동차 자기진단 장치

자작 

CAN Type / KOBD





2011년 만들어 본 미니 GST


Portable CAN type OBD / KOBD / OBD-II reader

http://turbocrazy.tistory.com/1137


소스 공개 : 허접하지만 참고들 하시라고 ....

code_canx.zip




atmega168로 컴파일 되도록 세팅됨

만일 코드가 크면 atmega328로 설정해서 컴파일

(makefile 내의 MCU = atmega168 ==> MCU = atmega328 로 변경)


EagleCAD (이글캐드 도면)

OBDCANLCD_X010.brd

OBDCANLCD_X010.sch





프로그램 기본 전제및 주의사항
// ----------------------------------------------------------------------------
// OBD-II CAN LCD Project : 20 Aug 2011 -CAN Lib based version
// ----------------------------------------------------------------------------
// -- Define MCP2515 port & CS in defaults.h and built in LibCAN.a
// -- MCP2515_CS = B,2  MCP2515_INT B,0
// -- SD_card CS = B,1
// -- Atmega168 @ 16MHz
// --- Define AVR type at UART.C for proper UART port setting
// --- Define AVR type at "sd_raw_config.h" for proper pin SD CS setting
#define CANSPEED_250  	3		// CAN speed at 250 kbps @16MHz
#define CANSPEED_500	1		// CAN speed at 500 kbps @16MHz
#define PID_REQUEST     		0x7DF
#define PID_REPLY				0x7E8	// ECU=0x7E0/8, TCU=0x7E1/9
// in 29bit ID 0x18DAF110 is ECM, 0x18DAF118 -> TCM
// CAN id : 0x7df(11bit) or 0x18DB33F1(29bit)
// https://www.scantool.net/forum/index.php?topic=5029.0
#define COOLANT_TEMP			0x05
#define ENGINE_RPM      		0x0C
#define VEHICLE_SPEED   		0x0D
#define IG_ANGLE	      		0x0E
#define VOLTBATT 	     		0x42
#define O2_VOLTAGE      		0x14
#define THROTTLE				0x11
#define DTCMIL					0x01
#define OBDTYPE					0x1C
#define FUELTRIM				0x07
#define MILCODE					0x02
#define MODE01					0x01
#define MODE03					0x03
#define MODE04					0x04
#define MODE07					0x07
#define	KEY1_DOWN				!(PINC & 0x20)	//(PINC.5 == 0)
#define	KEY2_DOWN				!(PINC & 0x10)	//(PINC.4 == 0)
#define CANSPEED_125 	7		// CAN speed at 125 kbps
#define CANSPEED_250  	3		// CAN speed at 250 kbps
#define CANSPEED_500	1		// CAN speed at 500 kbps 
#define MaxCANmsg		10

#include 
#include 
#include 
#include 
#include 
#include 

#include "can.h"
#include "uart.h"
#include "lcd.h"			// LCD IO & control pin setting
// #include "defaults.h"   	// MCP2515 IO & CS pin setting - done in Libcan.a
// ----------------------------------------------------------------------------
// standard lib don't support printf() for floats - to save space in flash
// for it use, 
// PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt -lm
// PRINTF_LIB = $(PRINTF_LIB_FLOAT)
// #---------------- Library Options ----------------
// # Minimalistic printf version
uint8_t Mode01REQ[]={ENGINE_RPM,THROTTLE,IG_ANGLE,O2_VOLTAGE,
					COOLANT_TEMP,VEHICLE_SPEED,VOLTBATT,FUELTRIM};
// ---------------------------- + note it is always 8 in OBD CAN  -------------
// ------------ CAN ID(11bit)   |   Len Mode   PID
can_t DTCreq  ={PID_REQUEST,{0},8,{0x01,MODE03,0x00,0x00,0x00,0x00,0x00,0x00}};
can_t Mode01  ={PID_REQUEST,{0},8,{0x02,MODE01,0x00,0x00,0x00,0x00,0x00,0x00}};
// Flow control for Multi frame, ID must be the one with that ECU
// FLW_CON.data[0] = 0x30;		// Send FC_CTS to continue	
// FLW_CON.data[1] = MaxCANmsg;	// BlockSize-get w/o stop
// FLW_CON.data[2] = 20;		// STmin : ms time btw message
// However, P2CAN time is kept/waited, Ok to receive message, if not use it
can_t FLW_CON ={0x7E0,{0},8,{0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
can_t can_mT;					// Can message to send / reqeust
can_t can_mR;					// Receiving buffer single frame
can_t can_mM[MaxCANmsg];		// Receiving buffer Multi frame
static int canMsgIndex;			// Handling for multiple can messages
int ByteNo = 0, massageType, KeyPressed=0, idx =0, menu=0, count=0, toggle=0;
char OBD_data[17], TXbuff[31];
uint16_t P2CAN=0;
// -------------------------------------------------------------------------
char *LCD_Menu[]={"1.OBD Info", "2.Confirmed DTC","3.Pending DTC",
				  "4.Permanant DTC","5.ERASE DTC","6.DATA FAST","7.DATA SLOW"};
char *OBDtype[]={"CARB OBDII","EPA OBD","OBD-II","OBD-1","NONE OBD",
				 "EOBD","EOBD_OBDII","EOBD&OBD","EOBD_1_II","JOBD"};
void print_can_message(can_t *message);
void disp_can_message_LCD(can_t *message);
//int CheckCAN(can_t *message, int mode, int pid);
//void Send_CAN_msg(can_t *message);
int GetCANmsg(void);
void DisplayOBDdata(char * buffer);
void OBD_INFO(int menu, char *buffer);
void OBD_INFO_PDTC(char *buffer);
void OBD_INFO_CDTC(char *buffer);
void OBD_PERM_DTC(char *buffer);
void OBD_DTC_ERASE(char *buffer);
void OBD_INFO_TYPE(char *buffer);
void OBD_DATA_FAST(char *buffer);
void OBD_DATA_SLOW(char *buffer);
void RS232_can_message(can_t *m);
CAN 메세지 필터 - 수많은 CAN 메세지중에서 필요한것 만 고르기 위함
// ----------------------------------------------------------------------------
prog_uint8_t can_filter [] = 
{ 
    // Group 0 
    MCP2515_FILTER (0x7e8), // ??Filter 0 - if '0' accept ALL message
    MCP2515_FILTER (0x7e8), // ??Filter 1 

    // Group 1 
    MCP2515_FILTER (0x7e8), // ??Filter 2 
    MCP2515_FILTER (0x7e8), // ??Filter 3 
    MCP2515_FILTER (0x7e8), // ??filter 4 
    MCP2515_FILTER (0x7e8), // ??Filter 5 

    MCP2515_FILTER (0x7FF), // Mask 0 (for group 0) 
    MCP2515_FILTER (0x7FF) // Mask 1 (for group 1) 
};
// ----------------------------------------------------------------------------
/* signal handler for timer interrupt TOV0 for P2CAN = 100us per tick */
/* T = (Prescale/clock) * (countmax) = (8 / 16,000,000) * (256 - 56) = 0.1ms */
// T = (Prescale/clock) * (countmax) = (64 / 16,000,000) * (256 - 0) = 1ms 
ISR(TIMER0_OVF_vect) { 	/* use it as global clock : (counter value/10) = ms */
	TCNT0 = 0;
	if(toggle){
		PORTD |= 0x04;
		toggle = 0;
	}
	else{
		PORTD &= ~(0x04);
		toggle = 1;
	}
	P2CAN++;		/* It will overflow to zero after reached 65535 */
}
// ----------------------------------------------------------------------------
void InitTimerInput(void) {

	/* First set the GlobalClock in timer 0 */
	TCNT0 = 0;		
	TCCR0B = (1 << CS01) | (1 << CS00);	// Use prescaler 64
	TIMSK0 = (1 << TOIE0);				// enable timer 0 overflow interrupt 
}
메인 함수
// ----------------------------------------------------------------------------
int main(void){
	int no_message;
	
	canMsgIndex = 0;
	InitTimerInput();

	//uart_init(UART_BAUD_SELECT(9600UL, F_CPU));	// Initialize UART
	//uart_init();
	sei(); 							// Enable interrupts
	LCDinit();
	DDRD |= 0x04;
	PORTD |= 0x04;
	DDRC &= ~((1< 6)	menu = 0;
			LCDputsXY(0, 1, LCD_Menu[menu]);
		}
		if(KEY2_DOWN){
			_delay_ms(50);
            if(KEY2_DOWN){
				if(menu != 5 || menu != 6){
					_delay_ms(250);
					OBD_INFO(menu, OBD_data);
				}
			}
		}
		switch(menu){
			case 0:
			case 5:
			case 6:
				_delay_ms(250);
				OBD_INFO(menu, OBD_data);
				break;
			default:
				break;
		}
	}
}
주요 기능별로 처리하는 루틴
// ----------------------------------------------------------------------------
void OBD_INFO(int menu, char *buffer){

	switch(menu){
		case 0:
			OBD_INFO_TYPE(buffer);
			break;
		case 1:			
			OBD_INFO_CDTC(buffer);
			break;
		case 2:
			OBD_INFO_PDTC(buffer);
			break;
		case 3:
			OBD_PERM_DTC(buffer);
			break;			
		case 4:
			OBD_DTC_ERASE(buffer);
			break;
		case 5:
			OBD_DATA_FAST(buffer);
			break;	
		case 6:
			OBD_DATA_SLOW(buffer);
			break;	
	}
}
각 센서정보를 요청해서 처리함
// ----------------------------------------------------------------------------
void OBD_DATA_FAST(char *buffer){
	float engine_data; 
	int no_message;
	
	can_mT = Mode01;
	can_mT.data[2] = Mode01REQ[idx++];// Message sent in 'GetCANmsg()'
	idx = idx % 4;
	no_message = GetCANmsg();	// Send & Get reply to my message
	sprintf(buffer,"P2=%2dms", P2CAN);
	LCDputsXY(8, 0, buffer);
	if(no_message == -1)	return;
	//if(can_mR.data[2] != Mode01REQ[i])	continue;
	// Detailes at http://en.wikipedia.org/wiki/OBD-II_PIDs
	switch(can_mR.data[2]){	
		case ENGINE_RPM: 	// ((A*256)+B)/4    [RPM]
			engine_data = can_mR.data[3]*64 + can_mR.data[4]/4;
			sprintf(buffer,"RPM=%04d", (int)engine_data);
			LCDputsXY(0, 0, buffer);
			break;
		case O2_VOLTAGE:	// A * 0.005, Trim at B => (B-128) * 100/128 
			engine_data = can_mR.data[3]*0.005;
			//Str2Float(engine_data, 2, 1, buffer);
			sprintf(buffer,"O2=%1.3fV ", (double)engine_data);
			LCDputsXY(8, 0, buffer);
			break;
		case IG_ANGLE: 	// (A-128)*0.5 deg
			engine_data =  (can_mR.data[3]-128)*0.5;
			//Str2Float(engine_data, 2, 1, buffer);
			sprintf(buffer,"IG=%2.1f ", (double)engine_data);
			LCDputsXY(0, 1, buffer);
			break;	 		// (if B=0xFF, sensor is not used in trim calc)
		case THROTTLE:		// Throttle Position
			engine_data = (can_mR.data[3]*100/255);
			sprintf(buffer,"TVO=%d%%",(int) engine_data);
			LCDputsXY(8, 1, buffer);
			break;
	}

}
// ----------------------------------------------------------------------------
void OBD_DATA_SLOW(char *buffer){
	float engine_data; 
	int no_message;

	can_mT = Mode01;
	can_mT.data[2] = Mode01REQ[idx+4];// Message sent in 'GetCANmsg()'
	idx++;
	idx = idx % 4;
	no_message = GetCANmsg();	// Send & Get reply to my message
	if(no_message == -1)	return;
	//if(can_mR.data[2] != Mode01REQ[i])	continue;
	// Detailes at http://en.wikipedia.org/wiki/OBD-II_PIDs
	switch(can_mR.data[2]){	
		case COOLANT_TEMP: 	// A-40  [degree C]
			engine_data =  can_mR.data[3] - 40;
			sprintf(buffer,"TCO=%3dc",(int) engine_data);
			LCDputsXY(0, 0, buffer);
			break;
		case VOLTBATT:
			engine_data = can_mR.data[3] * 0.256 + can_mR.data[4]*.001;
			//Str2Float(engine_data, 2, 1, buffer);
			sprintf(buffer,"VB=%2.1fV", (double)engine_data);
			LCDputsXY(8, 0, buffer);
			break;	
		case VEHICLE_SPEED: // A  [km]
			engine_data =  can_mR.data[3];
			sprintf(buffer,"VS=%3dkm",(int) engine_data);
			LCDputsXY(0, 1, buffer);			
			break;			
		case FUELTRIM: // 
			engine_data =  can_mR.data[3]-128;
			sprintf(buffer,"TRIM=%3d %%",(int) engine_data);
			LCDputsXY(8, 1, buffer);			
			break;		
	}

}
// ----------------------------------------------------------------------------
void OBD_INFO_TYPE(char *buffer){
	int i = 0;
	
	can_mT = Mode01;
	can_mT.data[2] = OBDTYPE;
	LCDputsXY(0, 0, "OBDtype=");
	while(i < 4){
		i++;
		int no_message = GetCANmsg();	// Send & Get reply to my message
		if(no_message == -1)	continue;
		//if(no_message == 1){
		if((can_mT.data[1]+0x40) != can_mR.data[1])	continue;
		
		if(can_mR.data[3] <= 9 && can_mR.data[3] != 0){
			LCDputsXY(8, 0, OBDtype[(can_mR.data[3]-1)]);
		}else if(can_mR.data[3] == 0x1E){
			LCDputsXY(8, 0, "KOBD");
		}else{
			sprintf(buffer,"%2d", can_mR.data[3]);
			LCDputsXY(8, 0, buffer);
		}
		can_mT = Mode01;
		can_mT.data[2] = DTCMIL;

		no_message = GetCANmsg();	// Send & Get reply to my message
		if(no_message == -1)	continue;
		//if(no_message == 1){
	/*
		if((can_mT.data[1]+0x40) != can_mR.data[1]){
			sprintf(buffer,"%3x:%02x%02x%02x   ",(int)can_mR.id,
				(int)can_mR.data[1],can_mR.data[2],can_mR.data[3]);
			LCDputsXY(4, 1, buffer);	
			return;	// Only in case SF -> ECU reply 'mode + 0x40'
		}
	*/	
		if((can_mT.data[1]+0x40) != can_mR.data[1])	continue;
		if(can_mR.data[3] & 0x80)
			sprintf(buffer,"MIL=ON  DTCs%02d ",(can_mR.data[3]-0x80));
		else	
			sprintf(buffer,"MIL=OFF DTCn%02d ",can_mR.data[3]);
		LCDputsXY(0, 1, buffer);
		return;
	}
}
// ----------------------------------------------------------------------------
void OBD_INFO_PDTC(char *buffer){
	
	can_mT = DTCreq;
	can_mT.data[1] = MODE07;
	int no_message = GetCANmsg();	// Send & Get reply to my message
	if(no_message == -1)	return;
	if((can_mM[0].data[0] & 0xF0) != 0x10){			// In case of Single Frame
		sprintf(buffer,"M07n=%2d:%02X%02X%02X%02X", can_mR.data[2],
			can_mR.data[3],can_mR.data[4],can_mR.data[5],can_mR.data[6]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%3X:%02X%02X%02X%02X",(int)can_mR.id,
			(int)can_mR.data[0],can_mR.data[1],can_mR.data[2],can_mR.data[3]);
		LCDputsXY(0, 1, buffer);	
	}else{
		sprintf(buffer,"M07n=%2d:%02X%02X%02X%02X", (int)can_mM[0].data[3],
			(int)can_mM[0].data[4],can_mM[0].data[5],can_mM[0].data[6],
			can_mM[0].data[7]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%02X%02X%02X%02X%02X%02X%02X%02X", can_mM[1].data[1],
			can_mM[1].data[2],can_mM[1].data[3],can_mM[1].data[4],
			can_mM[1].data[5],can_mM[1].data[6],
			can_mM[1].data[7],can_mM[2].data[1]);
		LCDputsXY(0, 1, buffer);
	}
}
새로 추가된 법규 요청항목 - 영구고장코드
// ----------------------------------------------------------------------------
void OBD_PERM_DTC(char *buffer){
	
	can_mT = DTCreq;
	can_mT.data[1] = 0x0A;
	int no_message = GetCANmsg();			// Send & Get reply to my message
/*	
	sprintf(buffer,"%3X:%02X%02X%02X%02X%02X",(int)can_mR.id,can_mR.data[0],
		can_mR.data[1],can_mR.data[2],can_mR.data[3],can_mT.data[4]);
	LCDputsXY(0, 1, buffer);
*/
	if(no_message == -1){
		LCDputsXY(0, 0, "No Perm DTC Supt");		
		return;
	}
	if((can_mM[0].data[0] & 0xF0) != 0x10){	// In case of Single Frame
		sprintf(buffer,"M0An=%2d:%02X%02X%02X%02X", can_mR.data[2],
			can_mR.data[3],can_mR.data[4],can_mR.data[5],can_mR.data[6]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%3X:%02X%02X%02X%02X",(int)can_mR.id,
			(int)can_mR.data[0],can_mR.data[1],can_mR.data[2],can_mR.data[3]);
		LCDputsXY(0, 1, buffer);	
	}else{
		sprintf(buffer,"M0An=%2d:%02X%02X%02X%02X", (int)can_mM[0].data[3],
			(int)can_mM[0].data[4],can_mM[0].data[5],can_mM[0].data[6],
			can_mM[0].data[7]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%02X%02X%02X%02X%02X%02X%02X%02X", can_mM[1].data[1],
			can_mM[1].data[2],can_mM[1].data[3],can_mM[1].data[4],
			can_mM[1].data[5],can_mM[1].data[6],
			can_mM[1].data[7],can_mM[2].data[1]);
		LCDputsXY(0, 1, buffer);
	}
}
확인된 고장코드 읽기
// ----------------------------------------------------------------------------
void OBD_INFO_CDTC(char *buffer){
	
	can_mT = DTCreq;
	can_mT.data[1] = MODE03;
	int no_message = GetCANmsg();			// Send & Get reply to my message
/*	
	sprintf(buffer,"%3X:%02X%02X%02X%02X%02X",(int)can_mR.id,can_mR.data[0],
		can_mR.data[1],can_mR.data[2],can_mR.data[3],can_mT.data[4]);
	LCDputsXY(0, 1, buffer);
*/
	if(no_message == -1)	return;
	if((can_mM[0].data[0] & 0xF0) != 0x10){	// In case of Single Frame
		sprintf(buffer,"M03n=%2d:%02X%02X%02X%02X", can_mR.data[2],
			can_mR.data[3],can_mR.data[4],can_mR.data[5],can_mR.data[6]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%3X:%02X%02X%02X%02X",(int)can_mR.id,
			(int)can_mR.data[0],can_mR.data[1],can_mR.data[2],can_mR.data[3]);
		LCDputsXY(0, 1, buffer);	
	}else{
		sprintf(buffer,"M03n=%2d:%02X%02X%02X%02X", (int)can_mM[0].data[3],
			(int)can_mM[0].data[4],can_mM[0].data[5],can_mM[0].data[6],
			can_mM[0].data[7]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%02X%02X%02X%02X%02X%02X%02X%02X", can_mM[1].data[1],
			can_mM[1].data[2],can_mM[1].data[3],can_mM[1].data[4],
			can_mM[1].data[5],can_mM[1].data[6],
			can_mM[1].data[7],can_mM[2].data[1]);
		LCDputsXY(0, 1, buffer);
	}
}
// ----------------------------------------------------------------------------
void OBD_DTC_ERASE(char *buffer){
	
	can_mT = DTCreq;
	can_mT.data[1] = MODE04;
	int no_message = GetCANmsg();	// Send & Get reply to my message
	if(no_message == -1)	return;
	//if(no_message == 1){
	if((can_mT.data[1]+0x40) != can_mR.data[1]){
		sprintf(buffer,"WrongPID:%02x%02x%02x",
			(int)can_mR.data[1],can_mR.data[2],can_mR.data[3]);
		LCDputsXY(0, 1, buffer);
		return;	// Only in case SF -> ECU reply 'mode + 0x40'
	}
	else if(can_mR.data[1] == 0x44){
		sprintf(buffer,"Erased:%02x",(int)can_mR.data[1]);
		LCDputsXY(0, 0, buffer);
		sprintf(buffer,"%3X:%02X%02X%02X%02X",(int)can_mR.id,
			(int)can_mR.data[1],can_mR.data[2],can_mR.data[3],can_mR.data[4]);
		LCDputsXY(0, 1, buffer);	
	}
}


중요함수 - CAN 메세지를 보내고 필요한 응답을 받아 되돌려줌

// ----------------------------------------------------------------------------
int GetCANmsg(void){
	uint8_t Block2Get = 0, FrameType;
	can_t *MsgIndexPtr;
	
	canMsgIndex = 1;	// As '0' is used for the First Frame
	MsgIndexPtr = &can_mM[0];
	can_send_message(&can_mT);
	P2CAN = 0;
	while(1){
		//sprintf(OBD_data,"%2d", loop);
		//LCDputsXY(14, 1, OBD_data);		
		if(can_check_message()) {			// Wait until we receive a message
			if(can_get_message(&can_mR)) {	// Read message from MCP2515
				//As CAN filter is used, no need to check the id here !
				if(can_mR.id != PID_REPLY)
					continue;	// return ONLY if not MF & not my id
				// verify is the msg correct or SF/FF/CF/FC
				FrameType = (can_mR.data[0] & 0xF0);
				if(FrameType == 0x10){		// message is First frame
					can_send_message(&FLW_CON);	
					//ByteNo = no of bytes to be received
					//ByteNo = (can_mR.data[0]&0x0F)*256 + can_mR.data[1] - 4;
					//Block2Get = ByteNo/7;
					//if(ByteNo%7 > 0)	Block2Get++;
					Block2Get = 2;
					can_mM[0] = can_mR;
					//sprintf(OBD_data,"%3X:%02X FF[%2d] ",(int)can_mR.id,
					//	(int)can_mR.data[0],(can_mR.data[0]&0x0F));
					//LCDputsXY(2, 1,OBD_data);
					continue;
				}else if(FrameType == 0x20){// Consecutive message
					can_mM[canMsgIndex++] = can_mR;
					Block2Get--;
					//if(canMsgIndex == MaxCANmsg)	// FC should be sent @ BS
					//	canMsgIndex = MaxCANmsg-1;	// at every BlockSize
					// SN is started from 1 NOT 0 as FF is the one, then 0..F
					//if((can_mR.data[0]&0x0F) != (canMsgIndex%16)){
					//	canMsgIndex = 0;
					//	can_send_message(&FLW_CON);	
					//	continue;			// because SN is wrong
					//}
					//sprintf(OBD_data,"%3X:%02X CF[%2d] ",(int)can_mR.id,
					//	(int)can_mR.data[0],(can_mR.data[0]&0x0F));
					//LCDputsXY(2, 1,OBD_data);
				}else if(FrameType == 0x00){// Single frame	
					//for(uint8_t k=0;k<8;k++)	
					//	can_mM[0].data[k] = can_mR.data[k];
					can_mM[0] = can_mR;
					//sprintf(OBD_data,"%3X:%02X SN[%2d] ",(int)can_mR.id,
					//	(int)can_mR.data[0],(can_mR.data[0]&0x0F));
					//LCDputsXY(2, 1,OBD_data);
						return 1;
				}else if(FrameType == 0x30){
					massageType = 3;		// Flow Control
					LCDputsXY(12, 1, "FC");	
					return 0;
				}
				else
					LCDputsXY(12, 1, "Wo");		
				if(canMsgIndex >= MaxCANmsg)
					return MaxCANmsg-1;		// return No of message get
				else if(Block2Get <= 0)
					return canMsgIndex-1;
			}
		}
		if(P2CAN > 70)	return -1;			// 70 ms  elapsed
	}
}
// ----------------------------------------------------------------------------
/*
void DisplayOBDdata(char * buffer){
	float engine_data; 

	sprintf(buffer,"%3x:%02x%02x%02x%02x  ",(int)can_mR.id,
		(int)can_mR.data[0],can_mR.data[1],can_mR.data[2],can_mR.data[3]);
	LCDputsXY(2, 0, buffer);

	switch(can_mR.data[2]){	// Details @ http://en.wikipedia.org/wiki/OBD-II_PIDs
		case ENGINE_RPM: 	//   ((A*256)+B)/4    [RPM]
			engine_data = can_mR.data[3]*64 + can_mR.data[4]/4;
			sprintf(buffer,"%04d", (int)engine_data);
			LCDputsXY(2, 1, buffer);
			break;
		case COOLANT_TEMP: 	// A-40  [degree C]
			engine_data =  can_mR.data[3] - 40;
			sprintf(buffer,"%3dC",(int) engine_data);
			LCDputsXY(6, 1, buffer);
			break;
		case VOLTBATT:
			engine_data = can_mR.data[3] * 0.256 + can_mR.data[4]*.001;
			//Str2Float(engine_data, 2, 1, buffer);
			sprintf(buffer,"%2.1fV", (double)engine_data);
			LCDputsXY(10, 1, buffer);
			break;
		case O2_VOLTAGE:	// A * 0.005, Trim at B => (B-128) * 100/128 
			engine_data = can_mR.data[3]*0.005;
			//Str2Float(engine_data, 2, 1, buffer);
			sprintf(buffer,"%1.3f", (double)engine_data);
			LCDputsXY(12, 0, buffer);
			break;
		case VEHICLE_SPEED: // A  [km]
			engine_data =  can_mR.data[3];
			sprintf(buffer,"%3dkm",(int) engine_data);
			LCDputsXY(11, 1, buffer);			
			break;
		case THROTTLE:		// Throttle Position
			engine_data = (can_mR.data[3]*100/255);
			sprintf(buffer,"%d %% ",(int) engine_data);
			LCDputsXY(0, 1, buffer);
			break;
	} 
}
*/
/*
// ----------------------------------------------------------------------------
void disp_can_message_LCD(can_t *message){
	uint8_t length = message->header.length;
	char buffer[21];
	
	sprintf(buffer,"id: %3x\n",message->id);	LCDputsXY(0, 0, buffer);
	sprintf(buffer,"len:%2d\n",length);			LCDputsXY(7, 0, buffer);
	sprintf(buffer,"rtr: %d\n",message->header.rtr);	LCDputsXY(15,0, buffer);
	
	if (!message->header.rtr) {
		LCDputsXY(0, 1, "data:");
		for (uint8_t i = 0; i < length; i++) {
			sprintf(buffer,"%2x ", message->data[i]);
			LCDputsXY(5+i*2, 1, buffer);
		}
	}
}
// ----------------------------------------------------------------------------
void print_can_message(can_t *message){
	uint8_t length = message->header.length;
	
	printf("id: %3x\n", message->id);
	printf("length: %d\n", length);
	printf("rtr: %d\n", message->header.rtr);
	
	if (!message->header.rtr) {
		printf("data:  ");
		
		for (uint8_t i = 0; i < length; i++) {
			printf("%2x ", message->data[i]);
		}
		printf("\n");
	}
}
// ----------------------------------------------------------------------------
void RS232_can_message(can_t *m){

	//LCDputsXY(2, 1, "Sending 2 PC");
	sprintf(TXbuff,"id=%3x L%d R%1d %02X%02X %02X%02X %02X%02X %02X%02X\n",
		m->id,m->header.length,m->header.rtr,m->data[0],m->data[1],m->data[2],
		m->data[3],m->data[4],m->data[5],m->data[6],m->data[7]);
	uart_puts(TXbuff);
}
*/
// ----------------------------------------------------------------------------
/*
prog_uint8_t can_filter[] = {		// Receive only 11 bit ID
	// Group 0
	MCP2515_FILTER(0),				// Filter 0
	MCP2515_FILTER(0),				// Filter 1
	
	// Group 1
	MCP2515_FILTER(0),				// Filter 2
	MCP2515_FILTER(0),				// Filter 3
	MCP2515_FILTER(0),				// Filter 4
	MCP2515_FILTER(0),				// Filter 5
	
	MCP2515_FILTER(0),				// Mask 0 (for group 0)
	MCP2515_FILTER(0),				// Mask 1 (for group 1)
};
*/
// ----------------------------------------------------------------------------
/*
void Send_CAN_msg(can_t *message){			// Not use it to reduce overhead

	can_send_message(message);			// Send a Message
		//LCDputsXY(0, 1, "Msg Sent to CAN!");
		//LCDputsXY(0, 1, "CanTsend message");
	printf("TX :id=%08x - %02x %02x %02x %02x %02x %02x %02x %02x \n", message->id,
		message->data[0],message->data[1],message->data[2],message->data[3],
		message->data[4],message->data[5],message->data[6],message->data[7]);

}
*/
// ----------------------------------------------------------------------------



블로그 이미지

DIYworld

,