|
|
View previous topic :: View next topic |
Author |
Message |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
Serial problem |
Posted: Thu Aug 29, 2013 3:17 pm |
|
|
Hi, I have an 18F2620 at 40MHz (10MHz H4). The h/w uart on C6 and C7 is set at 9600Bd. I have set it to display text on a serial LCD (PHAnderson LCD117) if the text is preceded by an exclamation mark, eg. !This is text, with the following code:
Code: |
if(kbhit())
{
id = fgetc(rpi);
if(id == '!') //setup params to follow
{
fgets(dataString, rpi); //get the text
fprintf(lcd, "?y2%s", dataString); //display on serial LCD
continue;
}
} |
(char dataString[30]; is defined as a global variable)
and
Code: | #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7, stream=rpi) |
in the header file.
If I use Hyperterm on my PC or Minicom on my Raspberry Pi, it works fine.
However, I have written 2 programs, one in C++ on the PC and the other in Lazarus on the RPi and in both cases, when I send the string, all I get on the LCD is the ! and it just sits, I presume in fgets? If I send only a !, it displays it and the program continues down main. I am sending a return (13) as gets wants at the end of the text.
I am at a loss to understand why the code works with data from 2 different terminal programs but not otherwise. Can anyone help, please? I have spent all day on it and got nowhere! It must be something obvious, just not to me!! Any help most appreciated.
CCS PCWH 3.249 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 29, 2013 5:04 pm |
|
|
Quote: | fprintf(lcd, "?y2%s", dataString); |
While you're sending this to the LCD, you're not reading the UART.
If you send data to the UART without reading it, you will fill up the
hardware receive fifo (only 2-deep) and after that, the UART will be
locked up. It won't work anymore.
To automatically detect and clear this situation, add the parameter
shown in bold below. You should always do this.
Quote: | #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7, ERRORS, stream=rpi) |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Thu Aug 29, 2013 11:22 pm |
|
|
and (of course), 'long term', if you want to receive data, use interrupt driven receive - ex_sisr.c, which will receive the data while the transmission is being done.
Best Wishes |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
Serial woes |
Posted: Fri Aug 30, 2013 2:14 am |
|
|
Hi, Thanks for that. I hadn't seen 'ERRORS' documented at all. However, what I don't follow is that surely fgets will continue to call fgetc until it has collected all the sent characters and placed them in the string. Only then am I sending that data to the LCD, so why should there be the clash? I will look at ex_sisr.c as well to see if that would be better. I am also still at a loss as to why Hyperterm and Minicom do the job flawlessly. What do they have that others don't??
Thanks for your help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Fri Aug 30, 2013 3:30 am |
|
|
The key point is that the PIC only has just under two characters of hardware buffering. _One_ held received character, and the one currently arriving. As soon as more than this is received, anything else that arrives is lost.
Now, while you are sending to the serial LCD, you are not calling fgets, hence anything beyond this 1.9x characters that arrives at this point is 'gone'. When the UART overflows, it goes into an 'errors' state, and stops receiving anything. The 'ERRORS' keyword, adds code, so that the compiler will recover from this (the data is still lost, but the UART won't be hung).
Now the difference between the 'terminal', and a 'program', is that the program will probably 'steam ahead' sending characters, while a person at the terminal only types at a limited speed, and stops to check what is happening...
Hence you need (ideally) to have a larger buffer at the PIC. This is what EX_SISR, shows you how to do. Implementing a bigger buffer (as is done on the PC), so that the PIC can be receiving characters _while_ also sending them to the LCD at the same time.
Best Wishes |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Fri Aug 30, 2013 8:49 am |
|
|
Hi, I had thought that gets called getc as many times as needed before continuing, rather than it going round the loop reading one char at a time. If that is what it's doing then I can quite see it overfilling the 2 byte buffer! I tried the ERROR addition to #use rs232 and you could quite easily then see what had been lost. I have now done similar to sisr and all is fine provided I keep the baud rate down to 9600, which is plenty as there is little data coming into the PIC and a data string every ten seconds going out.
Thank very much for your help - I have learnt some and my sanity is restored!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Fri Aug 30, 2013 8:55 am |
|
|
You are missing the point.
Yes, gets, gets what is needed. However as soon as this string completes, you go off and send it using another serial port to the LCD. As soon as you go off to do this, gets is no longer being called, and you are now dependant on the buffering. How long you are 'gone', depends on the serial speed to the LCD etc.. All the time this is sending, gets, is not being called....
Best Wishes |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Fri Aug 30, 2013 9:52 am |
|
|
OK, but since no string or characters follow what gets has got, it shouldn't matter. One data string is sent and that's it until the user next decides to alter the setup information, which would typically be some weeks or months later.
Anyway, with the interrupt routine it is working very well and has defied all my attempts to break it! |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
More serial woes!! |
Posted: Sun Sep 01, 2013 12:08 pm |
|
|
Having now sorted the hardware UART, I have now found a new problem, which defies solution! I have a second software uart using pins C0 and C1. It connects to a Cirrus CS5490 electricity chip. At power up, the CS5490 defaults to 600 baud for some reason! Cirrus recommend increasing this to a higher figure before doing anything else. To do this, it is necessary to send 5 bytes; the first is a page address, the second's top 2 bits tell the 5490 that a register write is required and the remaining 6 are the register address. Then 3 bytes of data need to follow, which are the contents of the 24 bit register. That should alter the baud rate. I follow that with a revised #'use rs232 command. After that there is an 8 bit instruction to tell it to get going. I have a function to do this and apart from any bytes arriving from the computer to the hw uart, nought else is happening. However, nothing happens at all ! I tried removing the 5490 and linking rcv and tx on the PIC and I can control and read the lines, but as soon as I try to use them as a uart, nothing. I have timer1 set to disabled as it can use one of the pins as an output. I have tried to loopback using the uart, but no joy. At this point, I have run out of ideas!
Any thoughts please? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Sun Sep 01, 2013 12:35 pm |
|
|
Setup _two_ #use rs232 statements. One at each baud rate, with different stream names. Send the initial setup with the slow stream, then switch to the fast stream.
Switching baud rate on a software UART is best done this way.
Trying to use different #use rs232 statements in the code often will not work the way you expect.
Best Wishes |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
more serial woes |
Posted: Sun Sep 01, 2013 1:02 pm |
|
|
Thanks for that. Is it possible to get loopback to work with the s/w uart, so I can prove it is doing something? I have tried, but without success.
Also, if I moved the uart to say RB1 and RB2, could I then use the intext1 interrupt to allow me to have a buffer, like with the hw uart? This is all new to me!
Thanks for your advice. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Sun Sep 01, 2013 1:19 pm |
|
|
If you only have 1 HW UART, I'd use it for the Cirrus chip and use a SW UART for the LCD interface.
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19557
|
|
Posted: Sun Sep 01, 2013 2:45 pm |
|
|
Buffering a software UART, is hard:
1) You can never receive while transmitting (with the code supplied).
2) If you use an interrupt based 'trigger' for receive, the code will stay in the interrupt for one character time. If this is longer than the service interval needed by any other interrupt (like hardware RS232), it'll cause loss of data on this.
3) Interrupts have to be disabled during transmit and receive (except at very slow baud rates), or the timing will fail.
Only use software RS232, for links that are 99.9% 'transmit only', or only ever reply to things when asked.
I have in the past posted the 'core' of a timer interrupt based buffered software RS232.
Best Wishes |
|
|
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
More serial woes!! |
Posted: Sun Sep 01, 2013 3:40 pm |
|
|
Thanks for that. The CS5490 won't transmit anything unless I tell it to.
I have tried your suggestion about 2nd #use rs232 but absolutely nothing seems to be happening. After setting to 9600, I tell it to start running and to configure its digital output pin to pulse on electricity usage. It resolutely doesn't! I have treble checked the circuit for any errors and can't find any. It just seems that the software uart just isn't doing a thing. Its predecessor worked over SPI and was a doddle compared with this later chip! I now haven't a clue how to proceed! I don't really want to move ports unless I have to as it will mean butchering the circuit board. I suppose I could hang a MAX232 board on and see if the PC will talk to the PIC at all?
The joys(??) of electronics!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Sep 01, 2013 5:04 pm |
|
|
1. Make a compilable test program that only sets up the CS5490 to 9600
baud and then tests that it's working. The test program should have the
#include for the PIC, #fuses, #use delay(), and #use rs232() statements,
as well as all necessary #define statements and variable declarations,
and it should have a main(). If you can make that program, test it,
post the results and post the program, then we can work on the problem.
2. Post a list of the connections between your PIC and the UART pins on the CS5490.
3. I assume the CS5490 is running at 3.3 volts. Tell us the Vdd voltage
of your PIC.
4. Did you buy the CS5490 board or did you build it yourself ?
If you bought it, post a link to the website for it. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|