//****************************************************************************************** // PIC16F877 Sample Program // Project : // Program Name : // Programer : // Create date : // History : // Laungage : XC8 C Laungage Version 2.20 //****************************************************************************************** // Description //****************************************************************************************** // #include #include #include #pragma config FOSC = HS, WDTE = ON, PWRTE = OFF, CP = OFF, BOREN = OFF, LVP = OFF, CPD = OFF, WRT = OFF, DEBUG = OFF //For 16F877 //#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, BOREN = OFF, LVP = OFF, CPD = OFF, WRT = OFF, DEBUG = OFF, CP = OFF //For 16F877A #define PI_NORMAL 0 #define PI_FAILER 1 // #define PI_AN0 0 #define PI_AN1 1 #define PI_AN3 3 void Init_usart(void); char Recive_usart(char *); char Send_usart(char); void Send_usart_s(char *); void Timer_1mS(unsigned int); void Timer_1mS_sub(void); void Init_ADC(void); void Init_WDT(void); unsigned int Get_ADC(char); void main() { char status; unsigned int ret_data; unsigned long ret_data_l; char tmp_line[15]; // ************************* // 1.Initialize // ************************* // (1)Initialize Watchdog Init_WDT(); // (2)Initialize UART Init_usart(); // (3)Put Start messages Send_usart_s((char *)"PIC16F877 Connected OK >>"); // (4)Initialize A/D Converter Init_ADC(); // ************************* // 2.Main loop // ************************* while(1){ ret_data = Get_ADC(PI_AN0); ret_data_l = (unsigned long)ret_data * (unsigned long)5000 / (unsigned long)1024; sprintf(tmp_line,"AN0:%ld",ret_data_l); Send_usart_s((char *)tmp_line); Send_usart_s((char *)"[mV] "); ret_data = Get_ADC(PI_AN1); ret_data_l = (unsigned long)ret_data * (unsigned long)5000 / (unsigned long)1024; sprintf(tmp_line,"AN1:%ld",ret_data_l); Send_usart_s((char *)tmp_line); Send_usart_s((char *)"[mV] "); ret_data = Get_ADC(PI_AN3); ret_data_l = (unsigned long)ret_data * (unsigned long)5000 / (unsigned long)1024; sprintf(tmp_line,"AN3:%ld",ret_data_l); Send_usart_s((char *)tmp_line); Send_usart_s((char *)"[mV] "); Timer_1mS(1000); CLRWDT(); }; } //****************************************************************************************** // Program : Init_WDT // Title : // Input : // Output : // Description : //****************************************************************************************** void Init_WDT(void) { //******************************************************* // 1.Define OPTION_REG Register // OPTION_REG[7] RBPU // OPTION_REG[6] INTEDG // OPTION_REG[5] T0CS: TMR0 Clock Source Select bit // 1 = Transition on T0CKI pin // 0 = Internal instruction cycle clock (CLKO) // OPTION_REG[4] T0SE: TMR0 Source Edge Select bit // 1 = Increment on high-to-low transition on T0CKI pin // 0 = Increment on low-to-high transition on T0CKI pin // OPTION_REG[3] PSA: Prescaler Assignment bit // 1 = Prescaler is assigned to the WDT // 0 = Prescaler is assigned to the Timer0 module // OPTION_REG[2-0] PS2:PS0: Prescaler Rate Select bits // 111 = 128 //******************************************************* // OPTION_REG[2-0]:111 // 18mS(0.018S) * 128 ===> 2.3[S] OPTION_REG |= 0b00000111; } //****************************************************************************************** // Program : Init_ADC // Title : // Input : // Output : // Description : //****************************************************************************************** void Init_ADC(void) { //******************************************************* // 1.Define ADCON0(A/D CONTROL REGISTER 0) Register // ADCON0[7-6] ADCS1:ADCS0: A/D Conversion Clock Select bits (ADCON0 bits in bold) // ADCON0[5-3] CHS2:CHS0: Analog Channel Select bits // 000 = Channel 0 (AN0) // 001 = Channel 1 (AN1) // 010 = Channel 2 (AN2) // 011 = Channel 3 (AN3) // 100 = Channel 4 (AN4) // 101 = Channel 5 (AN5) // 110 = Channel 6 (AN6) // 111 = Channel 7 (AN7) // Note: The PIC16F873A/876A devices only implement A/D channels 0 through 4; the // unimplemented selections are reserved. Do not select any unimplemented channels with these devices. // ADCON0[2] GO/DONE: A/D Conversion Status bit // When ADON = 1: // 1 = A/D conversion in progress (setting this bit starts the A/D conversion which is automatically // cleared by hardware when the A/D conversion is complete) // 0 = A/D conversion not in progress // ADCON0[1] Unimplemented: Read as '0' // ADCON0[0] ADON: A/D On bit //******************************************************* ADCON0 = 0b10000001 ; //******************************************************* // 2.Define ADCON1(A/D CONTROL REGISTER 1) Register // ADCON1[7] ADFM: A/D Result Format Select bit // 1 = Right justified. Six (6) Most Significant bits of ADRESH are read as '0' // 0 = Left justified. Six (6) Least Significant bits of ADRESL are read as '0' // ADCON1[6] ADCS2: A/D Conversion Clock Select bit (ADCON1 bits in shaded area and in bold) ===> Caution:16F877A Only bits !!!!! // ADCS2 ADCS1:ADCS0 // 0 00 = FOSC/2 // 0 01 = FOSC/8 // 0 10 = FOSC/32 // 0 11 = FRC (clock supplied from a dedicated RC oscillator) // 1 00 = FOSC/4 // 1 01 = FOSC/16 // 1 10 = FOSC/64 // 1 11 = FRC (clock supplied from a dedicated RC oscillator) // // ADCON1[5-4] Unimplemented: Read as '0' // ADCON1[3-0] PCFG3:PCFG0: A/D Port Configuration Control bits //******************************************************* // AN0 // ADCON1 = 0b10001110; // AN0,AN1,AN3 ADCON1 = 0b10000100; } //****************************************************************************************** // Function Name : Get_ADC // Title : // Input : // Output : // Description : //****************************************************************************************** unsigned int Get_ADC(char port_no) { char status; int ret_data = 0; // ***************** // 1.Start A/D Converter // ***************** // (1)GO/DONE: A/D Conversion Status bit // ADCON0[5-3] CHS2:CHS0: Analog Channel Select bits // 000 = Channel 0 (AN0) // 001 = Channel 1 (AN1) // 010 = Channel 2 (AN2) // 011 = Channel 3 (AN3) // 100 = Channel 4 (AN4) // 101 = Channel 5 (AN5) // 110 = Channel 6 (AN6) // 111 = Channel 7 (AN7) if( port_no == PI_AN0 ){ ADCON0 = 0b10000001 ; //Required item !!!! Timer_1mS(10); //Required item !!!! ADCON0 = 0b10000101 ; //AN0 }else if( port_no == PI_AN1 ){ ADCON0 = 0b10001001 ; //Required item !!!! Timer_1mS(10); //Required item !!!! ADCON0 = 0b10001101 ; //AN1 }else{ ADCON0 = 0b10011001 ; //Required item !!!! Timer_1mS(10); //Required item !!!! ADCON0 = 0b10011101 ; //AN3 } // ***************** // 2.Get data // ***************** // (1)Get data while((ADCON0 & 0b00000100)!=0x00); // (2)Set data ret_data = ADRESH * 0xff + ADRESL ; return(ret_data); } //****************************************************************************************** // Function Name : Timer_1mS // Title : Wait function (1mS) * Number (argument) // Input : // Output : //****************************************************************************************** void Timer_1mS(unsigned int Number) { unsigned int lp; for(lp=0;lp 0d4000(Count) ==> 0x0FA0(Count) // TMR1 = 0xFFFF - 0x0FA0 ==> 0xF05F // TMR1H = 0xF0; // TMR1L = 0x5F; // // (2)TMR1 data ( OSC:20MHz, 1:1 Prescale value, 0.001[S];1000Hz ) // 1mS(1000Hz): 20MHz / 4(FOSC/4) / 1000(1000Hz)==> 0d5000(Count) ==> 0x1338(Count) // TMR1 = 0xFFFF - 0x1338 ==> 0xECC7 TMR1H = 0xEC; TMR1L = 0xC7; // ******************************************************* // 3.Timer // ******************************************************* PIR1bits.TMR1IF = 0; while(1){ if(PIR1bits.TMR1IF != 0 )break; } } //****************************************************************************************** // Function Name : Init_usart // Title : // Input : // Output : //****************************************************************************************** void Init_usart(void) { // ******************************************************* // 1.Define Interrupts // ******************************************************* // PIR1bits.TXIF = 0 ; // USART Transmit Interrupt Flag bit // PIR1bits.RCIF = 0 ; // USART Receive Interrupt Flag bit INTCONbits.GIE = 1 ; // Grobal Interrupt Ebable (->1) INTCONbits.PEIE = 1 ; // Peripheral Interrupt Ebable (->1) // // PIE1bits.TXIE = 1 ; // USART Transmit Interrupt Enable bit (->1) PIE1bits.RCIE = 1 ; // USART Receive Interrupt Enable bit (->1) //******************************************************* // 2.Define TXSTA(TRANSMIT STATUS AND CONTROL) Register // TXSTA[7] CSRC: Clock Source Select bit // Asynchronous mode: // Don?t care. // Synchronous mode: // 1 = Master mode (clock generated internally from BRG) // 0 = Slave mode (clock from external source) // TXSTA[6] TX9: 9-bit Transmit Enable bit // 1 = Selects 9-bit transmission // 0 = Selects 8-bit transmission // TXSTA[5] TXEN: Transmit Enable bit // 1 = Transmit enabled // 0 = Transmit disabled // Note: SREN/CREN overrides TXEN in Sync mode. // TXSTA[4] SYNC: USART Mode Select bit // 1 = Synchronous mode // 0 = Asynchronous mode // TXSTA[3] Unimplemented: Read as ?0? // TXSTA[2] BRGH: High Baud Rate Select bit // Asynchronous mode: // 1 = High speed // 0 = Low speed // Synchronous mode: // Unused in this mode. // TXSTA[1] TRMT: Transmit Shift Register Status bit // 1 = TSR empty // 0 = TSR full // TXSTA[0] TX9D: 9th bit of Transmit Data, can be Parity bit TXSTA = 0b00100100 ; // TXSTA = 0b00100000 ; //******************************************************* // 3.Define RCSTA(RECEIVE STATUS AND CONTROL) Register // RCSTA[7] SPEN: Serial Port Enable bit // 1 = Serial port enabled (configures RC7/RX/DT and RC6/TX/CK pins as serial port pins) // 0 = Serial port disabled // RCSTA[6] RX9: 9-bit Receive Enable bit // 1 = Selects 9-bit reception // 0 = Selects 8-bit reception // RCSTA[5] SREN: Single Receive Enable bit // Asynchronous mode: // Don?t care. // Synchronous mode ? Master: // 1 = Enables single receive // 0 = Disables single receive // This bit is cleared after reception is complete. // Synchronous mode ? Slave: // Don?t care. // RCSTA[4] CREN: Continuous Receive Enable bit // Asynchronous mode: // 1 = Enables continuous receive // 0 = Disables continuous receive // Synchronous mode: // 1 = Enables continuous receive until enable bit CREN is cleared (CREN overrides SREN) // 0 = Disables continuous receive // RCSTA[3] ADDEN: Address Detect Enable bit // Asynchronous mode 9-bit (RX9 = 1): // 1 = Enables address detection, enables interrupt and load of the receive buffer when RSR<8> is set // 0 = Disables address detection, all bytes are received and ninth bit can be used as parity bit // RCSTA[2] FERR: Framing Error bit // 1 = Framing error (can be updated by reading RCREG register and receive next valid byte) // 0 = No framing error // RCSTA[1] OERR: Overrun Error bit // 1 = Overrun error (can be cleared by clearing bit CREN) // 0 = No overrun error // RCSTA[0] RX9D: 9th bit of Received Data (can be parity bit but must be calculated by user firmware) RCSTA = 0b10010000; // ******************************************************* // 4.Define BRG(EUSART Baud Rate Generator Register) Register // ******************************************************* // BRG 20MHz, 9600BPS SPBRG = 129; // BRG = 16000000(Hz)/4/9600(BPS)-1 ==> 0d0416 ==> 0x1A0 // BRG = 20000000(Hz)/4/9600(BPS)-1 ==> 0d0520 ==> 0x208 // (1)Define SPBRGH(EUSART Baud Rate Generator Register, High Byte) Register // SPBRGH = 0x20; // (2)Define SPBRG(EUSART Baud Rate Generator Register, Low Byte) Register // SPBRG = 0x08; } //****************************************************************************************** // Function Name : Recive_usart // Title : // Input : // Output : //****************************************************************************************** char Recive_usart(char *io_data) { unsigned char status; // **************************** // 1.Check Recvive Flagunsigned char status; // **************************** PIR1 = PIR1 & 0b11011111; while(1){ status = PIR1 & 0b00100000 ; if(status != 0x00)break; } // **************************** // 2.Check error // **************************** status = RCSTA & 0x06; //0000,0110 RCSTA(FERR,OERR) if(status != 0x00){ *io_data = 0x00; return(PI_FAILER); } // **************************** // 3.Set Recive Data // **************************** *io_data = RCREG; return(PI_NORMAL); } //****************************************************************************************** // Function Name : Send_usart_s // Title : Send UART String // Input : // Output : //****************************************************************************************** void Send_usart_s(char *put_string) { while(*put_string!=0x00){ Send_usart(*put_string); put_string++; } } //****************************************************************************************** // Function Name : Send_usart // Title : // Input : // Output : //****************************************************************************************** char Send_usart(char in_char) { char status; // *************************** // 1.Check Send Flag // *************************** while(1){ status = TXSTA & 0b00100010; //0000,0010 TXSTA(TRMT) if(status != 0x00)break; } // *************************** // 2.Set data // *************************** TXREG = in_char; // **************************** // 3.Check Flagunsigned char status; // **************************** PIR1 = PIR1 & 0b11101111; while(1){ status = PIR1 & 0b00010000 ; if(status != 0x00)break; } return(PI_NORMAL); } //****************************************************************************************** // Function Name : isr // Title : Interrupt function // Input : // Output : //****************************************************************************************** void __interrupt() isr(void) { char io_data; char status; // ********************************** // 1.Initiarize // ********************************** // 1.Stop Interrupt INTCONbits.GIE = 0 ; // Grobal Interrupt Disable (->1) // ********************************** // 2.UART // ********************************** if(PIR1bits.TXIF){ status = Recive_usart(&io_data); status = Send_usart(io_data); } // ********************************** // 3.Finarize // ********************************** // 1.Start Interrupt INTCONbits.GIE = 1 ; // Grobal Interrupt Ebable (->1) }