|
|
View previous topic :: View next topic |
Author |
Message |
Alphada
Joined: 19 Jun 2017 Posts: 27
|
PIC 16F1615 (RDA interrupt) not firing |
Posted: Mon Jun 19, 2017 5:00 pm |
|
|
I have a 16F1615 I'm trying to receive commands on the chip through rs232 but the RDA interrupt won't fire by any means. I hear that the soft UART can't handle RDA interrupt but in the data sheet it states that it has one UART port. But I'm not sure how to check in the datasheet if it's hardware or software. I'm using it on port C4 for Tx and C5 for Rx(CK). Not sure why this chip doesn't have Rx pin. For some reason in the datasheet it states the port as EUART (no idea why).
My questions are how do i know if the chip really has UART hardware? And if else how could i get rid of the incoming characters without using fgetc, because it disrupts the program by having to wait for characters.
Help and Guidance Appreciated. I'm really new regarding MCUs as you can notice. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 19, 2017 9:19 pm |
|
|
Alphada wrote: |
The RDA interrupt won't fire by any means.
|
Try this. If it doesn't work, then post your CCS compiler version.
Code: | #include <16F1615.h>
#FUSES INTRC_IO, NOWDT, BROWNOUT
#use delay(clock=4MHz)
#pin_select U1TX=PIN_C4
#pin_select U1RX=PIN_C5
#use rs232(baud=9600, UART1, ERRORS)
#int_rda
void rda_isr(void)
{
char c;
c = getc();
putc(c);
}
//==============================
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE);
} |
Alphada wrote: |
My questions are how do i know if the chip really has UART hardware?
|
Set the .LST file in Symbolic mode in the compiler options window.
Then compile and look at the .LST file. See below. The rs232 library
code is clearly talking to the UART's hardware registers. So the compiler
is using the hardware UART:
Code: | ........... #use rs232(baud=9600, UART1, ERRORS)
0021: BTFSS PIR1.RCIF
0022: GOTO 021
0023: MOVLB 03
0024: MOVF RC1STA,W
0025: MOVLB 00
0026: MOVWF rs232_errors
0027: MOVLB 03
0028: MOVF RC1REG,W
0029: MOVWF @78
002A: MOVLB 00
002B: BTFSS rs232_errors.1
002C: GOTO 031
002D: MOVLB 03
002E: BCF RC1STA.CREN
002F: BSF RC1STA.CREN
0030: MOVLB 00
*
0034: BTFSS PIR1.TXIF
0035: GOTO 034
0036: MOVLB 03
0037: MOVWF TX1REG |
Alphada wrote: |
how could i get rid of the incoming characters without using fgetc,
because it disrupts the program by having to wait for characters.
|
Call kbhit. If it returns true, then call fgetc(). If it returns false, then
don't call it. kbhit() will accept a Stream as the parameter. If you
are using streams, then do that. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Tue Jun 20, 2017 5:26 am |
|
|
re:
Not sure why this chip doesn't have Rx pin. For some reason in the datasheet it states the port as EUART (no idea why).
...EUART means 'Enhanced' UART, it has several features that a 'regular' UART doesn't. Chapter 25 or 26, explains this.
That PIC is one of the newer generation that has PPS (Peripheral Pin Select). As the programmer YOU get to choose (within limits..) what pin has which peripheral attached to it. While there is a default configuration of these special pins they probably are not what you need them to be. Mr. T's program shows the code necessary to set them up as required.
The EUART section (25 or 26) does detail that is it a HARDWARE UART and yes, reading 30-40 pages can be, yawn, boring.. BUT...there is a wealth of important information in there ! Also the UART is a very common peripheral amongst PICs so once you understand one version, the others are easy (well, easier..)
One thing about CCS is that even though there is a HW UART, they may code for a SW UART. Again Mr. T. shows that the listing will detail where the data goes... Just remember that the HW UART MUST be a certain pair of pins ! You cannot use any 2 pins so read the datasheet BEFORE laying out the PCB !
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Jun 20, 2017 9:10 am |
|
|
This is an area where we need to expand on CCS's manual.
On a chip without PPS, if you select the hardware UART pins in #USE RS232, the compiler 'defaults' to selecting the hardware UART.
On a chip with PPS, even if the manual shows 'default' pins, the compiler will not assume the hardware UART is there. On these you must always use the #PIN_SELECT statements to tell it where the peripheral physically 'is'.
The peripheral is actually a EUSART, not a EUART. Most of the PIC UART's are in some ways 'enhanced' over the most basic types, but this one supports wake up, 13bit mode, and quite a few other extras. |
|
|
Alphada
Joined: 19 Jun 2017 Posts: 27
|
|
Posted: Tue Jun 20, 2017 1:59 pm |
|
|
Thx a lot for your answers, I'm gonna check them.
Compiler version is 5.070
Thx PCM programmer I'm gonna test your code, I tried almost anything but not that directive
#pin_select U1TX=PIN_C4
#pin_select U1RX=PIN_C5
I'm looking forward to it.
Btw I'm using kbhit in the main loop, as you stated, is a workaround but I feel like wasting processor cycles I'm not feeling that quite efficient over the interrupt but it solves the problem at least.
Will post results as soon as I get home. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Jun 20, 2017 2:13 pm |
|
|
The 'kbhit' call for a UART, codes as a single bit test instruction. Not exactly a waste.... |
|
|
Alphada
Joined: 19 Jun 2017 Posts: 27
|
|
Posted: Wed Jun 21, 2017 12:53 am |
|
|
Ttelmah wrote: | The 'kbhit' call for a UART, codes as a single bit test instruction. Not exactly a waste.... |
You are right not a great waste but if there are delays in code wouldn't it miss keys?
Just wondering. |
|
|
Alphada
Joined: 19 Jun 2017 Posts: 27
|
|
Posted: Wed Jun 21, 2017 12:56 am |
|
|
PCM programmer wrote: | Alphada wrote: |
The RDA interrupt won't fire by any means.
|
Try this. If it doesn't work, then post your CCS compiler version.
Code: | #include <16F1615.h>
#FUSES INTRC_IO, NOWDT, BROWNOUT
#use delay(clock=4MHz)
#pin_select U1TX=PIN_C4
#pin_select U1RX=PIN_C5
#use rs232(baud=9600, UART1, ERRORS)
#int_rda
void rda_isr(void)
{
char c;
c = getc();
putc(c);
}
//==============================
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE);
} |
Alphada wrote: |
My questions are how do i know if the chip really has UART hardware?
|
Set the .LST file in Symbolic mode in the compiler options window.
Then compile and look at the .LST file. See below. The rs232 library
code is clearly talking to the UART's hardware registers. So the compiler
is using the hardware UART:
Code: | ........... #use rs232(baud=9600, UART1, ERRORS)
0021: BTFSS PIR1.RCIF
0022: GOTO 021
0023: MOVLB 03
0024: MOVF RC1STA,W
0025: MOVLB 00
0026: MOVWF rs232_errors
0027: MOVLB 03
0028: MOVF RC1REG,W
0029: MOVWF @78
002A: MOVLB 00
002B: BTFSS rs232_errors.1
002C: GOTO 031
002D: MOVLB 03
002E: BCF RC1STA.CREN
002F: BSF RC1STA.CREN
0030: MOVLB 00
*
0034: BTFSS PIR1.TXIF
0035: GOTO 034
0036: MOVLB 03
0037: MOVWF TX1REG |
Alphada wrote: |
how could i get rid of the incoming characters without using fgetc,
because it disrupts the program by having to wait for characters.
|
Call kbhit. If it returns true, then call fgetc(). If it returns false, then
don't call it. kbhit() will accept a Stream as the parameter. If you
are using streams, then do that. |
Thanks a lot it worked the #pin_select directive enforced hardware UART and RDA its working now, i was stuck there for like 3 days. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Jun 21, 2017 3:02 am |
|
|
That's why it's a sticky at the top of the forum.
Problem is that it's very 'non obvious' if you are used to PIC's without the relocatable peripherals and there is no warning from the compiler....
On the timing thing, it's an attitude of mind in programming. As an example, currently on a project. Just passed 30000 lines of code. It only contains two 'delays', and both of these are inside CCS routines. These though are short (a few uSec only). All the main delays are handled by 'ticks'. Every sub operation (handling GSM, Bluetooth, data logging, reading external peripherals etc., has it's own 'tick', and the master loop sequences through calling each operation in turn. The operations each have a state machine, and if they want to delay, they set their 'tick', and return immediately. The tick then updates at an interval (on the GSM for example 1/10th second), and the GSM code then gets suspended, till it's tick==0, or an 'event' triggers. The events are things like 'a line has been received', flagged by the interrupt code. So for instance If I send a message, which the data sheet says should reply within 2 seconds, I just send this to an interrupt driven transmit, set the tick to 21 (to allow for the actual transmission), and exit. The routine will then get called back, when either the reply arrives (so will come back with tick!=0, and a line in the buffer), or with tick==0 if the command timed out. The 'idle' state is called if is not doing anything, and this again will receive event flags if for example an unsolicited SMS arrives.
The only operations that suspend the main loop are things like a full system reset if the master configuration file on the server gets changed, and it is sent an SMS to trigger a re-configure, when it'll load the new data, and restart. |
|
|
Alphada
Joined: 19 Jun 2017 Posts: 27
|
|
Posted: Wed Jun 21, 2017 8:45 am |
|
|
Ttelmah wrote: | That's why it's a sticky at the top of the forum.
Problem is that it's very 'non obvious' if you are used to PIC's without the relocatable peripherals and there is no warning from the compiler....
On the timing thing, it's an attitude of mind in programming. As an example, currently on a project. Just passed 30000 lines of code. It only contains two 'delays', and both of these are inside CCS routines. These though are short (a few uSec only). All the main delays are handled by 'ticks'. Every sub operation (handling GSM, Bluetooth, data logging, reading external peripherals etc., has it's own 'tick', and the master loop sequences through calling each operation in turn. The operations each have a state machine, and if they want to delay, they set their 'tick', and return immediately. The tick then updates at an interval (on the GSM for example 1/10th second), and the GSM code then gets suspended, till it's tick==0, or an 'event' triggers. The events are things like 'a line has been received', flagged by the interrupt code. So for instance If I send a message, which the data sheet says should reply within 2 seconds, I just send this to an interrupt driven transmit, set the tick to 21 (to allow for the actual transmission), and exit. The routine will then get called back, when either the reply arrives (so will come back with tick!=0, and a line in the buffer), or with tick==0 if the command timed out. The 'idle' state is called if is not doing anything, and this again will receive event flags if for example an unsolicited SMS arrives.
The only operations that suspend the main loop are things like a full system reset if the master configuration file on the server gets changed, and it is sent an SMS to trigger a re-configure, when it'll load the new data, and restart. |
Thanks for taking time to respond on my problem too, I checked and it its in fact a sticky but to be honest I'm new with pic have never read about pin select. I was just following examples and none of them were following that practice. That's why I did not take it in to account. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Jun 21, 2017 9:00 am |
|
|
Key now is to move on.
You will find that several of the CCS examples do show #PIN SELECT being used, but 90% of the examples posted here in the forum, date to chips before this capability was launched.... |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: PIC 16F1615 (RDA interrupt) not firing |
Posted: Thu Jun 22, 2017 4:24 am |
|
|
Alphada wrote: | I hear that the soft UART can't handle RDA interrupt but in the data sheet it states that it has one UART port. But I'm not sure how to check in the datasheet if it's hardware or software.
My questions are how do i know if the chip really has UART hardware? |
Just to go back to the original question: if its in the datasheet it's hardware - the datasheet doesn't deal with anything implemented in software.
CCS C deals with all the various types of hardware UART/EUART/EUSART/whatever and makes them look pretty much all the same. This is a good thing as you, the programmer, doesn't have to worry about the differences, its all handled for you.
CCS C implements software UARTs when there is not suitable hardware, not enough hardware (e.g. requesting two UARTs when there's only one in hardware), or the requested parameters are not supported by hardware, or when the user requests it, e.g. by FORCE_SW. It is easy to inadvertently get a soft UART when you think it should be using hardware by making some request that the hardware connot support, such as incompatible pins.
The software UARTs implemented by CCS are blocking and do not in any sense run "in parallel" with other code, they run as part of and in line with other code. There is no need for interrupts and as far as I am aware there is no way of calling interrupt routines from software in PICs (there is on many other processors, but not PICs I think).
One important thing to remember with this is that when using a soft UART you can only receive characters when the soft UART is actively waiting for them. getc() and it's relatives, must have been called and will wait until a character arrives. kbhit() is pointless as there is no hardware to have received and buffered a character while the code was doing other things. This also means it is far easier to miss incoming characters with a software UART than with hardware: if your code is not waiting in getc() when a character arrives, it will be lost.
Summary:
Kbhit and interrupts are only useful and only work with hardware UARTs.
Receiving data with software UARTs in much more restricted than when using hardware.
Be careful: software UARTs might be used when you don't expect it.
If its in the datasheet, its hardware.
The capabilities of the hardware UARTs can be quite varied. CCS C deals with all that for you. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Jun 22, 2017 5:54 am |
|
|
The way to call an interrupt from code, is to set the interrupt flag.... |
|
|
|
|
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
|