Menu

Hardware USART Library

Steve
2007-02-04
2013-05-30
  • Steve

    Steve - 2007-02-04

    Here is some code that I've written to make a pic communicate with Hyperterminal in GCBASIC

    I thought I'd share it with you all.  I wanted to make the setup serial routine "smarter" but haven't got around to that yet.  It works fine with a 16F690 @ 9600 baud, 8/n/1, flow control off.  There is come parity checking code in there, but I have commented it out, since it works fine without it.

    To use, here is a sample program
    ******************************
    'Filename: test_usart.txt
    'A program to test serial communications

    'Chip model
    #chip 16F690, 8
    #config INTRC_OSC_NOCLKOUT, WDT_OFF

    #include "usart.h"
    'Hardware USART constants

    'Main routine
    ADOFF
    dir PORTC.7 out
    SetupSerial '9600 baud, 8/N/1 no flow control

    Main: 
    SET PORTC.7 ON
    TransmitSerial_Print("Please type in a character ")
    Transmitserial(13)
    Transmitserial(10)
    Loopx:
    Character = ReceiveSerial
    If flags.gotnewdata OFF then GOTO Loopx
    TransmitSerial_Print("Message received, you entered a: ")
    TransmitSerial(Character)
    Transmitserial(13)
    Transmitserial(10)
    Set flags.gotnewdata OFF
    SET PORTC.7 OFF
    wait 25 ms
    goto Main

    ******************************
    '   Filename: usart.h
    '   Hardware USART routines for Great Cow BASIC
    '   Steve Bell

    '     February 3, 2007

    'Subs
    ' sub SetupSerial     Setup serial port with baudrate 9600 for 8Mhz clock
    ' sub ReceiveSerial(data)    Receive data from serial port into byte data
    ' sub TransmitSerial(data)    Transmit data to serial port
    ' sub TransmitSerial_Print(PrintData$) Transmit a string to the serial port

    'Hardware USART constants
    #define GOTNEWDATA 0     'bit that indicates new data received

    sub SetupSerial(baud_rate,USARTPORT,USART_TX,USART_RX)
    ADOff 'make port digital
    DIR PORTB.7 OUT
    DIR PORTB.5 IN
    SPBRG = 12            ' this value is for 9600 baud with brgh bit = 0 P16F690
    TXSTA = b'00100000'    'note, bit 2 is BRGH
    RCSTA = b'10010000' 'enable serial port and reception
    SET FLAGS.GOTNEWDATA OFF
    end sub

    sub TransmitSerial(xmitdata)
    LoopTransmit:
    IF PIR1.TXIF OFF THEN goto LoopTransmit 'check if transmitter is busy
    TXDATA = xmitdata
    ' CalcParity(TXDATA) 'calculate parity
    ' rotate ParityByte RIGHT 'get parity bit into status.c
    ' SET TXSTA.TX9D OFF 'set parity bit to zero
    ' IF STATUS.C = 1 THEN SET TXSTA.TX9D ON 'if status.c is one, set parity bit
    TXREG = TXDATA 'transmit data
    end sub

    sub TransmitSerial_Print(PrintData$)
    PrintLen = PrintData(0)
    if PrintLen = 0 then exit sub
    'Write Data
    for SysPrintTemp = 1 to PrintLen
      TransmitSerial(PrintData(SysPrintTemp))
    next
    end sub

    sub CalcParity(Temp)     'calculate even parity bit, data starts in paritybyte
                                'result is in Lsb of ParityByte
    Paritybyte = Temp 'get data for parity calculation
    rrf     Paritybyte,W 'rotate
    xorwf     Paritybyte,W 'compare all bits against neighbor
    movwf     Paritybyte 'save
    rrf     ParityByte,F 'rotate
    rrf     ParityByte,F 'rotate
    xorwf     ParityByte,F 'compare every 2nd bit and save
    swapf     ParityByte,W 'rotate 4
    xorwf     ParityByte,F 'compare every 4th bit and save
    end sub

    function ReceiveSerial        'check if data received, and if so, return data
    IF PIR1.RCIF OFF THEN GOTO endreceiveserial
    IF RCSTA.OERR ON THEN ErrSerialOverr 'if overrun error occured, handle error
    IF RCSTA.FERR ON THEN ErrSerialFrame 'if framing error occurred, handle error
    ' for non-parity just use this below
    ReceiveSerial = RCREG
    SET FLAGS.GOTNEWDATA ON
    GOTO successreceiveserial
    ' for parity checking use this
    ' ParityBit = RCSTA.0    get received parity bit and save
    ' RxData = RCREG    get received data
    ' CalcParity(RxData)
    ' rotate ParityByte RIGHT  get parity bit into status.c
    ' IF STATUS.C = ParityBit THEN
    '    SET FLAGS.GOTNEWDATA ON indicate got new data
    '    ReceiveSerial = RxData
    '    GOTO successreceiveserial
    ' END IF
    ' ErrSerlParity then parity is different, error
    endreceiveserial:
    ReceiveSerial = 0
    successreceiveserial:
    end function

    sub ErrSerialOverr    'error because OERR overrun errr bit is set
                        'this code simply clears and continues
    SET RCSTA.CREN OFF
    SET RCSTA.CREN ON
    end sub

    sub ErrSerialFrame    'error because FERR framing error bit is set
    movf    RCREG,W        'discard received data that has error
    movf    RCREG,W
    movf    RCREG,W
    end sub

    sub ErrSerlParity    'error because parity bit is not correct
    end sub

     
    • Steve

      Steve - 2007-02-04

      whoops, the Setupserial subroutine should be:

      sub SetupSerial
      ADOff 'make port digital
      DIR PORTB.7 OUT
      DIR PORTB.5 IN
      SPBRG = 12            ' this value is for 9600 baud with brgh bit = 0 P16F690
      TXSTA = b'00100000'    'note, bit 2 is BRGH
      RCSTA = b'10010000' 'enable serial port and reception
      SET FLAGS.GOTNEWDATA OFF
      end sub

       
    • Stefano Bonomi

      Stefano Bonomi - 2007-03-10

      Hi Steve your code runs like a charm, but actually your PIC isn't running at 8 Mhz, only GCBasic compile your code for this speed.

      Quoted from help:

      "The #chip directive is used to specify the chip model and speed that GCBASIC must compile for. model is the model of the PIC chip - something along the lines of "16F819". speed is the speed of the chip in MHz, and is required for the delay and PWM routines."

      For let your 16F690 running at 8 Mhz you need to alter OSCCON register; in GCBasic you can do it with:

      OSCCON = 0x70 ' Setting internal oscillator to 8 Mhz

      The default speed for 16F690 is 4 Mhz

      Greetings

      Stefano Bonomi

       
    • Nobody/Anonymous

      Thanks for the source code. I just used it to test if the serial on my pic with a MAX233A works correctly on my circuit. If I have some spare time I might modify this library to be more general for other PICs with UART thanks a bunch!

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.