0% found this document useful (0 votes)
12 views12 pages

1wire2wayz Bidirectional

Download as txt, pdf, or txt
Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1/ 12

//************************************************************

// Auther: Luke Skaff


// EET 480 - Senior Project
// Spring 2007
// Automotive engine computer (ECU) diagnostic interface
// Compiled in WinAVR
//************************************************************

//***********************************************************
// Program discription
// Sends Mode 1 command set to ECU
// Stores Mode 1 data
// Cauclates disired values from stored data
// Outputs calculated data to LCD
//***********************************************************

//***********************************************************
// For more information on project visit:
// http://www.lukeskaff.com
//***********************************************************

// Dependent librarys
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <util/delay.h>

#define F_CPU 19660800UL // CPU crystal speed 19.6608Mhz


#define FOSC 19660800UL // CPU crystal speed 19.6608Mhz
#define BAUD 8192UL // 8192 Baud rate

// ------ PORT & PIN Definitions -------


#define LCD_PORT PORTC //8-BIT LCD data lines
#define RS_PORT PORTD //Port RS line in on
#define RS 7 //Pin # of RS line
#define E_PORT PORTD //Port Enable line in on
#define E 6 //Pin # of Enable line

#define RXcontrol 5 //Pin # RX enable transistor

#define DataM 0xFF

#define Bit_Set(port,bit_num) (port = port | (0x01 << bit_num))


#define Bit_Clear(port,bit_num) (port = port & ~(0x01 << bit_num))

#define DataStreamSize 63 //Size of receiving data stream


#define CarDataSize 22 //Size of ASCII car data

unsigned char DataStream[DataStreamSize];


#define Def_Offset 3
#define DEF_ERROR1 3 + Def_Offset
#define DEF_ERROR2 4 + Def_Offset
#define DEF_ERROR3 5 + Def_Offset
#define DEF_ERROR4 6 + Def_Offset
#define DEF_ERROR5 7 + Def_Offset
#define DEF_CTS 8 + Def_Offset
#define DEF_RPM 11 + Def_Offset
#define DEF_MPH 14 + Def_Offset
#define DEF_BLM 20 + Def_Offset
#define DEF_BLM_CELL 21 + Def_Offset
#define DEF_STPS 24 + Def_Offset // Scaled Throttle Position Sensor
#define DEF_MAP 26 + Def_Offset // volts = N x (5 / 255)
// KPa = N * .369 + 10.354
#define DEF_BATT 34 + Def_Offset // volts = N / 10

unsigned char CarData_ASCII[CarDataSize];


#define DATA_CTS_2 0 //COOLANT TEMPERATURE celcius
#define DATA_CTS_1 1
#define DATA_TPS_v 2 //TPS volts

#define DATA_RPM_4 3
#define DATA_RPM_3 4
#define DATA_RPM_2 5
#define DATA_RPM_1 6

#define DATA_MPH_3 7
#define DATA_MPH_2 8
#define DATA_MPH_1 9

#define DATA_BLM_3 10
#define DATA_BLM_2 20
#define DATA_BLM_1 21

#define DATA_BLM_CELL 11

#define DATA_TPS_3 12
#define DATA_TPS_2 13
#define DATA_TPS_1 14

#define DATA_MAP_3 15
#define DATA_MAP_2 16
#define DATA_MAP_1 17

#define DATA_BATT_2 18
#define DATA_BATT_1 19

//ECU trouble codes lookup table


const unsigned char PROGMEM ErrorCode_Table[]=
{
23,22,21,16,15,14,13,12,
35,34,33,32,31,26,25,24,
51,46,45,44,43,42,41,36,
63,62,61,56,55,54,53,52,
00,00,00,00,00,66,65,64
};
//Function prototypes
void LCD_Initialize(void);
void LCD_D_Write(unsigned char);
void LCD_I_Write(unsigned char);
void LCD_Delay(void);
void USART_init(void);
void Binary_Out(unsigned char);
void Get_Car_Data(void);
//void HEX_to_ASCII(unsigned int, unsigned char &, unsigned char &, unsigned char
&, unsigned char &);

// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// ------------------------ Program Code Starts Here ----------------------------
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------

//******************************************************************
//* Function: LCD_Initialize *
//* Initialize LCD *
//******************************************************************
void LCD_Initialize(void)
{
Bit_Clear(E_PORT,E); // Bring enable pin low

LCD_I_Write(0x38); // 8-Bit data transfer mode


LCD_I_Write(0x0C); // Turn display on, No cursor, No blinking
LCD_I_Write(0x01); // Display clear, Restore to upper left position
LCD_I_Write(0x06); // Address counter increment after each display
LCD_I_Write(0x02); // Set address counter to zero, move cursor to home
}

//******************************************************************
//* Function: LCD_Write *
//* Output data passed in, in data var. to LCD *
//* - Commented out, not used anymore - *
//******************************************************************
/*void LCD_Write(unsigned char data, unsigned char select)
{
Bit_Set(E_PORT,E);

if(select==0xFF)
Bit_Set(RS_PORT,RS); //LCD Data mode
else
Bit_Clear(RS_PORT,RS); //LCD Instruction mode

LCD_PORT=data;

_delay_ms(1);
Bit_Clear(E_PORT,E);
_delay_ms(1);

}
*/

//******************************************************************
//* Function: LCD_D_Write *
//* Output data passed in, in data var. to LCD *
//******************************************************************
void LCD_D_Write(unsigned char data)
{
Bit_Set(E_PORT,E);
Bit_Set(RS_PORT,RS); //LCD Data mode

LCD_PORT=data;

LCD_Delay();
Bit_Clear(E_PORT,E);
LCD_Delay();

//******************************************************************
//* Function: LCD_I_Write *
//* Output data passed in, in data var. to LCD *
//******************************************************************
void LCD_I_Write(unsigned char data)
{
Bit_Set(E_PORT,E);
Bit_Clear(RS_PORT,RS); //LCD Instruction mode

LCD_PORT=data;

LCD_Delay();
Bit_Clear(E_PORT,E);
LCD_Delay();

//******************************************************************
//* Function: LCD_Delay *
//* Relay function used for LCD communication *
//******************************************************************
void LCD_Delay(void)
{
_delay_ms(1);
}

//******************************************************************
//* Function: USART_init *
//* Enable and Initialize UART *
//******************************************************************
void USART_init(void)
{
// Set the USART baudrate registers for 8192, UBRR=149
UBRR0H = 0;
UBRR0L = 149; // Set for 4800 for PC testing
//255 = 4800 baud
//149 = 8192 buad
//127 = 9600 baud

//UCSRnA - USART Control and Status Register A


// Enable 2x speed change, 0=16 divider 1=8 divider
/*
Bit 7 MSB
R RXCn -> USART Receive Complete
0 TXCn -> TXCn: USART Transmit Complete
R UDREn -> USART Data Register Empty
R FEn -> Frame Error
R DORn -> Data OverRun
R UPEn -> USART Parity Error
0 U2Xn -> Double the USART Transmission Speed, 0=16 divider 1=8 divider
0 MPCMn -> Multi-processor Communication Mode
Bit 0 LSB
*/
UCSR0A = (0<<U2X0);

// UCSRnB - USART Control and Status Register n B


// Enable receiver
/*
Bit 7 MSB
RXCIE0 = 0 Receive Interrupt disabled
TXCIE0 = 0 Transmit Interrupt disabled
UDRIE0 = 0 Interupt disabled
RXEN0 = 1 Receive enabled
TXEN0 = 1 Transmit enabled
UCSZ02 = 0 8-bit mode
RXB80 = 0 9'th RX data bit when using 9-bit UART
TXB80 = 0 9'th TX data bit when using 9-bit UART
Bit 0 LSB
*/
UCSR0B =(1<<RXEN0)|(1<<TXEN0);

// UCSRnC - USART Control and Status Register n C


// Set the USART to asynchronous at 8 bits no parity and 1 stop bits
/*
Bit 7 MSB
0 UMSEL01 |
0 UMSEL00 |-> Async
0 UPM01 |
0 UPM00 |-> No parity
0 USBS0 -> 1 stop bits;
1 UCSZ01 |
1 UCSZ00 |-> 8-bit
0 UCPOL0 -> Reciving data sampled on fallign edge
Bit 0 LSB
*/
UCSR0C =(0<<UMSEL01)|(0<<UMSEL00)|(0<<UPM01)|(0<<UPM00)|(0<<USBS0)|
(1<<UCSZ01)|(1<<UCSZ00)|(0<<UCPOL0);

//******************************************************************
//* Function: Binary_Out *
//* Outputs any passed in variable to LCD in binary *
//* - Used for debugging - *
//* - Commented out, not used in final working code - *
//******************************************************************
/*
void Out_Binary(unsigned char data)
{
for(unsigned char bitn = 8 ; bitn > 0 ; bitn--)
{
if( data & ( 1 << (bitn-1) ) )
LCD_Write(0x31,0xFF); // Output 1 to LCD
else
LCD_Write(0x30,0xFF); // Output 0 to LCD
}
}
*/

//*******************************************************************
//* Function: USART_Receive *
//* Waits for incoming data on USART then returns it to the calling *
//* function *
//* - Commented out, not used in final working code - *
//*******************************************************************
/*
unsigned char USART_Receive(void)
{
// Wait for data to be received
while ( !(UCSR0A & (1<<RXC0)) );

// Get and return received data from buffer


return UDR0;
}
*/

//******************************************************************
//* Function: USART_Transmit *
//* Transmit data *
//* datastream array until array is full *
//******************************************************************
void USART_Transmit(unsigned char data)
{
// Wait for empty transmit buffer
while ( !( UCSR0A & (1<<UDRE0)) );

// Put data into buffer, sends the data


UDR0 = data;

// Wait for empty transmit buffer


while ( !( UCSR0A & (1<<UDRE0)) );
}

//******************************************************************
//* Function: Get_Car_Data *
//* Waits for incoming data on USART then puts received char into *
//* datastream array until array is full *
//******************************************************************
void Get_Car_Data(void)
{
unsigned int timeout;

Bit_Set(PORTD,RXcontrol); //Lockout recieve pin

//Mode 1 command set


USART_Transmit(0xF4);
USART_Transmit(0x56);
USART_Transmit(0x01);
USART_Transmit(0xB5);

Bit_Clear(PORTD,RXcontrol); //Open up recieve pin

for(unsigned char i = 0 ; i < DataStreamSize ; i++)


{
timeout=0; // Reset timeout to zero

// Wait for data to be received if data not recived in timout period


// then exit loop
while( !(UCSR0A & (1<<RXC0) ) && (timeout < 12000) )
{
timeout++;
}

// Get and return received data from buffer


if(timeout == 12000)
DataStream[i]=0; // If timeout load 0 into datastream value
else
DataStream[i]=UDR0; // Otherwise load recieved value
}

Bit_Set(PORTD,RXcontrol); //Lockout recieve pin


}

//******************************************************************
//* Function: Flash_LEDs *
//* - Used for debugging - *
//* - Commented out, not used in final working code - *
//******************************************************************
/*
void Flash_LEDs()
{
for(int i=0 ; i<20 ; i++ )
{
PORTA=0x00;
_delay_ms(1000);
PORTA=0xFF;
_delay_ms(1000);
}
}
*/

//******************************************************************
//* Function: HEX_to_ASCII *
//* Convert inputed 8-bit HEX data to 4 ANSII digits for LCD *
//******************************************************************
void HEXtoASCII(unsigned int Hex_Input,unsigned char *digit4, unsigned char
*digit3, unsigned char *digit2, unsigned char *digit1)
{

// Clear varaibles
*digit4 = 0x00;
*digit3 = 0x00;
*digit2 = 0x00;
*digit1 = 0x00;

while(Hex_Input >= 1000)


{
Hex_Input=Hex_Input - 1000;
*digit4 = *digit4 + 0x01;
}

while(Hex_Input >= 100)


{
Hex_Input=Hex_Input - 100;
*digit3 = *digit3 + 0x01;
}

while(Hex_Input >= 10)


{
Hex_Input=Hex_Input - 10;
*digit2 = *digit2 + 0x01;
}

*digit1 = Hex_Input; //remainder

// Convert to ASCII, OR with 0x30 produces ASCII


*digit4 = *digit4 | 0x30;
*digit3 = *digit3 | 0x30;
*digit2 = *digit2 | 0x30;
*digit1 = *digit1 | 0x30;
}

//******************************************************************
//* Function: Calculate_CarData *
//* Convert raw data from data stream to real numbers and put in *
//* ASCII format *
//******************************************************************
void Calculate_CarData()
{
unsigned char ignore;
unsigned int temp;

// Calculate coolant tempature


temp = DataStream[DEF_CTS] * 0.75 - 40;
HEXtoASCII(temp,&ignore, &ignore, &CarData_ASCII[DATA_CTS_2],
&CarData_ASCII[DATA_CTS_1]);

// Calculate RPM
temp = DataStream[DEF_RPM]*25;
HEXtoASCII(temp,&CarData_ASCII[DATA_RPM_4], &CarData_ASCII[DATA_RPM_3],
&CarData_ASCII[DATA_RPM_2], &CarData_ASCII[DATA_RPM_1]);

// Calculate MPH
temp = DataStream[DEF_MPH] / 1;
HEXtoASCII(temp,&ignore, &CarData_ASCII[DATA_MPH_3], &CarData_ASCII[DATA_MPH_2],
&CarData_ASCII[DATA_MPH_1]);

// Calculate Block Learn Multiplier (BLM)


temp = DataStream[DEF_BLM];
HEXtoASCII(temp,&ignore, &CarData_ASCII[DATA_BLM_3], &CarData_ASCII[DATA_BLM_2],
&CarData_ASCII[DATA_BLM_1]);

// Calculate Throttle Position Sensor (TPS) percent


temp = DataStream[DEF_STPS] / 2.56;
HEXtoASCII(temp,&ignore, &CarData_ASCII[DATA_TPS_3], &CarData_ASCII[DATA_TPS_2],
&CarData_ASCII[DATA_TPS_1]);

// Calculate Manifold Air Pressure (MAP)


temp = (DataStream[DEF_MAP] * 0.369) + 10.354;
HEXtoASCII(temp,&ignore, &CarData_ASCII[DATA_MAP_3], &CarData_ASCII[DATA_MAP_2],
&CarData_ASCII[DATA_MAP_1]);

// Calculate Battery voltage


temp = DataStream[DEF_BATT] / 10;
HEXtoASCII(temp,&ignore, &ignore, &CarData_ASCII[DATA_BATT_2],
&CarData_ASCII[DATA_BATT_1]);

//******************************************************************
//* Function: Output_CarData() *
//* Output calcualted car data and trouble codes to LCD *
//******************************************************************
void Output_CarData()
{
unsigned char ignore;
unsigned int ErrorCode;
unsigned char bitn=0;
unsigned char code_2, code_1;
unsigned char error_bit, error_byte;

LCD_I_Write(0x02); // Set address counter to zero, move cursor to home

LCD_D_Write('R');
LCD_D_Write('P');
LCD_D_Write('M');
LCD_D_Write(' ');
LCD_D_Write(CarData_ASCII[DATA_RPM_4]);
LCD_D_Write(CarData_ASCII[DATA_RPM_3]);
LCD_D_Write(CarData_ASCII[DATA_RPM_2]);
LCD_D_Write(CarData_ASCII[DATA_RPM_1]);

LCD_D_Write(' '); //Space


LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space

LCD_D_Write('M');
LCD_D_Write('P');
LCD_D_Write('H');
LCD_D_Write(' ');
LCD_D_Write(CarData_ASCII[DATA_MPH_3]);
LCD_D_Write(CarData_ASCII[DATA_MPH_2]);
LCD_D_Write(CarData_ASCII[DATA_MPH_1]);

LCD_D_Write(' '); //Space


LCD_D_Write(' '); //Space

LCD_D_Write('B');
LCD_D_Write('L');
LCD_D_Write('M');
LCD_D_Write(' ');
LCD_D_Write(CarData_ASCII[DATA_BLM_3]);
LCD_D_Write(CarData_ASCII[DATA_BLM_2]);
LCD_D_Write(CarData_ASCII[DATA_BLM_1]);

LCD_D_Write(' '); //Space


LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space

LCD_D_Write('C');
LCD_D_Write('T');
LCD_D_Write('S');
LCD_D_Write(' ');
LCD_D_Write(CarData_ASCII[DATA_CTS_2]);
LCD_D_Write(CarData_ASCII[DATA_CTS_1]);
LCD_D_Write('C');
LCD_D_Write(' ');

LCD_D_Write(' '); //Space

LCD_D_Write('M');
LCD_D_Write('A');
LCD_D_Write('P');
LCD_D_Write(' ');

LCD_D_Write(CarData_ASCII[DATA_MAP_3]);
LCD_D_Write(CarData_ASCII[DATA_MAP_2]);
LCD_D_Write(CarData_ASCII[DATA_MAP_1]);
LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space
LCD_D_Write(' '); //Space

LCD_D_Write('T');
LCD_D_Write('P');
LCD_D_Write('S');
LCD_D_Write(' ');
LCD_D_Write(CarData_ASCII[DATA_TPS_3]);
LCD_D_Write(CarData_ASCII[DATA_TPS_2]);
LCD_D_Write(CarData_ASCII[DATA_TPS_1]);
LCD_D_Write('%');

LCD_D_Write(' '); //Space

LCD_D_Write('B');
LCD_D_Write('A');
LCD_D_Write('T');
LCD_D_Write('T');
LCD_D_Write(' ');

LCD_D_Write(CarData_ASCII[DATA_BATT_2]);
LCD_D_Write(CarData_ASCII[DATA_BATT_1]);
LCD_D_Write('V');
LCD_D_Write(' ');

LCD_D_Write(' ');
LCD_D_Write(' ');

error_bit=0; //Reset error bit to zero

//*************************
// Check for Trouble Codes
//*************************
for(error_byte = DEF_ERROR1 ; error_byte < DEF_ERROR5 ; error_byte++)
{
for(bitn = 0 ; bitn < 7 ; bitn++)
{
//If error bit in datastream is 1 then ouput trouble code
if(DataStream[error_byte] & ( 1 << (bitn) ) )
{
ErrorCode = (unsigned char)pgm_read_byte(&ErrorCode_Table[error_bit]);

if(ErrorCode != 0) //If error code is 0 ignore trouble code


{
ErrorCode = (unsigned
char)pgm_read_byte(&ErrorCode_Table[error_bit]);

HEXtoASCII(ErrorCode,&ignore, &ignore, &code_2, &code_1);


LCD_D_Write(code_2);
LCD_D_Write(code_1);
LCD_D_Write(' ');
}
}

error_bit = error_bit + 1; //Increment error bit number

}
}

//******************************************************************
//* Function: main *
//* Main control function *
//******************************************************************
int main (void)
{
DDRA = 0xFF; // Configure PORTA as output
DDRC = 0xFF; // Configure PORTC as output
DDRD = (1<<PD1)|(1<<PD5)|(1<<PD6)|(1<<PD7); // Configure PORTD

USART_init(); //Initialize USART


LCD_Initialize(); //Initialize LCD

// Loop forever
while(1)
{
Get_Car_Data();
Calculate_CarData();
Output_CarData();
}

while(1)
;

}// End of main

You might also like