Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

RS232 Simple linear Buffer (OshonSoft Basic).

DogFlu66

Member
Hello; on this occasion I leave a simple linear buffer.
Specially applied for the RS232 port.
To avoid losing data, what is done is to add another software buffer to the hardware buffer of the pic (2 bytes). The length of the latter will depend on the user's needs and the amount of memory available. This is for those who are interested in learning how a simple buffer works and how it is complemented by the asynchronous pic module, in this case the usat module.
The input data blocking check has been implemented, since apparently those who start working with this type of port are not clear that if the pic buffer is overloaded it is blocked and stops working, and to activate it again you have to reset the control bits of the internal buffer of the pic.
If anyone sees that improvements can be made or another better algorithm can be presented, they can share it.

I leave the main program and the functions necessary for it to work as attachments.

Main program:

'Example of buffer for RS232 port
'Pic12F1840, 08/12/2023
Define CONFIG1 = 0x0f84
Define CONFIG2 = 0x1dff
Include "_FuncionesPic12F1840.bas"
Include "_Funciones_Buffer_RS232.Bas"
Define CLOCK_FREQUENCY = 32 '32Mhz system oscillator
'constants (ASCII control codes).
Const FF = 0x0c 'FF, page advance
Const Bell = 0x07 'Bell, sound signal
Const Sp = 0x20 'Sp, space
Const Bksp = 0x08 'Bksp, go back
'Const Cr = 0x0d 'Cr, car return
'Const Lf = 0x0a 'Lf, line break
Const Ctrlz = 0x1a 'Ctrl - Z
Const Esc = 0x1b 'Escape
main:
'Call _setup_oscillator_mode(_oscillator_by_fosc) 'Select by configuration word.
Call _setup_oscillator(_osc_32mhz_hf) 'Interno 8Mhz x 4(PLL) = 32Mhz
AllDigital
TRISA = 0xff

UART_Init 9600 'Initialize port pin (default: A0 = Tx, RA1 = Rx)
Call _uart_pin_tx_ra4(True) 'Pin Tx = RA4
Call _uart_pin_rx_ra5(True) 'Pin Rx = RA5
WaitMs 10

Call _setup_buffer_rs232() 'Initialize buffer by software
Call _enable_interrupts(_int_rda) 'Enables uart interrupts
Call _enable_interrupts(_global) 'Enables peripheral and global interrupts.

Dim data As Byte

UART_Write "Ready", CrLf

While True

If _buffer() = True Then 'If there is data in the buffer.
'data = _read_buffer_rs232()'Reads byte fron buffer and assigns it to a variable.
'UART1_Write data'Write the byte to the serial port.
UART_Write _read_buffer_rs232() 'Reads byte fron buffer and write to the serial port.
Endif
Wend
End
On Interrupt
Save System
If _uartif = True Then 'If there is data in the uart hardware buffer.
Call _get_rs232() 'Moves a byte from the hardware buffer to the software buffer.
Endif
Resume
 

Attachments

  • _FuncionesPic12F1840.bas
    31.6 KB · Views: 144
  • _Funciones_Buffer_RS232.Bas
    3.5 KB · Views: 122
Last edited:
I advise you to use a ringbuffer better, I attach the library, try it separately and when you understand how it works, incorporate it into your program.
_BUFFER > 0: There is data in the buffer.
_Receive(10): Sometimes, when we anticipate the arrival of a frame, advancing ahead of its bytes can lead to reading errors. The '10' parameter is used to introduce a delay if the frame's entry is slower than usual, waiting 10 milliseconds to adapt to the frame byte input speed. This adjustment is unrelated to the baud rate.

The issue is complex and not straightforward to implement, as each code has its unique characteristics.

Include "_FuncionesUartRingBuffer.bas"
Call _Interrupts_Mode(_DISABLE_PRIORITY)
UART1_Init 115200
Call _SetUpRBF() 'Initialize buffer by software
Call _Enable_Interrupts(_INT_RDA) 'Enables uart interrupts
Call _Enable_Interrupts(_GLOBAL_HIGH) 'Enables peripheral and global interrupts.
'Main
While True
If _BUFFER > 0 Then 'If there is data in the buffer.
UART1_Write _Receive(10) 'Reads byte fron buffer and write to the serial port.
Endif
Wend
End
On High Interrupt
Save System
If _UAR1IF = True Then 'If there is data in the uart hardware buffer.
Call _RingBuffer() 'Moves a byte from the hardware buffer to the software buffer.
Endif
Resume
Hi D,
I've modified the above for the Oshonsoft simulator.
It's fairly certain that there will be errors, so please check.

As it is here, it outputs the entered DATA, as seen, but once that DATA has gone through the buffer, and it reaches '0' then it won't allow any more DATA through the buffer.
C.

Ring buffer result.jpg
 

Attachments

  • '18F4431 32MHz XTL PCB9 REMOTE_SLAVE RING_BUFFER SERVO 190524 0802.bas
    4.4 KB · Views: 30
  • _FuncionesUartRingBuffer.bas
    4.5 KB · Views: 29
Hello; I have tested it both in physics and in simulation and it works for me, even overloading the buffer with several hundred pieces of data at a time and it works for me. Ok. That is for the Pic18F26K22.
 

Attachments

  • '18F4431 32MHz XTL PCB9 REMOTE_SLAVE RING_BUFFER SERVO 190524 0802.bas
    5.2 KB · Views: 30
Hello; I have tested it both in physics and in simulation and it works for me, even overloading the buffer with several hundred pieces of data at a time and it works for me. Ok. That is for the Pic18F26K22.
Hi D,
Can you post the INCLUDES and CALLs please? I think I cause errors when I use my set-up.
C
 
Ok, here they are.
 

Attachments

  • 18F4431 32MHz XTL PCB9 REMOTE_SLAVE RING_BUFFER SERVO 190524 0802.bas
    5.2 KB · Views: 32
  • _FuncionesUartRingBuffer.bas
    4.5 KB · Views: 31
  • _Pic18F26K22Library.bas
    46.4 KB · Views: 31
  • _SetUpAmicus18.bas
    2.9 KB · Views: 33
Ok, here they are.
Hi D,
Thanks.

EDIT: I put all of your files in a separate folder, opened the 18F4431 program, changed it to 18F25K22 in OSH, and it wouldn't compile!
Then I saw that it appears that you don't use this program but the 'uartringbuffer as your program?, but this also didn't compile and showed errors.
Will you tell me how you open it please, and which files are in your folder.

Can anyone else try the files in #25 also please?
C
 
Last edited:
Hi D,
Something is strange! As mentioned I put your files in a separate folder and for me it failed.
I went back to the original folder, where the almost working programs are and they now fail.
It appears that Oshonsoft has been broken!
I'll let you know what happens.
C.
 
You have to select Pic18F46K22 to compile, and use the functions for ringbuffer, which is the one that is properly tested.
Hi D,
I'm a bit confused! I looked up Amicus18 and see it is for another PIC, and there's mention of different PIC dotted around. I'm not as skilled as you at programming, so easily confused.
I changed to 1846K22 and the first error is this: see attached.
I'm sure I can figure it out, but: Why don't you get this error?
C
 

Attachments

  • Error.jpg
    Error.jpg
    375.3 KB · Views: 36
The Pic18F46K22 and Pic18F26K22 are compatible microcontrollers, with the main differences being the amount of RAM and the number of pins. A .hex file generated for the Pic18F46K22 can be loaded onto a Pic18F26K22 as long as it doesn't use resources or modules that the Pic18F26K22 lacks.

In the Amicus development environment, I don't use the default microcontroller. Instead, I use the Pic18F26K22, which has the same pin layout but superior features. However, I compile the code for the Pic18F46K22 rather than the Pic18F26K22. This is because your program references port D, which is not present in the Pic18F26K22. By doing this, I can compile your program without any modifications for a Pic18F46K22, ensuring there are no errors. Then, I load the .hex file onto a physical Pic18F26K22 to test your program in a real-world environment.

Regarding the rest, I have no compilation errors, so you do have to make sure you use the latest libraries, the ones I have uploaded, because I have updated them and therefore modified them. The library for the Pic18F26K22 is compatible with the Pic18F46K22, in the future when the library for the Pic18F46K22 is finished it will surely not be compatible with the 18F26K22 because the 18F46K22 has more modules than the other.
 
Last edited:
The Pic18F46K22 and Pic18F26K22 are compatible microcontrollers, with the main differences being the amount of RAM and the number of pins. A .hex file generated for the Pic18F46K22 can be loaded onto a Pic18F26K22 as long as it doesn't use resources or modules that the Pic18F26K22 lacks.

In the Amicus development environment, I don't use the default microcontroller. Instead, I use the Pic18F26K22, which has the same pin layout but superior features. However, I compile the code for the Pic18F46K22 rather than the Pic18F26K22. This is because your program references port D, which is not present in the Pic18F26K22. By doing this, I can compile your program without any modifications for a Pic18F46K22, ensuring there are no errors. Then, I load the .hex file onto a physical Pic18F26K22 to test your program in a real-world environment.

Regarding the rest, I have no compilation errors, so you do have to make sure you use the latest libraries, the ones I have uploaded, because I have updated them and therefore modified them. The library for the Pic18F26K22 is compatible with the Pic18F46K22, in the future when the library for the Pic18F46K22 is finished it will surely not be compatible with the 18F26K22 because the 18F46K22 has more modules than the other.
Hi D,
It's working :) It was also working at #22, but I use the OSH simulator, and it is slow once [ _BUFFER =0 ] so I wasn't waiting long enough.

Now I see it working, I can watch it in the sim, so that I fully understand it.
Thanks.
EDIT: REMOVED

The way I've got it, the LED doesn't TOGGLE, I'm guessing that it should be within the WAIT-WEND, is this correct. To use your RING_BUFFER, I will need to add my CODE, where should I add it?
C
Code:
main:

Toggle rled

While True
    If _Buffer > 0 Then  'If there is data in the buffer.
        data = _Receive(10)  'Reads byte fron buffer and assigns it to a variable.
        UART1_Write data  'Write the byte to the serial port.
        UART_Write _Receive(10)  'Reads byte fron buffer and write to the serial port.
    Endif
Wend


While True
    If _BUFFER > 0 Then 'If there is data in the buffer.
    UART1_Write _Receive(10) 'Reads byte fron buffer and write to the serial port.
    Endif
Wend

Goto main
 
Last edited:
I advise you to use a ringbuffer better,

Using one buffer or another isn't the most important thing; what matters is that you can't stop receiving input data while you're doing something else. The reception of input data cannot be interrupted, or you will have problems. In the buffer, each time a byte is read, it is destroyed, making room for a new incoming byte. The input process never stops. You can either process the read byte in real-time or store it in a variable to process once the variable is full. Be mindful of the header byte and the end byte; in your case, the header byte is "$".
Hi D,
We use a linear buffer at the moment, that works well, but blocks. I think you suggest in the above that it will be avoided if this method is used, ok.

_Receive(10): Sometimes, when we anticipate the arrival of a frame, advancing ahead of its bytes can lead to reading errors. The '10' parameter is used to introduce a delay if the frame's entry is slower than usual, waiting 10 milliseconds to adapt to the frame byte input speed. This adjustment is unrelated to the baud rate.
Interesting!
The issue is complex and not straightforward to implement, as each code has its unique characteristics.
This is probably why I can't see why the CODEs block in my project.

The GPS UART is set for the fastest/most accurate speed of 5/sec, but my system can't PARSE at that speed so I'm used to switching the UART OFF/ON while PARSING.

I sensed that reading every input is wasteful and not time saving, but it appears that things happen so fast that it isn't relevant, is this true?

I'm not sure if I'm skilled enough to incorporate your methods into the existing method of GPS reading, but I'll try. I am getting help :)

Maybe incorporating some of you system to use with a linear buffer would suit best.

Thanks, C.
 
Last edited:
Hi D,
It's working :) It was also working at #22, but I use the OSH simulator, and it is slow once [ _BUFFER =0 ] so I wasn't waiting long enough.

Now I see it working, I can watch it in the sim, so that I fully understand it.
Thanks.
EDIT: REMOVED

The way I've got it, the LED doesn't TOGGLE, I'm guessing that it should be within the WAIT-WEND, is this correct. To use your RING_BUFFER, I will need to add my CODE, where should I add it?
C
Code:
main:

Toggle rled

While True
    If _Buffer > 0 Then  'If there is data in the buffer.
        data = _Receive(10)  'Reads byte fron buffer and assigns it to a variable.
        UART1_Write data  'Write the byte to the serial port.
        'UART_Write _Receive(10)  'Reads byte fron buffer and write to the serial port.
    Endif
Wend


While True
    If _BUFFER > 0 Then 'If there is data in the buffer.
    UART1_Write _Receive(10) 'Reads byte fron buffer and write to the serial port.
    Endif
Wend

Goto main
Code:
main:
While True

Toggle rled

'While True
    If _Buffer > 0 Then  'If there is data in the buffer.
        data = _Receive(10)  'Reads byte fron buffer and assigns it to a variable.
        UART1_Write data  'Write the byte to the serial port.
        UART_Write _Receive(10)  'Reads byte fron buffer and write to the serial port.
    Endif
'Wend


'While True
    If _BUFFER > 0 Then 'If there is data in the buffer.
    UART1_Write _Receive(10) 'Reads byte fron buffer and write to the serial port.
    Endif

Wend

Goto main

The buffer has its own flags and is managed by leaving it in the main code.
 
Last edited:
Code:
main:
While True

Toggle rled

'While True
    If _Buffer > 0 Then  'If there is data in the buffer.
        data = _Receive(10)  'Reads byte fron buffer and assigns it to a variable.
        UART1_Write data  'Write the byte to the serial port.
        UART_Write _Receive(10)  'Reads byte fron buffer and write to the serial port.
    Endif
'Wend


'While True
    If _BUFFER > 0 Then 'If there is data in the buffer.
    UART1_Write _Receive(10) 'Reads byte fron buffer and write to the serial port.
    Endif

Wend

Goto main

The buffer has its own flags and is managed by leaving it in the main code.
Hi D,
As the ringbuffer can't be used to it's full capacity, due to lack of speed of my system, I think this idea may be ok:->->

I've used your #25 CODE but can now spot a $ in the DATA, which is the start of sentences, so I set the BUFFER to '0' which I resume makes it a linear BUFFER, but I think this will suit my system.

I should soon be able to test if it blocks or not,
EDIT: It didn't work:arghh:
Thanks, C.
 
Last edited:
data = _Receive(10) 'Reads the byte from the buffer and assigns it to a variable.
UART1_Write data 'Write the byte to the serial port.
'UART_Write _Receive(10) 'Reads bytes from the buffer and writes to the serial port.

Only one _Receive is used, you use one or the other.
Remember that every time a byte is read from the buffer it is destroyed to leave the buffer byte free.
 
Last edited:
data = _Receive(10) 'Reads the byte from the buffer and assigns it to a variable.
UART1_Write data 'Write the byte to the serial port.
'UART_Write _Receive(10) 'Reads bytes from the buffer and writes to the serial port.

Only one _Receive is used, you use one or the other.
Remember that every time a byte is read from the buffer it is destroyed to leave the buffer byte free.
Hi D,
Thanks, I'll try that.
C
 
You may need to extend the buffer length. The good thing about having a buffer is that the data is stored until processed.

Modify the following in the Include "_FuncionesUartRingBuffer.bas" libraries:

'Shared variables in serial port functions
Const _LgBf =999 'Number of bytes of the _buffer minus one.
Dim _RxHdBf(1000) As Byte '_Buffer by software
 
You may need to extend the buffer length. The good thing about having a buffer is that the data is stored until processed.

Modify the following in the Include "_FuncionesUartRingBuffer.bas" libraries:

'Shared variables in serial port functions
Const _LgBf =999 'Number of bytes of the _buffer minus one.
Dim _RxHdBf(1000) As Byte '_Buffer by software
Hi D,
Ok, thanks.
I've got it to copy a GPS sentence (73=my max needs) into a second buffer, but so far only one?

EDIT: I've now been able to copy every update, so next, I need to hold the second buffer without updating, while I PARSE it, then re-load.

In order to see what's happeneing in the SIM, I've moved the INCLUDES into the main program.
C.
 
Last edited:
Deleted,
In SIM it can take 1ms to move a CHAR into the buffer, I thought it was stalling.
C
 

Attachments

  • Stalling.jpg
    Stalling.jpg
    230 KB · Views: 21
Last edited:
Deleted,
In SIM it can take 1ms to move a CHAR into the buffer, I thought it was stalling.
C
In the example image you continue making two readings and two sendings to the serial port. Only one read can be made with each buffer comparison. By doing two readings and two shipments in a row you are slowing down the system. And by making two readings in a row without checking the buffer each time, the buffer may run out of data and cause a slowdown of up to 10mSec.

If buffer > 0 then
data = _Receiver(10)
Processed frame code, if data in the buffer has a complete frame or more than one frame.
Endif

That is why a buffer is used to process received frames when possible, hence the need to have a buffer that can hold several frames at the same time.

I insist, it is very important that the buffer is long enough to be able to store several frames at the same time, this way you do not depend on the time or speed of the micro to process them, process them when you can.
 
Back
Top