View previous topic :: View next topic |
Author |
Message |
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
Setting up a software UART |
Posted: Mon Nov 21, 2022 11:00 pm |
|
|
I am using the PIC18LF46K22 MCU, CCS C compiler v5.113, and MPLAB IDE v8.92.
I tested the following program for a software UART, to check whether I was able to receive the transmitted data. The RCV pin is the INT0 interrupt pin. The compiled program was loaded onto the MCU and I used the Terminal.exe interface to send and receive data.
Code: | #include "18LF46K22.h"
#fuses INTRC_IO
#use delay(clock=16000000)
#use rs232(baud=9600, xmit=pin_A6, rcv=pin_B0, disable_ints, sample_early, errors, stream=UART_db)
#int_ext
void f_int_ext_isr()
{
/* Echo back received byte */
fputc(fgetc(UART_db), UART_db);
}
void main()
{
ext_int_edge(0, H_to_L);
clear_interrupt(int_ext);
enable_interrupts(int_ext);
enable_interrupts(global);
while (true);
} |
Results:
1. When I sent “$CA$06$01$00$C1$34$01$39”, the program only echoed back “CA 01 C1 01” (only bytes 1, 3, 5, 7).
2. When I sent “$CA$0E$01$00$C1$34$56$78$90$AA$BB$CC$DD$EE$01$61”, the program only echoed back “CA 01 C1 56 90 BB DD 01” (only bytes 1, 3, 5, 7, 9, 11, 13, 15).
3. The program always skips the even byte.
Question:
What should I do to get the program to work properly?
I will appreciate any ideas or advice. Thank you. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 21, 2022 11:49 pm |
|
|
A soft uart can only do one thing at a time. If it's doing fputc() in the isr
then it can't exit to main() and get the next INT0 interrupt for the next
incoming byte. You're transmitting a byte when the next one comes in
so you miss it.
Save the whole message in a large buffer. Then when it's done, send the
whole message back. Put a marker byte in the message sent to the PIC
to show the end of the message. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Tue Nov 22, 2022 1:56 am |
|
|
If you really 'must' use a software serial, and need to have other things
happening while you are receiving, there is another approach to doing such
serial.
I posted in the code forum a while ago, a software serial done by using
a timer:
[url]
http://www.ccsinfo.com/forum/viewtopic.php?t=51403&highlight=timer+serial
[/url]
This generates a buffered serial receive done by sampling the pin at
intervals 4* the baud rate.
This can also be adapted to provide transmit as well.
Keeping it to one job at a time by only sending when receive is not
happening, is much simpler, but solutions can be written if this can't be
avoided. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Nov 22, 2022 6:22 am |
|
|
hmm, I was curious to see if the 46k22 was available ( next year..) but their recommended alternate the PIC18F46Q10 is !!
It not only has FIVE UARTs, it's 1/2 the price !!
but, I'd have to upgrade my compiler.
Just wanted to point out another way to get a 3rd UART.
Jay |
|
|
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
|
Posted: Tue Dec 27, 2022 9:27 am |
|
|
Sorry for this late acknowledgement.
Thank you all very much for your input.
It was good that Temtronic brought up the possibility of the PIC18LF46K22 being discontinued. We will be keeping a close watch on this MCU as we are using it in a number of our products.
Yes, we have used up the two hardware UARTs available on the PIC18LF46K22, and that is why we have to use a software UART.
I have managed to get the software UART working quite reliably now, except that sometimes the Terminal program shows garbage for a short while, and then reverts to showing the characters correctly.
Also, I have a program (hex file) that prints some text before the master while (true) loop through the software UART to the Terminal screen every time it runs. However, every time the program runs, the same garbage always appears in the same print location, but the corresponding fprintf statement where the garbage occurs is just like the other fprintf statements that print correctly.
Is there any way to minimize the occurrence of such garbage?
I will appreciate any ideas. Thank you. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Tue Dec 27, 2022 11:10 am |
|
|
Not discontinued, just sometimes unavailable due to supply shortages. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Tue Dec 27, 2022 11:54 am |
|
|
It is not clear how the hardware is actually done?.
If it is using a MAX232 type chip, the charge pumps in these do take a
little time to generate the full output voltage. Hence code generally needs
to start by explicitly setting the TX bit high, and then waiting for a few
mSec before starting a transmission. Generally something like 15mSec is
needed before the level can be guaranteed. A chip that starts and
immediately sends will commonly find the first few characters are corrupted. |
|
|
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
|
Posted: Fri Dec 30, 2022 3:39 am |
|
|
Thank you, gaugeguy, for pointing out my misunderstanding.
Thank you, Ttelmah, for the tip.
I tried this tip on the software UART by setting the TX bit to high before the fprintf statement where the character corruption occurs, and it works!
My fprintf problem occurred in a function, and I realized that at the beginning of the function, I had set the TX bit of the software UART to low, to minimize current consumption. Code: | output_low(debug_tx_pin);
…
output_high(debug_tx_pin);
delay_ms(20);
fprintf(UART_db, "Master oscillator settings:\n");
fprintf ...;
… |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Dec 30, 2022 10:20 am |
|
|
Dropping TX, is explicitly sending a 'start', so not surprisng you were
seing spurious characters!.
Glad you have it working now.
Happy New Year everybody. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sat Dec 31, 2022 7:20 am |
|
|
Nice it's 'up and running' !
If you're concerned about saving power, you may be able to reduce the delay_ms(20).
try 15 and see if it's 100% working. if not, try 17, try again.
Even if you have to use delay_ms(19), you've saved '1ms of power'. Not much but saving a few electrons and some there, does add up ! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sat Dec 31, 2022 8:06 am |
|
|
Also, if the signal being high draws more power, then you need to ask 'why'.
Generally on the outputs themselves it is changing the level that draws
power. Being stable high or low should not make any difference, unless
there is some pull-up/pull-down involved in what is being driven. |
|
|
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
|
Posted: Sun Jan 15, 2023 2:17 am |
|
|
Thank you, Ttelmah and Temtronic, for your advice.
Quote: | If you're concerned about saving power, you may be able to reduce the delay_ms(20).
| Temtronic: I tested the delay time all the way down to zero (no delay), and it still works -- repeatedly without corrupted characters! I now do not use any delay after the "output_high(debug_tx_pin)" statement.
Quote: | Generally on the outputs themselves it is changing the level that draws power. Being stable high or low should not make any difference, unless there is some pull-up/pull-down involved in what is being driven.
| Ttelmah, your comment prompted me to test how the state of the TX pin affects the current consumption. It turned out that setting it to high or low makes no difference to the current consumption! So now, I just set it to high and leave it that way (without resetting it to low later).
Thank you for your help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sun Jan 15, 2023 6:58 am |
|
|
Great news. |
|
|
|