#include #include #include #include /* Set up the configuration bits */ #pragma config OSC = HS #pragma config PWRT = OFF #pragma config BOR = OFF #pragma config WDT = OFF #pragma config LVP = OFF #define BAUD 9600 #define FOSC 20000000L #define MIPS 5 #define LOW_PULSE_PERIOD (10L) // in ms #define HIGH_PULSE_PERIOD (100L) // in ms #define LOW_PULSE_COUNT (0xFFFF - (LOW_PULSE_PERIOD*MIPS*1000L)/256L) #define HIGH_PULSE_COUNT (0xFFFF - (HIGH_PULSE_PERIOD*MIPS*1000L)/256L) #define ERROR 1 #define DEVICE_ADDRESS 0b10010000 // Address(7:1) static unsigned int T0_pulse_count; static signed char current_temp; static signed char assigned_temp; static char state = 'O'; // off; + -> heat; - -> cold void interrupt_handler (void); #pragma code high_vector=0x08 void high_priority_interrupt (void) { _asm GOTO interrupt_handler _endasm } #pragma code void usart_setup(void) { // Set the port direction. TRISCbits.TRISC6 = 0; TRISCbits.TRISC7 = 1; // High baud rate select (TXSTA) TXSTAbits.BRGH = 1; // compute the divider for speed (see page 161) SPBRG = ((int)(FOSC/(16UL * BAUD) -1)); // Asynchronous mode (TXSTA) TXSTAbits.SYNC = 0; // 8 bits reception (RCSTA) RCSTAbits.RX9 = 0; // enable the receiver (RCSTA) RCSTAbits.CREN = 1; // 8 bits transmission (TXTSA) TXSTAbits.TX9 = 0; // enable transmission (TXTSA) TXSTAbits.TXEN = 1; // enable the Serial Port (RCSTA) RCSTAbits.SPEN = 1; } void io_port_setup(void) { // Sets all bits for port C for output TRISC = 0b00000000; // RE2 for input and RE1 for output; TRISE = 0b00000100; // RE1 (LED) is on; PORTE = 0b00000010; // RA0 for input; TRISA = 0b00000001; // Select AN0 as Anolog and AN6/7 (RE1/2) as digital // We are using the internal reference (VDD) // PCFG3:0 = 0010 ADCON1 = 0b00001001; // Result is left aligned in ADRESH ADCON1bits.ADFM = 0; // Conversion clock set to Fosc/32 (ADCS2:0 = 010) // Fosc = 20Mhz ADCON1bits.ADCS2 = 0; ADCON0bits.ADCS1 = 1; ADCON0bits.ADCS0 = 0; // We are sampling AN0: CHS2:0 = 000 // ADCON0 = ((ADCON0 & 0b11100011) | 0b00000000); ADCON0bits.CHS2 = 0; ADCON0bits.CHS1 = 0; ADCON0bits.CHS0 = 0; // Powering the module ADCON0bits.ADON = 1; // Clears A2D interrupt flag PIR1bits.ADIF = 0; // Allows A2D to trigger an interrupt PIE1bits.ADIE = 1; // acquisition delay? // Starting the fist conversion ADCON0bits.GO = 1; } void update_T0_value(unsigned int value) { TMR0H = value >> 8; TMR0L = value & 0xFF; } void timer0_setup(void) { T0_pulse_count = LOW_PULSE_COUNT; // Select low to high transition T0CONbits.T0CS = 0; // Select the pre-scaler T0CONbits.PSA = 0; // Set the pre-scaler value (T0PS2:0 = 111 -> 256) T0CON = ((T0CON & 0b11111000) | 0b00000111); // Set TO to be a 16bits timer T0CONbits.T08BIT = 0; // Load the timer value update_T0_value(T0_pulse_count); // Clear Timer0 interrupt flag INTCONbits.TMR0IF = 0; // Set Timer0 to trigger interrupt INTCONbits.TMR0IE = 1; // Start Timer0 T0CONbits.TMR0ON = 1; } void PWM_setup(void) { // PORTC2 output TRISCbits.TRISC2 = 0; // Select PWM mode; CCP1CON = ((CCP1CON & 0b11110000) | 0b00001100); // 16 as a prescaler T2CON = ((T2CON & 0b11111100) | 0b00000011); // Frequency: 2000 Hz PR2 = 155; // Duty cycle: 0 (OFF) CCP1CON = ((CCP1CON & 0b11001111) | 0b00000000); CCPR1L = 0; // Timer is ON! T2CONbits.TMR2ON = 1; } #pragma interrupt interrupt_handler void interrupt_handler(void) { if (PIR1bits.ADIF == 1) { // Update the Duty cycle CCPR1L = ADRESH; CCP1CON = ((CCP1CON & 0b11001111) | ((ADRESL & 0b11000000) >> 2)); PIR1bits.ADIF = 0; } if (INTCONbits.TMR0IF == 1) { // Timer expired // Load the new value update_T0_value(T0_pulse_count); // Clear the interrupt flag INTCONbits.TMR0IF = 0; // Start a new conversion ADCON0bits.GO = 1; } } void main( void) { char input; // setup the ports io_port_setup(); // setup the USART usart_setup(); // setup timer_0; timer0_setup(); PWM_setup(); printf("\n\r"); printf("\n\r"); // Not Interupt Priority RCONbits.IPEN = 0; // Allows for Peripheral interrupts INTCONbits.PEIE = 1; // Interrupts are on INTCONbits.GIE = 1; // Loop forever while (1); }