|
|
View previous topic :: View next topic |
Author |
Message |
beaker404
Joined: 24 Jul 2012 Posts: 163
|
18F4550 and INT_EXT serial port. |
Posted: Wed Aug 24, 2016 2:35 pm |
|
|
Having some problems getting my 18F4550 up and running with two serial ports. I am using the C6,C7 UART for the PC side that sees the most traffic. I have a second serial port talking to a 16F876 set up to come in on B0 INT_EXT0. I am set up for 9600 baud on the UART and 4800 baud on the INT_EXT UART. Not getting into my ISR when data comes in. O-scope shows data being present but cannot even get an acknowledge that the ISR is firing.
I have #priority set to INT_EXT being highest priority, should be by default. I am also using INT_RTCC and INT_RDA. I have my INT_EXT transition set to H_TO_L and all interrupts are enabled, disabling all interrupts except INT_EXT when in the INT_EXT ISR. Here are a few code snippets.
Code: |
#include <18f4550.h>
#DEVICE ADC=10
#include <stdlib.h>
//#fuses XT,NOWDT,NOPROTECT,NOLVP
#FUSES HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP,NODEBUG, CPUDIV1
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7,stream=USB_SERIAL,ERRORS)
#use rs232(baud=4800,xmit=pin_b1,rcv=pin_b0,stream=CTRL) // serial comm w/ down hole power module.
#priority INT_EXT,INT_RDA,INT_RTCC
|
Code: |
#int_ext
void DH_serial_isr() // Reads incoming data from the USART sent by the down hole power module. GTS 6-2016
{
char cChar;
disable_interrupts (INT_RDA);
disable_interrupts (INT_RTCC);
cChar = fgetc(CTRL); // get char from down hole
fprintf(USB_SERIAL, "***%c\n\r",cChar);
DH_serial_buffer[DH_buffer_index] = cChar;
DH_buffer_index = DH_buffer_index + 1;
if(cChar == '#') { // The message is complete
DH_msg_complete_flg = 1;
DH_serial_buffer[DH_buffer_index] = '\0'; // end of string char
DH_buffer_index = 0;
}
else {
DH_msg_complete_flg = 0; // clear the flag for next time.
}
enable_interrupts (INT_RDA); //re-enable interupts, but check and only turn on INT2 if it was on previously. INT EXT2 should only be on if we were are using the internal GPS
enable_interrupts (INT_RTCC);
} // end DH_serial_isr()
|
I know, the ISR is dirty and I am doing the no no of printing from it, trying to see if the code is firing, tomorrow I will just toggle a pin.
wondering what is wrong here, seems like I am doing it right and it is a pretty simple thing to do. open for ideas. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Aug 24, 2016 3:02 pm |
|
|
First thing may be to do is put the _faster_ serial on the INT_EXT stream. Otherwise to receive a character on this, you are stuck in the INT_EXT interrupt for 2 byte times of the INT_RDA, and characters will be lost.....
See below.
Then the second is to keep the ISR short. You are doing far too much inside the ISR.
Now some problems at the start. Why on earth are you running so slow?. You need some CPU speed to do this. You are currently selecting 'HS', which is for a crystal faster than 4MHz, but are running at 4MHz. Lets run faster:
Code: |
#include <18f4550.h>
#DEVICE ADC=10
//Do not load libraries till after the fuses and timing are defined
#FUSES XTPLL, PLL1 ,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#FUSES NODEBUG, CPUDIV3
//This will route your 4MHz crystal into the PLL. /1, *24
//Then divide this by 8 (you'll have to study the data sheet to see why
//'div3' gives /8...
#use delay(clock=12MHz) //96/8
#include <stdlib.h>
//now include other things
|
Now we need to know more about the nature of the two serials?.
If nothing will come on the second stream at the same time as you are receiving data on the INT_EXT stream, then things can be all right. One thing you could do, is send an 'XOFF' on the RDA stream to prevent problems, or if the nature is such that this is unlikely, and your data format can recover from lost bytes, then again this may be OK. Otherwise you need to think again.
Now, inside your interrupt all other interrupts are disabled already. Get rid of the wasted disable/enable instructions.
You are not using hardware interrupt priorities. #PRIORITY only sets the order that the interrupts are polled.
To use hardware priorities, you need to add #DEVICE HIGH_INTS=TRUE as the line after the ADC=10 line, and declare #INT_EXT HIGH.
So store the character to a buffer, and just exit. If you want to print it to USB, do this in the main code outside.
You don't show us your interrupt setup line. You need to be using H_TO_L on ext_int_edge, to get the correct edge on the data. Also (obviously) enabling this interrupt, and the global.
SAMPLE_EARLY, tells the code to assume there has been some delay in arriving at the read |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 8:06 am |
|
|
thanks Ttelmah for all the comments.
I have done the clock changes as you recommended.
Bumped the 4800 rate to 9600
tried to do the DEVICE HIGH_INTS calls but compiler did not like it.
my compiler is PCH version 5.026 xxxxx
Running on windows 10.
I stripped all the unnecessary stuff out of the ISR. I read the char, toggle pin B5 and get out.
the O-scope shows it is not getting into the ISR at all.
my interrupt enables are as follows:
Code: | set_rtcc(0);
setup_timer_0( RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT); //15 interrupts/sec 18F chip RTCC in 8 bit mode not 16
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
clear_interrupt(INT_EXT);
enable_interrupts(INT_RTCC); // set up the RTCC counter
enable_interrupts(INT_RDA); // set up the serial interrupt
enable_interrupts(GLOBAL); // turn on all interrupts.
|
I am open for more ideas. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Aug 25, 2016 11:04 am |
|
|
Maybe time to go back to 'square one' ?
Code a simple program that JUSTS looks for the external interrupt to occour and toggle an LED? NO timers, no serial, KISS code. Might even be code in the 'examples' folder ?
OR...
maybe a hardware issue ? bad solder connection, loose wire, etc.
'something' ain't right and the easiest way to debug is go 'low level', one step at a time.
Jay |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Thu Aug 25, 2016 11:16 am |
|
|
why not use the USB port for the PC connection and then the HW uart for the other? The 18f4550 is a USB enabled part. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 11:38 am |
|
|
agreed, I am stripping the code down now. more later.
as for USB, not an option this time around need the length of RS-232 transmissions. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 1:17 pm |
|
|
ok, found what stops INT_EXT from working right with my serial interrupt.
Code: |
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
clear_interrupt(INT_EXT);
enable_interrupts(INT_RTCC); // set up the RTCC counter
enable_interrupts(INT_RDA); // set up the serial interrupt
enable_interrupts(GLOBAL); // turn on all interrupts.
//SETUP_ADC_PORTS(ALL_ANALOG); // all analog ports on
//SETUP_ADC(ADC_CLOCK_DIV_32);
|
here is a snippet of my initialization routine showing the interrupts I am setting up. note the ADC setup calls are commented out. When I restore them to the code, my INT_EXT ISR stops working. I know this by only toggling a pin in the ISR and watching it with the scope.
perhaps here is a way to still get the analogs enabled and make everyone get along? I need analogs on this project. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 1:27 pm |
|
|
it is the setup_adc_ports call that is messing the INT_EXT up. not sure why that is, my INT_EXT is on B0 and B1 and my analogs are on port A.
crazy.
really open for ideas and theories now. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Aug 25, 2016 2:19 pm |
|
|
OK, silly question but...
are you 'committed' to the 4550 ?
I ask cause I dumped it years ago for the 46k22...tons of memory and TWO HW UARTs, plus other goodies... $2 ttl-usb module gets me to PC these days.
options, maybe it's one for you ??
BTW, EVERYONE here has been 'bitten' by the 'default' I/O pin assignments at one time or another.....
it's none of those , read 600 pages, plan every pin, see what WILL work, THEN check for default settings... sigh.... too many pins, too many peripherals in PICs these days !
welcome ..lol..
Jay |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 2:31 pm |
|
|
I am sorta stuck on the 4550. It is a direct replacement for 16F877 and that fits my upgrade of existing hardware. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Thu Aug 25, 2016 4:46 pm |
|
|
Have a look at the 18F46k22 in your spare time... Unless you're using the USB internal peripheral of the 4550, you'll be light years ahead of the game with the 46k22. Yup, I've got 2 tubes of 4550s here, 3 or more of the 877 as well.There isn't anything it hasn't done for me, way 'overkill' for most projects but it does work. Neat stuff like FULL speed at 3 OR 5 volts.
Can run at 64MHz too !
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 25, 2016 5:31 pm |
|
|
This discussion isn't solving his problem.
He needs to look in the 18F4550.h file to see what constants are allowed
to setup the analog pins.
Look at the allowable settings below. You are using "ALL_ANALOG".
Look at the comment for that line. It makes pin B0 be analog.
You don't want that. So choose another setting from the list that
gives you the analog pins that you want.
Code: |
// Constants used in SETUP_ADC_PORTS() and SET_ANALOG_PINS() are:
// First argument:
#define NO_ANALOGS 0x0F // None
#define ALL_ANALOG 0x00 // A0 A1 A2 A3 A5 E0 E1 E2 B2 B3 B1 B4 B0
#define AN0_TO_AN11 0x03 // A0 A1 A2 A3 A5 E0 E1 E2 B2 B3 B1 B4
#define AN0_TO_AN10 0x04 // A0 A1 A2 A3 A5 E0 E1 E2 B2 B3 B1
#define AN0_TO_AN9 0x05 // A0 A1 A2 A3 A5 E0 E1 E2 B2 B3
#define AN0_TO_AN8 0x06 // A0 A1 A2 A3 A5 E0 E1 E2 B2
#define AN0_TO_AN7 0x07 // A0 A1 A2 A3 A5 E0 E1 E2
#define AN0_TO_AN6 0x08 // A0 A1 A2 A3 A5 E0 E1
#define AN0_TO_AN5 0x09 // A0 A1 A2 A3 A5 E0
#define AN0_TO_AN4 0x0A // A0 A1 A2 A3 A5
#define AN0_TO_AN3 0x0B // A0 A1 A2 A3
#define AN0_TO_AN2 0x0C // A0 A1 A2
#define AN0_TO_AN1 0x0D // A0 A1
#define AN0 0x0E // A0 |
|
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Aug 25, 2016 7:01 pm |
|
|
Ah Yes! thanks guys and thanks PCM programmer, I will look into that tomorrow, you are right do not need all analogs, just the lazy way to turn on what I need.
I will also look at the other chips mentioned for future projects.
thanks all. I will confirm this fixes me tomorrow. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Aug 26, 2016 1:21 am |
|
|
What PCM_Programmer has pointed out to you with the printout from the header, is that 'ALL_ANALOGS' sets port B to analog.....
If you are only using port A, then you need to use AN0_TO_AN4, which only enables the five analog pins on port A.
If you look at the PORTB I/O summary table, the second line:
Code: |
PORTB<0> data input; weak pull-up when RBPU bit is cleared.
Disabled when analog input enabled(1).
|
Note the "Disabled when analog input enabled(1)."....
It is _never_ good practice to enable analog pins you are not using. Not only does it do things like this, but it increases analog 'noise' on the other pins. When a pin is selected to feed to the analog input multiplexer, the FET is turned on routing it to the multiplexer, and there is a slight increase in cross-talk to the other analog signals. If you do this with several 'digital' pins, you significantly degrade the analog performance..... |
|
|
|
|
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
|