Kappa
Reged: Oct 04 2004
Posts: 89
|
|
Hi all, this is an example for using RX and TX interrupt for transmit and receiving text message.
Some adjustment also in order to receive RAW messages.
It's possible to add a serial time-out using a timer, for reset USART module.
This is a example for PIC18F452:
Code:
// ********************************************************************** // * * // * File name: main.c * // * * // * Since: 31 December 2007 * // * * // * Version: 0.01 * // * * // * Author: Kappa [KP] * // * * // * Purpose: * // * USART Interrupt test program * // * * // * History: * // * * // * 31/12/2007 [KP] File creation * // * 31/12/2007 [KP] First Release * // * * // **********************************************************************
#include <htc.h> #include <stdio.h> #include <string.h> #define FALSE 0 #define TRUE 1
#define LOW 0 #define HIGH 1
#define UART_DIVIDER 64 // 9600 bps for 40 MHz Osc
#define BUFFER_USART_LEN 64 // Size of TX/RX USART Buffer
// // Enumeration status serial // enum uart_status { WAITING, // Waiting byte on serial RECEIVING, // Receiving byte on serial READY, // Message on buffer PROCESSING // Processing message };
// // Struct of serial buffer // struct buffer_serial_tx { unsigned char buffer[BUFFER_USART_LEN]; // Buffer data unsigned char ptr; // Pointer to buffer unsigned char counter; // Number of byte };
struct buffer_serial_rx { unsigned char buffer[BUFFER_USART_LEN]; // Buffer data unsigned char ptr; // Pointer to buffer enum uart_status status; // Status buffer unsigned char counter; // Number of byte };
// // TX and RX Buffer // struct uart { // Buffer di ricezione trasmissione struct buffer_serial_tx tx; struct buffer_serial_rx rx; } rs232;
// ********************************************************************** // * * // * Setup FUSE of CPU * // * * // **********************************************************************
__CONFIG(1, OSCSDIS & HSPLL);
#if defined(__MPLAB_ICD__) __CONFIG(2, WDTPS128 & WDTDIS & BORV45 & BOREN & PWRTDIS); #else __CONFIG(2, WDTPS128 & WDTDIS & BORV45 & BOREN & PWRTEN); #endif
__CONFIG(3, CCP2RC1);
#if defined(__MPLAB_ICD__) __CONFIG(4, STVREN & LVPDIS & DEBUGEN); #else __CONFIG(4, STVREN & LVPDIS & DEBUGDIS); #endif
__CONFIG(5, UNPROTECT); __CONFIG(6, UNPROTECT); __CONFIG(7, UNPROTECT);
// ********************************************************************** // * Descrizione: Interrupt Service Routine High Priority * // * * // * Returns: None * // * * // * Parameters: None * // **********************************************************************
void interrupt ISR_high(void) { // ********************************************************************** // * * // * Interrupt Receive Uart RS232 * // * * // **********************************************************************
if((RCIF) && (RCIE)) { // Overrun error bit if(OERR) // { // CREN=0; // Restart USART CREN=1; // } //
// If error ... if(FERR) { // Flush buffer RCREG=RCREG; RCREG=RCREG; RCREG=RCREG; } else { // If Message absent on buffer or pointer if out of buffer if((rs232.rx.status == WAITING) || (rs232.rx.ptr >= BUFFER_USART_LEN)) { // Reset counter of RX bytes rs232.rx.counter = 0;
// Reset pointer of RX bytes rs232.rx.ptr = 0; // USART Receiving ... rs232.rx.status = RECEIVING; } // // If Receiving ... // if(rs232.rx.status == RECEIVING) { // Download and store byte rs232.rx.buffer[rs232.rx.ptr++] = RCREG; // Counter byte rs232.rx.counter++; // Test if received CR+LF byte (0x0D - 0x0A) if(rs232.rx.buffer[rs232.rx.ptr-1] == '\r') { // Message on Buffer ... rs232.rx.status=READY; } } else { // Flush buffer RCREG=RCREG; RCREG=RCREG; RCREG=RCREG; } } } }
// ********************************************************************** // * Descrizione: Interrupt Service Routine Low Priority * // * * // * Returns: None * // * * // * Parameters: None * // **********************************************************************
void interrupt low_priority ISR_low(void) { // ********************************************************************** // * * // * Interrupt Transmit Usart RS232 * // * * // **********************************************************************
if((TXIF) && (TXIE)) { // Bytes to send ... if(rs232.tx.counter > 0) { // TX byte TXREG = rs232.tx.buffer[rs232.tx.ptr];
// Point to next byte if (++rs232.tx.ptr > BUFFER_USART_LEN) rs232.tx.ptr = 0; }
// End TX byte, disable interrupt ... if(rs232.tx.counter == 0) { // END TX message TXIE = 0; } else { // Decrement number of bytes rs232.tx.counter--; } } }
// ********************************************************************** // * Descrizione: Initialize CPU * // * * // * Returns: CPU Initialized * // * * // * Parameters: None * // **********************************************************************
void init(void) { // ********************************************************************** // * * // * Setup PORT C * // * * // **********************************************************************
// // RC0 = Unused (Input - HIGH) // RC1 = Unused (Input - HIGH) // RC2 = Unused (Input - HIGH) // RC3 = Unused (Input - HIGH) // RC4 = Unused (Input - HIGH) // RC5 = Unused (Input - HIGH) // RC6 = TX Usart (Input - HIGH) // RC7 = RX Usart (Input - HIGH) // PORTC = 0b11111111; LATC = 0b11111111; TRISC = 0b10111111; // ********************************************************************** // * * // * Setup UART Service * // * * // **********************************************************************
SPBRG = UART_DIVIDER; // Setup baudrate TXSTA = 0b00100100; RCSTA = 0b10010000;
RCIE = 1; // Attivo Interrupt Receive RCIP = 1; // High Priority interrupt
TXIE = 0; // Reset Interrupt Trasmit TXIP = 0; // Low Priority interrupt // ********************************************************************** // * * // * Setup Gestione interruzioni * // * * // **********************************************************************
IPEN=1; // Enable interrupt Priority GIEL=1; // Enable interrupt Peripheral GIEH=1; // Enable interrupt Global }
// ********************************************************************** // * Descrizione: Main Routine * // * * // * Returns: None * // * * // * Parameters: None * // **********************************************************************
void main(void) { // Initialize CPU init(); // Initiaize status rs232.rx.status = WAITING; // Welcom message rs232.tx.counter = sprintf(rs232.tx.buffer, "Welcomes on USART example on %s\r", __DATE__); rs232.tx.ptr = 0; TXIE = HIGH; // Infinite loop while(TRUE) { // Message on buffer ... if(rs232.rx.status == READY) { // Processing buffer rs232.rx.status = PROCESSING; // Echo replay memcpy(rs232.tx.buffer, rs232.rx.buffer, rs232.rx.counter);
// Number of TX char rs232.tx.counter = rs232.rx.counter;
// Initialize TX pointer rs232.tx.ptr = 0;
// Start TX TXIE = HIGH; // Reset RX Buffer memset(rs232.rx.buffer, NULL, rs232.rx.counter);
// Reset Pointer and counter RX rs232.rx.ptr = 0; rs232.rx.counter = 0;
// Restart receive USART rs232.rx.status = WAITING; } } }
Kappa.
|
Tenson
newbie
Reged: Jul 20 2008
Posts: 49
|
|
Hi
I would like to remind you that variables/structures shared by ISR / main should be declared volatile.
|
Legend
stranger
Reged: Dec 30 2008
Posts: 1
Loc: China
|
|
Quote:
Hi
I would like to remind you that variables/structures shared by ISR / main should be declared volatile.
agree^
|
shahrul
newbie
Reged: Apr 23 2009
Posts: 38
Loc: Malaysia
|
|
I try compile this code, but there is an error. I don't understand, that void interrupt ISR_high(void) and void interrupt low_priority ISR_low(void) is the interrupt functions right? Is that function need to be declared or not? Why there is no setup on INTCON and PIE1 like INTCON=0b11000000; PIE1=0b00100000;
-------------------- SHAHRULNIZAM.COM
SHAHRULNIZAM.WS
|
Kappa
Reged: Oct 04 2004
Posts: 89
|
|
Hi,
Quote:
I try compile this code, but there is an error.
With that version of compiler ?
Quote:
I don't understand, that void interrupt ISR_high(void) and void interrupt low_priority ISR_low(void) is the interrupt functions right?
Check the manual of the compiler or some examples included with it.
Quote:
Is that function need to be declared or not?
For management to interrupt is to be declared.
Quote:
Why there is no setup on INTCON and PIE1 like INTCON=0b11000000; PIE1=0b00100000;
In init() function :
Code:
RCIE = 1; // Attivo Interrupt Receive RCIP = 1; // High Priority interrupt
TXIE = 0; // Reset Interrupt Trasmit TXIP = 0; // Low Priority interrupt
Kappa.
|
shahrul
newbie
Reged: Apr 23 2009
Posts: 38
Loc: Malaysia
|
|
Quote:
Quote:
I try compile this code, but there is an error.
With that version of compiler ?
I'm using software MPlab v8.2 with HI-TECH C Pro for the PIC10/12/16. I setup at device PIC16F877A.
Quote:
Quote:
I don't understand, that void interrupt ISR_high(void) and void interrupt low_priority ISR_low(void) is the interrupt functions right?
Check the manual of the compiler or some examples included with it.
I check the HI-TECH C Manual, but not available the function.
Quote:
Quote:
Why there is no setup on INTCON and PIE1 like INTCON=0b11000000; PIE1=0b00100000;
In init() function :
Code:
RCIE = 1; // Attivo Interrupt Receive RCIP = 1; // High Priority interrupt
TXIE = 0; // Reset Interrupt Trasmit TXIP = 0; // Low Priority interrupt
Oh, I see that RCIE and TXIE. But in the PIC16F877A not available the RCIP and TXIP. What is the alternative if I want to use with PIC16F877A? Shahrul..
-------------------- SHAHRULNIZAM.COM
SHAHRULNIZAM.WS
|
Dan Henry
Guru
  
Reged: Oct 16 2003
Posts: 3866
Loc: Colorado
|
|
Quote:
I setup at device PIC16F877A.
Quote:
I don't understand, that void interrupt ISR_high(void) and void interrupt low_priority ISR_low(void) is the interrupt functions right?
PIC16s do not have interrupt priority levels.
|
shahrul
newbie
Reged: Apr 23 2009
Posts: 38
Loc: Malaysia
|
|
Quote:
I setup at device PIC16F877A.
Quote:
PIC16s do not have interrupt priority levels.
So, how I want to write USART interrupt in PIC16s?
-------------------- SHAHRULNIZAM.COM
SHAHRULNIZAM.WS
|
Dan Henry
Guru
  
Reged: Oct 16 2003
Posts: 3866
Loc: Colorado
|
|
Quote:
So, how I want to write USART interrupt in PIC16s?
Adjust the code for your PIC (e.g., combine Tx and Rx interrupt handling into one interrupt function, delete lines dealing with priority level, resolve PORT and SFR differences, etc.).
|
shahrul
newbie
Reged: Apr 23 2009
Posts: 38
Loc: Malaysia
|
|
Quote:
Adjust the code for your PIC (e.g., combine Tx and Rx interrupt handling into one interrupt function, delete lines dealing with priority level, resolve PORT and SFR differences, etc.).
I have tried with this code Code:
char DATA[4],V3,V4; void interrupt ISR(void) {int i; //lcd_goto(0x00); //lcd_string(" INTERRUPT "); if(RCIF==1){ DATA[0]=DATA[1]; DATA[1]=DATA[2]; DATA[2]=DATA[3]; DATA[3]=DATA_IN; if(DATA[2]==0x0F){ if(DATA[3]==0xF0){ V3=DATA[0]; V4=DATA[1];}} }}
This function is to capture 4 byte data. I have succesfull using this function by call function. But, I'm fail to do this interrupt. This function not located in the interrupt vector (i.e address 0x04 for PIC16F877A). What is my mistake? Another problem, why I cannot call another function in the interrupt function?
-------------------- SHAHRULNIZAM.COM
SHAHRULNIZAM.WS
|