fork download
  1. /*
  2.  * TMAP Sensor Fault Detection for ESD Assignment
  3.  * PIC16F877A, 20MHz Crystal, 8-bit LCD on PORTB
  4.  * A0 = MAP Signal, A1 = Temp Signal
  5.  * Thresholds: <0.2V = Open, >4.8V = Short to Power
  6.  */
  7.  
  8. #define _XTAL_FREQ 20000000
  9. #include <xc.h>
  10.  
  11. // CONFIG bits for 20MHz HS oscillator
  12. #pragma config FOSC = HS // High speed crystal
  13. #pragma config WDTE = OFF // Watchdog off
  14. #pragma config PWRTE = ON // Power-up timer on
  15. #pragma config BOREN = ON // Brown-out reset on
  16. #pragma config LVP = OFF // Low voltage programming off
  17. #pragma config CPD = OFF // Data EEPROM protection off
  18. #pragma config WRT = OFF // Flash write protection off
  19. #pragma config CP = OFF // Code protection off
  20.  
  21. // LCD connections - 8 bit mode on PORTB
  22. #define LCD_PORT PORTB
  23. #define LCD_TRIS TRISB
  24. #define RS RB0 // Register Select
  25. #define EN RB1 // Enable
  26. #define RW RB2 // Read/Write - tied low in hardware
  27.  
  28. // Function prototypes
  29. void LCD_Init(void);
  30. void LCD_Command(unsigned char cmd);
  31. void LCD_Char(unsigned char data);
  32. void LCD_String(const char *str);
  33. void LCD_SetCursor(unsigned char row, unsigned char col);
  34. void ADC_Init(void);
  35. unsigned int ADC_Read(unsigned char channel);
  36. void Delay_ms(unsigned int ms);
  37.  
  38. void main(void) {
  39. unsigned int adc_map, adc_temp;
  40. float volt_map, volt_temp;
  41.  
  42. // Set ports: A0,A1 analog input, rest digital
  43. ADCON1 = 0x80; // Right justified, AN0-AN1 analog, rest digital
  44. TRISA = 0x03; // RA0, RA1 input. Rest output
  45. TRISB = 0x00; // PORTB all output for LCD
  46. PORTB = 0x00;
  47.  
  48. LCD_Init();
  49. ADC_Init();
  50.  
  51. LCD_SetCursor(1,1);
  52. LCD_String("TMAP Sensor Test");
  53. Delay_ms(2000);
  54. LCD_Command(0x01); // Clear
  55.  
  56. while(1) {
  57. // Read ADC: 0-1023 for 0-5V
  58. adc_map = ADC_Read(0); // AN0 = MAP
  59. adc_temp = ADC_Read(1); // AN1 = Temp
  60.  
  61. // Convert to voltage: ADC * 5 / 1023
  62. volt_map = adc_map * 0.004887;
  63. volt_temp = adc_temp * 0.004887;
  64.  
  65. LCD_SetCursor(1,1);
  66.  
  67. // Priority: E01 Connector Open > E02/E03 Short
  68. // E01: Both signals < 0.2V = connector open
  69. if(volt_map < 0.20 && volt_temp < 0.20) {
  70. LCD_String("E01: OPEN CKT ");
  71. LCD_SetCursor(2,1);
  72. LCD_String("Check Connector ");
  73. }
  74. // E02: MAP > 4.8V = Short to power
  75. else if(volt_map > 4.80) {
  76. LCD_String("E02: MAP SHORT ");
  77. LCD_SetCursor(2,1);
  78. LCD_String("MAP=5V ");
  79. LCD_Command(0xC7); // Line 2, pos 7
  80. LCD_Char((adc_map/1000)%10 + '0');
  81. LCD_Char((adc_map/100)%10 + '0');
  82. LCD_Char((adc_map/10)%10 + '0');
  83. LCD_Char(adc_map%10 + '0');
  84. }
  85. // E03: Temp > 4.8V = Short to power
  86. else if(volt_temp > 4.80) {
  87. LCD_String("E03: TEMP SHORT ");
  88. LCD_SetCursor(2,1);
  89. LCD_String("TMP=5V ");
  90. LCD_Command(0xC7);
  91. LCD_Char((adc_temp/1000)%10 + '0');
  92. LCD_Char((adc_temp/100)%10 + '0');
  93. LCD_Char((adc_temp/10)%10 + '0');
  94. LCD_Char(adc_temp%10 + '0');
  95. }
  96. // Normal condition
  97. else {
  98. LCD_String("System OK ");
  99. LCD_SetCursor(2,1);
  100. LCD_String("M:");
  101. LCD_Char((adc_map/1000)%10 + '0');
  102. LCD_Char('.');
  103. LCD_Char(((adc_map*5)/102)%10 + '0');
  104. LCD_String("V T:");
  105. LCD_Char((adc_temp/1000)%10 + '0');
  106. LCD_Char('.');
  107. LCD_Char(((adc_temp*5)/102)%10 + '0');
  108. LCD_String("V ");
  109. }
  110. Delay_ms(300);
  111. }
  112. }
  113.  
  114. void ADC_Init(void) {
  115. ADCON0 = 0x41; // ADC ON, Fosc/16, Channel 0
  116. ADCON1 = 0x80; // Right justified, Vref = Vdd/Vss
  117. }
  118.  
  119. unsigned int ADC_Read(unsigned char channel) {
  120. ADCON0 &= 0xC5; // Clear channel bits
  121. ADCON0 |= channel << 3; // Set channel
  122. Delay_ms(1); // Acquisition time
  123. GO_nDONE = 1; // Start conversion
  124. while(GO_nDONE); // Wait
  125. return ((ADRESH << 8) + ADRESL); // Return 10-bit result
  126. }
  127.  
  128. void LCD_Init(void) {
  129. LCD_TRIS = 0x00; // PORTB output
  130. Delay_ms(20);
  131. LCD_Command(0x38); // 8-bit, 2 line, 5x7
  132. LCD_Command(0x0C); // Display on, cursor off
  133. LCD_Command(0x06); // Auto increment
  134. LCD_Command(0x01); // Clear display
  135. Delay_ms(2);
  136. }
  137.  
  138. void LCD_Command(unsigned char cmd) {
  139. RS = 0; // Command mode
  140. RW = 0; // Write
  141. LCD_PORT = (LCD_PORT & 0x03) | (cmd & 0xFC); // Keep RS,EN, put data
  142. if(cmd & 0x02) RB1 = 1; else RB1 = 0; // D1
  143. if(cmd & 0x01) RB0 = 1; else RB0 = 0; // D0
  144. EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
  145. LCD_PORT = cmd; // Send full byte
  146. EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
  147. }
  148.  
  149. void LCD_Char(unsigned char data) {
  150. RS = 1; // Data mode
  151. RW = 0;
  152. LCD_PORT = data;
  153. EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
  154. }
  155.  
  156. void LCD_String(const char *str) {
  157. while(*str) LCD_Char(*str++);
  158. }
  159.  
  160. void LCD_SetCursor(unsigned char row, unsigned char col) {
  161. if(row == 1) LCD_Command(0x80 + (col-1));
  162. else LCD_Command(0xC0 + (col-1));
  163. }
  164.  
  165. void Delay_ms(unsigned int ms) {
  166. while(ms--) __delay_ms(1);
  167. }
  168.  
Success #stdin #stdout 0.03s 25552KB
stdin
Standard input is empty
stdout
/*
 * TMAP Sensor Fault Detection for ESD Assignment
 * PIC16F877A, 20MHz Crystal, 8-bit LCD on PORTB
 * A0 = MAP Signal, A1 = Temp Signal
 * Thresholds: <0.2V = Open, >4.8V = Short to Power
 */
 
#define _XTAL_FREQ 20000000
#include <xc.h>
 
// CONFIG bits for 20MHz HS oscillator
#pragma config FOSC = HS        // High speed crystal
#pragma config WDTE = OFF       // Watchdog off
#pragma config PWRTE = ON       // Power-up timer on
#pragma config BOREN = ON       // Brown-out reset on
#pragma config LVP = OFF        // Low voltage programming off
#pragma config CPD = OFF        // Data EEPROM protection off
#pragma config WRT = OFF        // Flash write protection off
#pragma config CP = OFF         // Code protection off
 
// LCD connections - 8 bit mode on PORTB
#define LCD_PORT PORTB
#define LCD_TRIS TRISB
#define RS RB0  // Register Select
#define EN RB1  // Enable
#define RW RB2  // Read/Write - tied low in hardware
 
// Function prototypes
void LCD_Init(void);
void LCD_Command(unsigned char cmd);
void LCD_Char(unsigned char data);
void LCD_String(const char *str);
void LCD_SetCursor(unsigned char row, unsigned char col);
void ADC_Init(void);
unsigned int ADC_Read(unsigned char channel);
void Delay_ms(unsigned int ms);
 
void main(void) {
    unsigned int adc_map, adc_temp;
    float volt_map, volt_temp;
    
    // Set ports: A0,A1 analog input, rest digital
    ADCON1 = 0x80;  // Right justified, AN0-AN1 analog, rest digital
    TRISA = 0x03;   // RA0, RA1 input. Rest output
    TRISB = 0x00;   // PORTB all output for LCD
    PORTB = 0x00;
    
    LCD_Init();
    ADC_Init();
    
    LCD_SetCursor(1,1);
    LCD_String("TMAP Sensor Test");
    Delay_ms(2000);
    LCD_Command(0x01); // Clear
    
    while(1) {
        // Read ADC: 0-1023 for 0-5V
        adc_map = ADC_Read(0);   // AN0 = MAP
        adc_temp = ADC_Read(1);  // AN1 = Temp
        
        // Convert to voltage: ADC * 5 / 1023
        volt_map = adc_map * 0.004887;
        volt_temp = adc_temp * 0.004887;
        
        LCD_SetCursor(1,1);
        
        // Priority: E01 Connector Open > E02/E03 Short
        // E01: Both signals < 0.2V = connector open
        if(volt_map < 0.20 && volt_temp < 0.20) {
            LCD_String("E01: OPEN CKT   ");
            LCD_SetCursor(2,1);
            LCD_String("Check Connector ");
        }
        // E02: MAP > 4.8V = Short to power
        else if(volt_map > 4.80) {
            LCD_String("E02: MAP SHORT  ");
            LCD_SetCursor(2,1);
            LCD_String("MAP=5V ");
            LCD_Command(0xC7); // Line 2, pos 7
            LCD_Char((adc_map/1000)%10 + '0');
            LCD_Char((adc_map/100)%10 + '0');
            LCD_Char((adc_map/10)%10 + '0');
            LCD_Char(adc_map%10 + '0');
        }
        // E03: Temp > 4.8V = Short to power  
        else if(volt_temp > 4.80) {
            LCD_String("E03: TEMP SHORT ");
            LCD_SetCursor(2,1);
            LCD_String("TMP=5V ");
            LCD_Command(0xC7);
            LCD_Char((adc_temp/1000)%10 + '0');
            LCD_Char((adc_temp/100)%10 + '0');
            LCD_Char((adc_temp/10)%10 + '0');
            LCD_Char(adc_temp%10 + '0');
        }
        // Normal condition
        else {
            LCD_String("System OK       ");
            LCD_SetCursor(2,1);
            LCD_String("M:");
            LCD_Char((adc_map/1000)%10 + '0');
            LCD_Char('.');
            LCD_Char(((adc_map*5)/102)%10 + '0');
            LCD_String("V T:");
            LCD_Char((adc_temp/1000)%10 + '0');
            LCD_Char('.');
            LCD_Char(((adc_temp*5)/102)%10 + '0');
            LCD_String("V  ");
        }
        Delay_ms(300);
    }
}
 
void ADC_Init(void) {
    ADCON0 = 0x41; // ADC ON, Fosc/16, Channel 0
    ADCON1 = 0x80; // Right justified, Vref = Vdd/Vss
}
 
unsigned int ADC_Read(unsigned char channel) {
    ADCON0 &= 0xC5; // Clear channel bits
    ADCON0 |= channel << 3; // Set channel
    Delay_ms(1);    // Acquisition time
    GO_nDONE = 1;   // Start conversion
    while(GO_nDONE); // Wait
    return ((ADRESH << 8) + ADRESL); // Return 10-bit result
}
 
void LCD_Init(void) {
    LCD_TRIS = 0x00; // PORTB output
    Delay_ms(20);
    LCD_Command(0x38); // 8-bit, 2 line, 5x7
    LCD_Command(0x0C); // Display on, cursor off
    LCD_Command(0x06); // Auto increment
    LCD_Command(0x01); // Clear display
    Delay_ms(2);
}
 
void LCD_Command(unsigned char cmd) {
    RS = 0; // Command mode
    RW = 0; // Write
    LCD_PORT = (LCD_PORT & 0x03) | (cmd & 0xFC); // Keep RS,EN, put data
    if(cmd & 0x02) RB1 = 1; else RB1 = 0; // D1
    if(cmd & 0x01) RB0 = 1; else RB0 = 0; // D0
    EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
    LCD_PORT = cmd; // Send full byte
    EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
}
 
void LCD_Char(unsigned char data) {
    RS = 1; // Data mode
    RW = 0;
    LCD_PORT = data;
    EN = 1; Delay_ms(1); EN = 0; Delay_ms(2);
}
 
void LCD_String(const char *str) {
    while(*str) LCD_Char(*str++);
}
 
void LCD_SetCursor(unsigned char row, unsigned char col) {
    if(row == 1) LCD_Command(0x80 + (col-1));
    else LCD_Command(0xC0 + (col-1));
}
 
void Delay_ms(unsigned int ms) {
    while(ms--) __delay_ms(1);
}