#include <xc.h> #include <stdio.h> // ================= CONFIG ================= // Use these settings in MPLAB/XC8 #pragma config FOSC = HS // HS oscillator #pragma config WDTE = OFF // Watchdog Timer disabled #pragma config PWRTE = ON // Power-up Timer enabled #pragma config BOREN = ON // Brown-out Reset enabled #pragma config LVP = OFF // Low-Voltage Programming disabled #pragma config CPD = OFF // Data EEPROM Memory Code Protection off #pragma config WRT = OFF // Flash Program Memory Write Protection off #pragma config CP = OFF // Flash Program Memory Code Protection off #define _XTAL_FREQ 20000000 // 20 MHz Crystal (change if different) // ================= LCD CONNECTIONS ================= // LCD on PORTD #define RS RD0 #define EN RD1 #define D4 RD2 #define D5 RD3 #define D6 RD4 #define D7 RD5 // ================= FUNCTION PROTOTYPES ================= void Lcd_Command(char); void Lcd_Char(char); void Lcd_Init(void); void Lcd_String(const char *); void Lcd_Clear(void); void Lcd_Set_Cursor(char, char); unsigned int Read_ADC(unsigned char channel); // ================= GLOBAL VARIABLES ================= volatile unsigned int pulse_count = 0; unsigned int heart_rate = 0; // ================= MAIN PROGRAM ================= void main(void) { unsigned int adc_value; float temperature; char buffer[16]; // ADC setup ADCON1 = 0x80; // Right justified, Vref=VDD ADCON0 = 0x41; // ADC enabled, Channel 0 (AN0) // LCD setup TRISD = 0x00; // LCD port output Lcd_Init(); // RB0 as heart pulse input (external interrupt) TRISB0 = 1; // RB0 input INTEDG = 1; // Interrupt on rising edge INTE = 1; // Enable RB0 external interrupt GIE = 1; // Enable global interrupts // Timer1 for 1-second period T1CON = 0x31; // Prescaler 8, Timer1 ON TMR1H = 0; TMR1L = 0; while(1) { // ====== Read Temperature from LM35 ====== adc_value = Read_ADC(0); // Read AN0 temperature = (adc_value * 4.88) / 10.0; // LM35 = 10mV/°C // ====== Heart Rate Calculation every ~1s ====== if (TMR1H > 0x3C) { // Adjust for ~1 second heart_rate = pulse_count * 60; // convert to bpm pulse_count = 0; TMR1H = 0; TMR1L = 0; } // ====== Display on LCD ====== Lcd_Clear(); Lcd_Set_Cursor(1, 1); Lcd_String(buffer); Lcd_Set_Cursor(2, 1); Lcd_String(buffer); __delay_ms(500); } } // ================= ADC FUNCTION ================= unsigned int Read_ADC(unsigned char channel) { if(channel > 7) return 0; // PIC16F877A has 8 ADC channels (AN0–AN7) ADCON0 = (channel << 3) | 0x41; // Select channel, turn on ADC __delay_ms(2); // Acquisition time GO_DONE = 1; // Start conversion while(GO_DONE); // Wait until done return ((ADRESH << 8) + ADRESL); // Return result } // ================= LCD FUNCTIONS ================= void Lcd_Command(char cmd) { RS = 0; D4 = (cmd >> 4) & 1; D5 = (cmd >> 5) & 1; D6 = (cmd >> 6) & 1; D7 = (cmd >> 7) & 1; EN = 1; __delay_ms(1); EN = 0; D4 = cmd & 1; D5 = (cmd >> 1) & 1; D6 = (cmd >> 2) & 1; D7 = (cmd >> 3) & 1; EN = 1; __delay_ms(1); EN = 0; __delay_ms(2); } void Lcd_Char(char data) { RS = 1; D4 = (data >> 4) & 1; D5 = (data >> 5) & 1; D6 = (data >> 6) & 1; D7 = (data >> 7) & 1; EN = 1; __delay_ms(1); EN = 0; D4 = data & 1; D5 = (data >> 1) & 1; D6 = (data >> 2) & 1; D7 = (data >> 3) & 1; EN = 1; __delay_ms(1); EN = 0; __delay_ms(2); } void Lcd_Init() { Lcd_Command(0x02); // Initialize Lcd_Command(0x28); // 4-bit mode, 2-line, 5x7 Lcd_Command(0x0C); // Display ON, Cursor OFF Lcd_Command(0x06); // Auto-increment Lcd_Command(0x01); // Clear display } void Lcd_String(const char *str) { while(*str) Lcd_Char(*str++); } void Lcd_Clear() { Lcd_Command(0x01); } void Lcd_Set_Cursor(char row, char col) { char pos; } // ================= INTERRUPT SERVICE ROUTINE ================= void __interrupt() ISR(void) { if (INTF) { // RB0 interrupt flag pulse_count++; INTF = 0; // Clear interrupt flag } }
Standard input is empty
#include <xc.h> #include <stdio.h> // ================= CONFIG ================= // Use these settings in MPLAB/XC8 #pragma config FOSC = HS // HS oscillator #pragma config WDTE = OFF // Watchdog Timer disabled #pragma config PWRTE = ON // Power-up Timer enabled #pragma config BOREN = ON // Brown-out Reset enabled #pragma config LVP = OFF // Low-Voltage Programming disabled #pragma config CPD = OFF // Data EEPROM Memory Code Protection off #pragma config WRT = OFF // Flash Program Memory Write Protection off #pragma config CP = OFF // Flash Program Memory Code Protection off #define _XTAL_FREQ 20000000 // 20 MHz Crystal (change if different) // ================= LCD CONNECTIONS ================= // LCD on PORTD #define RS RD0 #define EN RD1 #define D4 RD2 #define D5 RD3 #define D6 RD4 #define D7 RD5 // ================= FUNCTION PROTOTYPES ================= void Lcd_Command(char); void Lcd_Char(char); void Lcd_Init(void); void Lcd_String(const char *); void Lcd_Clear(void); void Lcd_Set_Cursor(char, char); unsigned int Read_ADC(unsigned char channel); // ================= GLOBAL VARIABLES ================= volatile unsigned int pulse_count = 0; unsigned int heart_rate = 0; // ================= MAIN PROGRAM ================= void main(void) { unsigned int adc_value; float temperature; char buffer[16]; // ADC setup ADCON1 = 0x80; // Right justified, Vref=VDD ADCON0 = 0x41; // ADC enabled, Channel 0 (AN0) // LCD setup TRISD = 0x00; // LCD port output Lcd_Init(); // RB0 as heart pulse input (external interrupt) TRISB0 = 1; // RB0 input INTEDG = 1; // Interrupt on rising edge INTE = 1; // Enable RB0 external interrupt GIE = 1; // Enable global interrupts // Timer1 for 1-second period T1CON = 0x31; // Prescaler 8, Timer1 ON TMR1H = 0; TMR1L = 0; while(1) { // ====== Read Temperature from LM35 ====== adc_value = Read_ADC(0); // Read AN0 temperature = (adc_value * 4.88) / 10.0; // LM35 = 10mV/°C // ====== Heart Rate Calculation every ~1s ====== if (TMR1H > 0x3C) { // Adjust for ~1 second heart_rate = pulse_count * 60; // convert to bpm pulse_count = 0; TMR1H = 0; TMR1L = 0; } // ====== Display on LCD ====== Lcd_Clear(); sprintf(buffer, "Temp: %.1f C", temperature); Lcd_Set_Cursor(1, 1); Lcd_String(buffer); sprintf(buffer, "HR: %u bpm", heart_rate); Lcd_Set_Cursor(2, 1); Lcd_String(buffer); __delay_ms(500); } } // ================= ADC FUNCTION ================= unsigned int Read_ADC(unsigned char channel) { if(channel > 7) return 0; // PIC16F877A has 8 ADC channels (AN0–AN7) ADCON0 = (channel << 3) | 0x41; // Select channel, turn on ADC __delay_ms(2); // Acquisition time GO_DONE = 1; // Start conversion while(GO_DONE); // Wait until done return ((ADRESH << 8) + ADRESL); // Return result } // ================= LCD FUNCTIONS ================= void Lcd_Command(char cmd) { RS = 0; D4 = (cmd >> 4) & 1; D5 = (cmd >> 5) & 1; D6 = (cmd >> 6) & 1; D7 = (cmd >> 7) & 1; EN = 1; __delay_ms(1); EN = 0; D4 = cmd & 1; D5 = (cmd >> 1) & 1; D6 = (cmd >> 2) & 1; D7 = (cmd >> 3) & 1; EN = 1; __delay_ms(1); EN = 0; __delay_ms(2); } void Lcd_Char(char data) { RS = 1; D4 = (data >> 4) & 1; D5 = (data >> 5) & 1; D6 = (data >> 6) & 1; D7 = (data >> 7) & 1; EN = 1; __delay_ms(1); EN = 0; D4 = data & 1; D5 = (data >> 1) & 1; D6 = (data >> 2) & 1; D7 = (data >> 3) & 1; EN = 1; __delay_ms(1); EN = 0; __delay_ms(2); } void Lcd_Init() { Lcd_Command(0x02); // Initialize Lcd_Command(0x28); // 4-bit mode, 2-line, 5x7 Lcd_Command(0x0C); // Display ON, Cursor OFF Lcd_Command(0x06); // Auto-increment Lcd_Command(0x01); // Clear display } void Lcd_String(const char *str) { while(*str) Lcd_Char(*str++); } void Lcd_Clear() { Lcd_Command(0x01); } void Lcd_Set_Cursor(char row, char col) { char pos; if(row == 1) pos = 0x80 + (col - 1); else pos = 0xC0 + (col - 1); Lcd_Command(pos); } // ================= INTERRUPT SERVICE ROUTINE ================= void __interrupt() ISR(void) { if (INTF) { // RB0 interrupt flag pulse_count++; INTF = 0; // Clear interrupt flag } }