UARTCODE




//RS232 settings
                
#define tris_a     0111b
#define tris_b 11111111b
#define tris_c 11111111b


/*------------------------------------------------------------------------------*/
/******************************* Compiler Pragmas *******************************/
/*------------------------------------------------------------------------------*/
// Timing settings
#pragma TURBO_MODE 1
#pragma CLOCK_FREQ 50000000


/*------------------------------------------------------------------------------*/
/*********************** IO Pin and Status Pin Assignments **********************/
/*------------------------------------------------------------------------------*/

/* RA Port */                                         
#define RX_PIN  2
#define TX_PIN  3

/* STATUS */
#define ZERO    2
#define CARRY   0


// [9600] baud    - Sampling Rate = ~32     /*###### Tested ######*/
//#define BAUD_BIT        5                 /* These 3 definitions were hardcoded into the UART code    */
//#define START_DELAY     32+16+1           /* if you look at my comments in the UART code, you can see */
//#define INT_PERIOD      163               /* where I hardcoded them in, so you can change baud rate   */
                                            /* in the future                                            */

/*----------------------------------------------------------------*/
/** Absolute Addresses for UART Variables - General Purpose Regs **/
/*----------------------------------------------------------------*/

char    tx_high@248;       /* ISR: hi byte to transmit              */
char    tx_low@249;        /* ISR: low byte to transmit             */
char    tx_count@250;     /* ISR: number of bits sent              */
char    tx_divide@251;    /* ISR: xmit timing (/16) counter        */
char    rx_count@252;     /* ISR: number of bits received          */
char    rx_divide@253;    /* ISR: receive timing counter           */
char    rx_byte@254;      /* ISR: buffer for incoming byte         */   

/*------------------------------------------------------------------------------*/
/******************** GLOBAL REGISTER DEFINITIONS *******************************/
/*------------------------------------------------------------------------------*/

char    flags;  
char    ctemp = 0x00;
short   stemp = 0x0000;
          

void interrupt()
{
    goto isr_code;
    isr_code:
    /*------------------------------------*/
    transmit:
    
    asm
        {
            bank    _tx_divide
            clrb    _tx_divide.5 ;/* (tx_divide.baud_bit) clear xmit timing count flag      */
            inc     _tx_divide   ;/* (tx_divide)          only execute the transmit routine */
            setb    3.2          ;/* (STZ)                Set zero flag for test            */
            snb     _tx_divide.5 ;/* (tx_divide.baud_bit) every 2^baud_bit interrupt        */
            test    _tx_count    ;/* (tx_count)           are we sending?                   */
            snb     3.2          ;/* (SNZ)                (required for jz instruction)     */
            jmp     _receive     ;/*                      if not, go to :receive            */            
            clrb    3.0          ;/* (CLC)                yes, ready stop bit               */
            rr      _tx_high     ;/* (tx_high)            and shift to next bit             */
            rr      _tx_low      ;/* (tx_low)                                               */   
            dec     _tx_count    ;/* (tx_count)           decrement bit counter             */
        }

    if ((tx_low & 0x20) == 0)          /* output next bit                    */
    {                                  /* ( Rewritten MOVB instruction       */
        output_high_port_a(TX_PIN);    /*    movb    tx_pin,/tx_low.6 )      */
    }
    else
    {
        output_low_port_a(TX_PIN);
    }
 
    /*------------------------------------*/
    receive:
    
    if (input_pin_port_a(RX_PIN) == 0) /* get current rx bit                 */
    {                                  /* ( Rewritten MOVB instruction       */
        clear_bit(STATUS,CARRY);       /*   movb    c,rx_pin )               */
    }                                             
    else
    {
        set_bit(STATUS,CARRY);
    }
    asm
        {
            bank    _rx_count
            test    _rx_count    ;/* (rx_count) currently receiving byte?          */
            sb      3.2          ;/* (SZ)( required for jnz instruction )          */
            jmp     _rxbit       ;/* if so, jump ahead                             */
            mov     w,#9         ;/* in case start, ready 9 bits                   */
            sb      3.0          ;/* (SC) skip ahead if not start bit              */
            mov     _rx_count,w  ;/* (rx_count)it is, so renew bit count           */
            mov     w,#49        ;/* (START_DELAY) ready 1.5 bit periods           */
            mov     _rx_divide,w ;/* (rx_divide) */
        }

    /*------------------------------------*/
    rxbit:
    asm
        {
            bank    _rx_divide
            decsz   _rx_divide   ;/* (rx_divide) middle of next bit?               */
            jmp     _rxdone      ;/* ( rewritten for djnz instruction,             */
                                 ;/*  djnz    rx_divide,_rxdone )                  */
            setb    _rx_divide.5 ;/* (rx_divide.baudbit) yes, ready 1 bit period   */
            dec     _rx_count    ;/* (rx_count) last bit?                          */
            sb      3.2          ;/* (SZ) if not                                   */
            rr      _rx_byte     ;/* (rx_byte) then save bit                       */
            snb     3.2          ;/* (SNZ) if so                                   */
            bank    _flags
            setb    _flags.0     ;/* (flags.RX_FLAGS)then set flag                 */
        }

    rxdone: 
    asm
        {
            mov     w,#-163 ;/* (INT_PERIOD) interrupt every 'int_period' clk */
            retiw           ;/* exit interrupt                                */
        }
}

/*------------------------------------------------------------------------------*/
/******************** SUBROUTINE[PUT_CHAR] - Transmit a byte ********************/
/*------------------------------------------------------------------------------*/
void put_char(char data)
{
    asm
    {
        bank   param00_put_char
        mov    w,param00_put_char ; /* read in byte to be written. */
    }
pb_wait:
    asm
    {
        bank    _tx_count
        test    _tx_count   ;/* (TX_COUNT) wait for not busy  */
        sb      3.2         ;/* (SZ)                          */
        jmp     _pb_wait           
        not     w           ;/* ready bits (inverse logic)    */
        bank    _tx_high
        mov     _tx_high,w  ;/* (tx_high) store data byte     */
        setb    _tx_low.7   ;/* (tx_low) set up start bit     */
        mov     w,#10       ;/* 1 start + 8 data + 1 stop bit */
        mov     _tx_count,w ;/* (TX_COUNT)                    */
        ret                 ;/* leave and fix page bits       */
    }
}

/*------------------------------------------------------------------------------*/
/************* SUBROUTINE[PUT_STRING] - Send string out serial port *************/
/*------------------------------------------------------------------------------*/
void put_string(const char* text)
{
  char i = 0;

  while( text[i] != 0 )
      put_char( text[i++] ); 
}

/*------------------------------------------------------------------------------*/
/*********** SUBROUTINE[PUT_HEX_BYTE] - Send a Hex byte (2 digits) **************/
/*------------------------------------------------------------------------------*/
void put_hex_byte(char data)
{
    char temp;

    temp = data;
    temp = temp >> 4;
    temp = 0x0f & temp;

    if ((temp >= 0) & (temp <= 9))
    {
        temp = temp + 48;
    }
    else
    {
        temp = temp + 55;
    }
    put_char(temp);
    
       temp = 0x0f & data;
    
    if ((temp >= 0) & (temp <= 9))
    {
        temp = temp + 48;
    }    
    else
    {
        temp = temp + 55;
    }
    put_char(temp);
}


/*------------------------------------------------------------------------------*/
/*********** SUBROUTINE[PUT_HEX_WORD] - Send a Hex word (4 digits) **************/
/*------------------------------------------------------------------------------*/

void put_hex_word (short data)
{
    char ctemp;
    asm
    {
        bank param00_put_hex_word
        mov w,param00_put_hex_word+1
        bank _ctemp_put_hex_word
        mov _ctemp_put_hex_word, w
    }   
    put_hex_byte(ctemp);
    asm
    {
        bank param00_put_hex_word
        mov w,param00_put_hex_word 
        bank _ctemp_put_hex_word
        mov _ctemp_put_hex_word, w
    }   
    put_hex_byte(ctemp); 

}

/*------------------------------------------------------------------------------*/
/********* SUBROUTINE[GET_CHAR] - Receive a byte from the serial port ***********/
/*------------------------------------------------------------------------------*/
char get_char(void)
{
getit:
    asm
    {
        bank    _flags
        sb      _flags.0      ;/* (flags.#RX_FLAG) wait till byte is received   */
        jmp     _getit
        clrb    _flags.0      ;/* (flags.#RX_FLAG) reset the receive flag       */
        bank    _rx_byte
        mov     w,_rx_byte    ;/* (rx_byte)                                     */
        ret
    }                                                                      
}


/*------------------------------------------------------------------------------*/
/****** SUBROUTINE[GET_HEX_BYTE] - Capture an 8bit ascii Hex number (2 dig) *****/
/*------------------------------------------------------------------------------*/
 char get_hex_byte()
 {
  char nibble, byte, count;
      
  byte  = 0;
  count = 0;
  
  while (count != 2)
  {
      nibble = get_char();
  
    if ((nibble >= '0') && (nibble <= '9'))
    {
      asm
      {
       bank  _byte_get_hex_byte
       swap  _byte_get_hex_byte
      }
      byte = byte | (nibble - '0');
      count++; 
    }
    else
    {
      if (nibble >= 'a')
      {
        nibble = nibble & 0xDF;
      } 
      
      if ((nibble >= 'A') && (nibble <= 'F'))
      {
        asm
        {
         bank  _byte_get_hex_byte
         swap  _byte_get_hex_byte
        }
        byte = byte | (nibble - ('A' - 10));
        count++; 
      }
    }
  }
  return(byte);
 }

 
/*------------------------------------------------------------------------------*/
/***** SUBROUTINE[GET_HEX_WORD] - Capture an 16bit ascii Hex number (4 dig) *****/
/*------------------------------------------------------------------------------*/
 short get_hex_word()
{
  short byte, word;

  byte = get_hex_byte();
  asm
  {
    bank _byte_get_hex_word
    mov  w,_byte_get_hex_word
    bank _word_get_hex_word
    mov  _word_get_hex_word+1,w
  }
  byte = get_hex_byte();
  asm
  {
    bank _byte_get_hex_word
    mov  w,_byte_get_hex_word
    bank _word_get_hex_word
    mov  _word_get_hex_word,w
  }

  return(word);
}

//***********************************************
//MAIN CODE
//***********************************************
main()
{
       
        set_tris_a(tris_a);
        set_tris_b(tris_b);
        set_tris_c(tris_c);
               
        set_option(0x9F);
        
        while(1)
        {
         
         put_string("\r\nHELLO WORLD   get_char     = ");
         ctemp = get_char();
         put_char(ctemp);
         put_string("\r\n");
         
         put_string("HELLO EARTH   get_hex_byte = ");
         ctemp = get_hex_byte();
         put_hex_byte(ctemp);
         put_string("\r\n");
         
         put_string("HELLO MARS    get_hex_word = ");
         stemp = get_hex_word();
         put_hex_word(stemp);
         put_string("\r\n"); 
        }

        


Copyright© 2000 John Wynia