# Software Usart

Status
Not open for further replies.

#### mastero

##### Member
Hello all,

PIC16f675

Wanna know is there a way to assign software usart bit in Oshonsoft.

Something like this, this is for pic 10 need for pic 16

Define serout_reg = portb
Define serout_bit = 5
Define serout_baud = 9600

any help shall be good

cheers
mastero

#### ericgibbs

##### Well-Known Member
hi m,
Clip from OSH manual.
E
Software UART implementation . Index

On all supported PIC devices software serial communication can be implemented with SEROUT and SERIN statements.

The first argument of both statements must be one of the microcontroller's pins, and
the second argument is baud rate: 300, 600, 1200, 2400, 4800, 9600 or 19200.

Using higher baud rates with low clock frequency could cause framing errors.

For SEROUT statement then follows the list of arguments to be sent to serial port.
You can use strings, LF keyword for Line Feed character or CRLF keyword for Carriage Return - Line Feed sequence,

constants and variables.
If '#' sign is used before the name of a variable then its decimal representation is sent to the serial port.

SEROUT statement uses SEROUT_DELAYUS parameter that can be set by DEFINE directive and has default value of 1000 microseconds.
This defines the delay interval before a character is actually sent to the port and it is used to increase the reliability of software SEROUT routine.

For SERIN statement then follows the list of Byte and Word variables to be loaded with the values received on serial port.

This statement will wait until the required number of bytes is received on serial port.

For serial interface with inverted logic levels there are SERININV and SEROUTINV statements available.

Some examples:

DEFINE SEROUT_DELAYUS = 5000
SEROUT PORTC.6, 1200, "Hello world!", CrLf
DIM I AS BYTE loop:
SERIN PORTC.7, 9600, I
SEROUT PORTC.6, 9600, "Number: ", #I, CrLf
GOTO loop

#### mastero

##### Member
Hello Eric,

This clip from OSH manual, i know very well ....... but i don't want to use it.

I need to know can i assign a software usrat bit in define or somewhere.

Below is the snip of my code it works for hardware USART but need to use PIC16F675 which does not have hardware Usart.

Any idea or direction will good .

Mastero

Code:
Hseropen 9600

'set up interrupts
PIE1.RCIE = 1
INTCON.PEIE = 1
INTCON.GIE = 1

'main loop
'******************************************************************************
main:
If outptr > 0 Then ; a valid packet has arrived
led = 1
WaitMs 100
led = 0
outptr = 0
Endif
WaitMs 100
Goto main
End
'******************************************************************************
On High Interrupt
Save System
If rcsta.oerr = True Then ; any error reboot serial module..
rcsta.cren = 0
rcsta.cren = 1
Goto finish
Endif

buffer(inptr) = rcreg  'get data and store in buffer (reading clears the rcif)

If buffer(inptr) = "#" Then outptr = inptr  'flag when # received

inptr = inptr + 1
If inptr = 10 Then inptr = 0  'buffer reset

finish:
Resume

#### sagor1

##### Active Member
I'm assuming you mean 12F675.
Serial is by "bit banging", using internal timing loops. You should not use any Interrupts if using software serial, as it will mess up the timing of the serial software loops (unless really short interrupt like 10-20uS).
With software serial, there is no notification that a character has been received, it is all done with the SERIN command, which waits forever for a character to be received.
SEROUT is the same issue, the code waits until all the bits have been sent by software emulation before continuing.
Software serial is critical of clock frequency, the chip must be calibrated if using internal clock, but better still to use an external crystal. You must Define the proper frequency the chip is running at.

Once SERIN is completed, you can check what the character is, but there is no validity check on it (if serial timing is off...). You can set a timer interrupt to cancel the SERIN command, to check if the character is zero with the definitions:
SERIN_TIMEOUT_REG
SERIN_TIMEOUT_BIT
where the register is either a timer bit or even a GPIO bit (any register is valid to use here, if you can control the bits). I used a 12F675 to read a serial data stream, making sure every character was in the proper position and proper format by using a read subroutine(s). Any character that was not correct, I set the success flag as zero and just read the stream until end was seen, then start all over waiting for next stream of data. Always wait for start of message, read data expected, read end of message character. If ok, then set "ok" flag to one.

Example (not complete code, just example of reading data stream with fixed format, else reject). Used a GPIO pin to interrupt the read (SERIN):

Define SERIN_TIMEOUT_REG = GPIO 'set interupt register and
Define SERIN_TIMEOUT_BIT = 3 'set which register bit - use push button switch
Symbol switch = GPIO.3 'push button input to +5V (pin has pulldown resistor)
Symbol rcx = GPIO.0 'software serial input pin

...code...
If ok = 1 Then 'complete command received...
....more code
END

Serin rcx, 9600, arg1 'read a character
If switch = 1 Then ok = 0 'button pressed, abort
Return

getack: 'Routine to get ack from our commands
ok = 0 'flag used to indicate status

findstart:
If switch = 1 Then Return
If arg1 <> som Then Goto findstart 'Wait for "Start of Message" symbol
If arg1 = 0 Then Return
If arg1 <> command0 Then Goto nope
If arg1 = 0 Then Return
If arg1 <> command1 Then Goto nope
If arg1 = 0 Then Return
If arg1 <> command2 Then Goto nope
If arg1 = 0 Then Return
If arg1 = command3 Then ok = 1 'Valid command received
nope:
Gosub readbyte 'read until EOM is seen and ignore rest
If switch = 1 Then Return
If arg1 <> eom Then Goto nope 'Keep reading until end of message
Return

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
If you combine the serin with your int pin you can generate an interrupt and read the serin manually..

Personally I would write my own serin routine... Basically it'll be a function that happens to be your interrupt.

If you can wait I could possibly write you one..

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I've been trawling the microchip site... Pic16f675 isn't a chip... Are you using the pic12f675???

I would look into the pic12f1822 and pic12f1840... Pin compatible and they have a hardware serial module..

#### ericgibbs

##### Well-Known Member
I've been trawling the microchip site... Pic16f675 isn't a chip... Are you using the pic12f675???
I also had no luck finding the 16F675 datasheet.

I would consider a 'mix' of OSH Basic and assembler code would be OK for the Uart prog.

#### mastero

##### Member
hey sorry guys i meant 12f675 or 12f629 .....my BAD sorry.

The 12f1822 has E-usart, and will have to call a sample from microchip to try it.. not readily avalible here in India.

Ian i have all the time in the world. if you can write me one nothing like it.

eric i was also thinking the same ASM: but don't know the ASM code for it..

progress till now .....

I have made the RX and TX program on OSHO for 16f628A both RX and TX end. works with both 315 and 434 modules works perfectly no noise no issue no drops etc....

wanted to move to 675 or 629 for space saving and small foot print.

mastero

#### sagor1

##### Active Member
Mastero, I would strongly recommend using an external crystal clock (HS mode) if doing software serial communications. I had tried using the internal clock at 4Mhz, and always got errors at 9600 baud. The issue is the internal clock does drift as the chip heats up or cools down (for 12F675/629).
The Oshonsoft compiler will list the estimated error of the TX and RX software serial in the compiled listings, for either hardware UART or software serial, based on the clock frequency you specify. I found that a 8Mhz crystal is the most accurate overall (both directions) for 9600 software serial.
This is a little table I had made up for a different chip, but lists the expected serial errors at 9600 for various crystal frequencies (most common ones):
HSER is the hardware error %, SER is the software error % (TX/RX). Note that 4Mhz has over 2% error on RX. Now, with a long SEROUT_DELAYUS, these errors may not be as big an issue.

'Clock vs baud rates, Error % for Hardware, software TX/RX (or same) for 16F688 at 9600
'Define CLOCK_FREQUENCY = 4.0 'Hser = 0.16%, 1.13/2.12%
'Define CLOCK_FREQUENCY = 7.3728 'Hser = 0 Ser = 1.05/0%
Define CLOCK_FREQUENCY = 8.0 'Hser = 0.16%, Ser = 0.16/0.64%
'Define CLOCK_FREQUENCY = 11.0592 'Hser = 0, Ser = 0.69/0%
'Define CLOCK_FREQUENCY = 12 'Hser =0.16%, Ser = 0.8/0.16%
'Define CLOCK_FREQUENCY = 13.560 'Hser = 0.31%, Ser = 0.89%
'Define CLOCK_FREQUENCY = 14.31818 'Hser =0.23%, Ser = 0.77%
'Define CLOCK_FREQUENCY = 14.7456 'Hser = 0% Ser = 0.52%
'Define CLOCK_FREQUENCY = 16 'Hser = 0.16%, Ser = 0.64%
'Define CLOCK_FREQUENCY = 20 'Hser = 0.16%, Ser = 0.74/0.54%

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I've used software serial on the pic12f675 very successfully... The error is only 1.1% (9700 baud) BUT!!!! You must use the OSCCAL value or the 4Mhz frequency is too far out...

If you have re-programmed the pic12f675 then this value is lost... I use pickit2 to re-insert the OSCCAL value

You need to load the value at 0x3FF into the OSCCAL value on startup You may have to do this in asm as oshonsoft hasn't allowed this to happen..

When you boot pickit2's small interface, you can calculate this value AND!!! the bandgap... once the chip is running at the correct frequency the baud rate will be perfect!

#### mastero

##### Member
Should i add this in my code ?

ASM: bsf STATUS,RP0 ;bank 1
ASM: call 3ffh ;get the cal value
ASM: movwf OSCCAL ;calibrate
ASM: bcf STATUS,RP0 ;bank 0

or have a better suggestion ?

I am using PICkit3 and there is only osccal insert manually option.

#### mastero

##### Member
ok .... progress till now:~

RX is with 16f628A ........NO ISSUES

TX is with 12f629 or 12f675 or 12f683.........major issues

Tried till now

a) Osccal auto regenerate in piclit2 ..... showed Osccal 3448 osccal and bandgap 0000 generated successfully.......failed
b) Bought new chips which had osccal 3454 bandgap 1000 @ 8mhz. ....failed

c) Same chip same software just this time with external 4mhz resonator works perfectly.

any ideas here will be great

cheers
mastero

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Somewhere on the net you will find an Osccal circuit... One that will generate the values.. Im on an iPad and I hate browsing with it... Type osccal circuit into Google,..

#### mastero

##### Member
seen that ian thanks ..... just went with 16f628A ssop for small foot print and also needed extra pins for the project.

#### mastero

##### Member
Hello again...,

just landed into a new corner....

The code is as follows

Code:
Hseropen 9600

'set up interrupts
PIE1.RCIE = 1
INTCON.PEIE = 1
INTCON.GIE = 1

'main loop
'******************************************************************************
main:
If outptr > 0 Then ; a valid packet has arrived
led = 1
WaitMs 100
led = 0
outptr = 0
Endif
WaitMs 100
Goto main
End
'******************************************************************************
On High Interrupt
Save System
If rcsta.oerr = True Then ; any error reboot serial module..
rcsta.cren = 0
rcsta.cren = 1
Goto finish
Endif

buffer(inptr) = rcreg  'get data and store in buffer (reading clears the rcif)

If buffer(inptr) = "#" Then outptr = inptr  'flag when # received

inptr = inptr + 1
If inptr = 10 Then inptr = 0  'buffer reset

finish:
Resume
The problem is ....

Works perfectly with some 16f628A and some it does not read the incoming msg on RX pin

Any Idea ?

Also the one which works reads the incoming msg the second time

Hardware is Em-18 RFID reader TX pin to MCU RX pin direct connection.

cheers
Mastero

Forum Supporter