async_sample3.c

Sample application that demonstrates how to mix interrupts and use interrupt driven receive features of the usart in the 16F877 chip. It also shows out to output a mix of strings and numbers to the serial port (by Bert Drake).




#pragma CLOCK_FREQ 20000000



#include <system.h>



//-----------------------------------------------------------------------------

// Macros



// Very useful macro which allows use of predefine bit values from system.h

// to be used for testing bits just like they are used in set_bit and clear_bit

#define test_bit(x,y) (x&(1<<y))



//-----------------------------------------------------------------------------

// Set the configuration values (aka fuses)



#ifdef _PIC16F877A

// Appropriate defines for 16F877A

asm __config _HS_OSC & _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_ON & _BODEN_ON & _PWRTE_ON & _WDT_OFF

#endif



#ifdef _PIC16F877

// Appropriate defines for 16F877A

asm __config _HS_OSC & _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_ON & _BODEN_ON & _PWRTE_ON & _WDT_OFF

#endif



//-----------------------------------------------------------------------------

// Set the ID bytes

asm __idlocs H'1234'



//-----------------------------------------------------------------------------

// Prototypes

void ms_tick(void);

void writeString(const char *s);

void sendDecimalInt(int n);

void sendDecimalByte(int n);

void sendHexInt(int n);

void sendHexByte(int n);

void sendBinaryByte(char n);

void sendChar(char c);

void sendRate(void);

void handleReceivedChar(char receivedChar);



//-----------------------------------------------------------------------------

// Globals

int ms_count;

int blink_interval; // # of MS between blinks

char led_flag;      // Use of a shadow flag prevents side effects of pin latency

char port_b_val;    // Only used for testing



const char *strReady = "\r\nReady> ";

const char *strRate = "Blink Rate = ";



//----------------------------------------------------------------------------

// Writes a string (character array) to the USART

//----------------------------------------------------------------------------

void writeString(const char *s)

{

    char i=0;



    if( ! test_bit(txsta,TXEN) )

        set_bit(txsta, TXEN );

    while( s[i]!=0 ){

        // write 'u' to serial port, LCD, etc.

        while( ! test_bit(pir1, TXIF) )

            nop();

        txreg=s[i];

        i++;

    }

}



//----------------------------------------------------------------------------

// Writes a single character to the USART

//----------------------------------------------------------------------------

void sendChar(char c)

{

    if( ! test_bit(txsta, TXEN) ){

        set_bit(txsta, TXEN );

    }



    while( ! test_bit(pir1, TXIF) ){

        nop();

    }

    txreg=c;

}



//----------------------------------------------------------------------------

// Writes a 16-bit integer in decimal format to the USART

//----------------------------------------------------------------------------

void sendDecimalInt(int n)

{

    if( n >=10000 )

        sendChar(((n/10000)%10)+'0');

    if( n >=1000 )

        sendChar(((n/1000)%10)+'0');

    if( n >=100 )

        sendChar(((n/100)%10)+'0');

    if( n >=10 )

        sendChar(((n/10)%10)+'0');

    sendChar((n%10)+'0');

}



//----------------------------------------------------------------------------

// Writes a 8-bit byte in decimal format to the USART

//----------------------------------------------------------------------------

void sendDecimalByte(int n)

{

    if( n >=100 )

        sendChar(((n/100)%10)+'0');

    if( n >=10 )

        sendChar(((n/10)%10)+'0');

    sendChar((n%10)+'0');

}



//----------------------------------------------------------------------------

// Writes a 16-bit integer in hex format to the USART

//----------------------------------------------------------------------------

void sendHexInt(int n)

{

    sendHexByte((n>>8)&0xFF);

    sendHexByte(n&0xFF);

}



//----------------------------------------------------------------------------

// Writes a 8-bit byte in hex format to the USART

//----------------------------------------------------------------------------

void sendHexByte(char n)

{

    char h;

    h=(n>>4)&0xF;

    n=n&0xF;

    if( h>=10 )

        sendChar((h-10)+'A');

    else

        sendChar(h+'0');

    if( n>=10 )

        sendChar((n-10)+'A');

    else

        sendChar(n+'0');

}



//----------------------------------------------------------------------------

// Writes a 8-bit byte in binary format to the USART

//----------------------------------------------------------------------------

void sendBinaryByte(char n)

{

    static char masks[]={0x80, 0x40, 0x20, 0x10, 8,4,2,1 };

    int i;

    for(i=0; i<8; i++ ){

        if( n & masks[i] )

            sendChar('1');

        else

            sendChar('0');

    }

}





//----------------------------------------------------------------------------

// Write the current blink interval value to the terminal

// This illustrates mixing string and numeric output

// This method avoids the memory waste of a printf type function

// Sends the 16-bit value in decimal, hex, and binary

//----------------------------------------------------------------------------

void sendRate(void)

{

    writeString(strRate);

    sendDecimalInt(blink_interval);

    sendChar(' ');

    sendChar('0');

    sendChar('x');

    sendHexInt(blink_interval);

    sendChar(' ');

    sendBinaryByte((blink_interval>>8)&0xFF);

    sendChar('.');

    sendBinaryByte(blink_interval&0xFF);

    sendChar('b');

    sendChar('\r');

    sendChar('\n');

}



//-----------------------------------------------------------------------------

void handleReceivedChar(char receivedChar)

{

    if( receivedChar==13 ){

        writeString(strReady);

    }else if( receivedChar=='+' ){  // Increase the blink delay

        if( blink_interval>=100 ){

            blink_interval = blink_interval + 100;

        }else{

            blink_interval = blink_interval + 10;

        }

        sendRate();

    }else if( receivedChar=='-' ){  // Decrease the blink delay

        if( blink_interval >= 200 )

            blink_interval = blink_interval - 100;

        else if( blink_interval > 10 )

            blink_interval = blink_interval - 10;

        sendRate();

    }else if( receivedChar=='?' ){  // Show the blink delay

        sendRate();

    }else{  // Just echo the inbound char

        txreg=receivedChar;

        set_bit(txsta,TXEN);

    }

}



//-----------------------------------------------------------------------------

void interrupt(void)

{

    if( test_bit(intcon,T0IF) ){    // TMR0 overflow interrupt

        ms_tick();



        tmr0 = 0x64;    // -156 generates a 1MHz tick at 20MHz

        clear_bit(intcon,T0IF);

    }



    if ( test_bit(intcon,INTF) ){ // INT interrupt

        clear_bit(intcon,INTF);  // reset flag

    }



    if ( test_bit(intcon,RBIF) ){   // RB port change interrupt

        port_b_val = portb; // clear mismatch

        clear_bit(intcon,RBIF);

    }



    if ( test_bit(pir1, RCIF) ){    // Char received will be in RCREG

        if( test_bit(rcsta, FERR) || test_bit(rcsta, OERR) ){

            clear_bit(rcsta,CREN);

            nop();  // Put a nop between bit operations on the same register to avoid PIC read-modify-write problems

            set_bit(rcsta,CREN);

        }

        handleReceivedChar(rcreg);

    }

}



//----------------------------------------------------------------------------

void ms_tick(void)

{

    ms_count++;

    if( ms_count > blink_interval ){

        ms_count=0;

        if( led_flag==0 ){

            led_flag=1;

            set_bit(porta,0);   // led1=1;

        }else{

            led_flag=0;

            clear_bit(porta,0); // led1=0;

        }

    }

}



//-----------------------------------------------------------------------------

void main()

{

    disable_interrupt( GIE );



    adcon1=0x06;



    led_flag=0;



    blink_interval=500; // Default blink on/off interval of 500 ms yelds 1 blink/sec



    ms_count=0;



    option_reg=4;   // set prescaler to 1:32

    porta=00000001b;

    trisa=11111110b;

    tmr0 = 0x64;    // -156 generates a 1ms interrupt at 20MHz

    set_bit(intcon, T0IE);



    char i = 0;



    // Set up serial comm

    trisc = 11000000b;



    txsta=0;    // Transmit Status Register - init everything to 0

    rcsta=0;    // Receive Status Register - init everything to 0



    // Now set up baud rate

    set_bit(txsta,BRGH);    // High Baud Rate Select

    spbrg=129;  // 20MHz: 129=9600, 64=19200  (if BRGH=0 then 129=2400)



    // Set SYNC to 0 for Async mode

    clear_bit(txsta,SYNC);  // SYNC=0;  // Async Mode



    set_bit(rcsta,SPEN);    // SPEN=1;  // Serial Port Enable



    set_bit(txsta,TXEN);    // Transmit Enable

    set_bit(pie1,TXIE);     // Transmit Interrupt Enable



    set_bit(rcsta,CREN);    // Constant Receive ENable

    set_bit(pie1,RCIE);     // Receive Interrupt Enable



    set_bit(intcon,PEIE);   // PEripherial Interrupt Enable



    enable_interrupt( GIE );



    while( 1 )

    {

        nop();

    }

}



//-----------------------------------------------------------------------------






http://www.sourceboost.com/home.html

Copyright © 2002-2006 SourceBoost Technologies