View previous topic :: View next topic |
Author |
Message |
starfire151
Joined: 01 Apr 2007 Posts: 195
|
PIC24FV32KA301 serial interrupt question |
Posted: Wed Feb 12, 2014 2:37 pm |
|
|
I have made some progress in getting my first voyage into using 16-bit PICs to work... largely because of the help from this forum. Thank you.
I'm trying to get this PIC to split the com port functionality and use the predefined U1RX pin (pin 6 on this device) as the com receive and use the OscI/An13/... pin (device pin 7) as the com transmit pin. When I first power up, I print out a message to the com port. That message works correctly so the transmit pin is working OK. I've enabled the com receive interrupt (#INT_RDA) but the interrupt routine is not receiving com inputs. I've placed a "if kbhit()" in the background and the receive characters are being seen correctly.
Why isn't the com receive interrupt routine seeing the input?
Thanks, again, for the help. If I can get a few more interface functions working, this will be my new favorite chip
Apologies for the lengthy code...
Code: |
#include <24FV32KA301.h>
#device adc=12
#fuses ICSP1 // select ICSP1 programming port
#fuses NOWDT
#fuses NOPROTECT
#fuses MCLR
#fuses PUT
#fuses NOBROWNOUT
#fuses OSCIO // oscillator pins used as general purpose I/O
#fuses SOSC_DIGITAL // digital I/O for osco pin
#use delay(internal=32000000)
//#pin_select U1RX=PIN_B2 <= STATES INVALID PR-PROCESSOR DIRECTIVE: Invalid Pin
#use rs232(baud=38400, parity=N, xmit=PIN_A2, rcv=PIN_B2, bits=8)
#define INTS_PER_SEC 10 // (32,000,000 / (2 * 256)) / 6250
// ---- define I/O default port data and TRIS parameters ----
#define PA_DEF 0b1111111111111111
#define PA_TRIS 0b1111111111111011
// 15 I: NA on 20-pin PIC
// 14 I: NA on 20-pin PIC
// 13 I: NA on 20-pin PIC
// 12 I: NA on 20-pin PIC
// 11 I: NA on 20-pin PIC
// 10 I: NA on 20-pin PIC
// 9 I: NA on 20-pin PIC
// 8 I: NA on 20-pin PIC
// 7 I: NA on 20-pin PIC
// 6 I: VCap on FV part
// 5 I: Pin 1 : MCLR
// 4 I: Pin 10 : unused
// 3 I: Pin 8 : unused
// 2 O: Pin 7 : Tx output to terminal
// 1 I: Pin 3 : unused
// 0 I: Pin 2 : unused
#define PB_DEF 0b1111111111101111
#define PB_TRIS 0b0100111111101111
// 15 O: Pin 18 : unused
// 14 I: Pin 17 : unused
// 13 O: Pin 16 : unused
// 12 O: Pin 15 : unused
// 11 I: NA on 20-pin PIC
// 10 I: NA on 20-pin PIC
// 9 I: Pin 13 : unused
// 8 I: Pin 12 : unused
// 7 I: Pin 11 : unused now (will be used for interrupt input)
// 6 I: NA on 20-pin PIC
// 5 I: NA on 20-pin PIC
// 4 O: Pin 9 : heartbeat
// 3 I: NA on 20-pin PIC
// 2 I: Pin 6 : Rx input from terminal
// 1 I: Pin 5 : PGEC1 prog clock
// 0 I: Pin 4 : PGED1 prog data
#define HEARTBEAT PIN_B4 // 1-second heartbeat toggle
// ---- variable definitions ----
int1 sFlag; // TRUE:COM serial character seen
char sCmd; // current serial command
int16 intCount; // interrupt counter
int32 secondsTotal; // total count of running seconds
// ---- initialize the system routine ----
void InitSys(void)
{
output_a(PA_DEF);
output_b(PB_DEF);
intCount = INTS_PER_SEC;
secondsTotal = 0;
sFlag = FALSE;
}
// ---- real time clock interrupt routine ----
#INT_TIMER1
void ClockISR(void)
{
intCount--;
if(intCount == 0)
{
intCount = INTS_PER_SEC; // reinit timer ints per msec cntr
output_toggle(HEARTBEAT); // toggle heartbeat output pin
secondsTotal++; // increment local total seconds count
}
}
// ---- serial interrupt routine to capture terminal interface ----
// Command syntax:
// S display current status of variables
// H help command
#INT_RDA
void ComISR(void)
{
char sCh;
sCh = getch();
sCmd = toupper(sCh); // save the current command
sFlag = TRUE; // process now
}
// ---- main program beginning ----
void main()
{
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_tris_a(PA_TRIS);
set_tris_b(PB_TRIS);
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 6250); // 0.1 sec interrupt
InitSys();
delay_ms(10);
printf("PIC24FV32KA301 Testbed\r\n");
printf("V1.0 Compiled: %s %s\r\n", __DATE__, __TIME__);
printf("\r\n");
delay_ms(100);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
enable_interrupts(INTR_GLOBAL);
while(TRUE)
{
if(kbhit())
printf("serial char %c\r\n", getch());
if(sFlag) // if a command was seen, respond to it
{
switch(sCmd)
{
case 'S': // status
printf("S:\r\n");
printf("elapsed time: %lu secs\r\n", secondsTotal);
printf("\r\n");
break;
case 'H': // help command
printf("H:\r\n");
printf("S display current status\r\n");
printf("H help\r\n");
printf("\r\n");
break;
}
sFlag = FALSE; // clear flag for next time
}
}
}
|
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Feb 12, 2014 4:00 pm |
|
|
No need for lengthy code.
I don't care to plough through several pages of commented out and superfluous text.
You should be able to produce complete compilable code which illustrates your issue in no more than a ten or at most twenty lines.
Will then make it easier for you and us to see the problem.
Mike |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Feb 12, 2014 4:27 pm |
|
|
...tried to make it small...
Code: |
#include <24FV32KA301.h>
#device adc=12
#fuses ICSP1 // select ICSP1 programming port
#fuses NOWDT
#fuses NOPROTECT
#fuses MCLR
#fuses PUT
#fuses NOBROWNOUT
#fuses OSCIO // oscillator pins used as general purpose I/O
#fuses SOSC_DIGITAL // digital I/O for osco pin
#use delay(internal=32000000)
#use rs232(baud=38400, parity=N, xmit=PIN_A2, rcv=PIN_B2, bits=8)
int1 sFlag; // TRUE:COM serial character seen
char sCmd; // current serial command
#INT_RDA
void ComISR(void)
{
sCmd = getch(); // save the received char
sFlag = TRUE; // let background know char seen
}
void main()
{
set_tris_a(0xfffb);
set_tris_b(0x4fef);
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 6250); // 0.1 sec interrupt
printf("init message\r\n");
output_a(0xffff);
output_b(0xffef);
sFlag = FALSE;
clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
enable_interrupts(INTR_GLOBAL);
while(TRUE)
{
if(kbhit())
printf("serial char %c\r\n", getch());
if(sFlag) // if a command was seen, respond to it
{
switch(sCmd)
{
case 'S': // status
printf("S command:\r\n");
break;
case 'H': // help command
printf("H command:\r\n");
break;
}
sFlag = FALSE; // clear flag for next time
}
}
}
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed Feb 12, 2014 5:07 pm |
|
|
You're using PIN_A2 for your transmit, which isn't a hardware UART pin. So the compiler is generating a software UART for you. Interrupts are hardware based, so a software UART wouldn't have an RDA interrupt. You need to move your pins to hardware UART pins for it to work.
kbhit still works with a software UART, but interrupts do not. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Feb 12, 2014 5:29 pm |
|
|
That's what I kinda figured. I need to use the pin for an interrupt input so I can't use it for U1TX. I was hoping the hardware UART for receive would still work. I can't use int1 or int2 because I have an SPI interface, also. I'll have to look at rearranging pins...
Thanks for responding. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed Feb 12, 2014 6:53 pm |
|
|
There are two UART and two SPI interfaces on that chip. Any chance of using UART2 or SPI2 instead? Also, do you need INT0/1/2 for sure? Change notification interrupts (on the CNXX pins) can be used in a pinch. Takes a little more care, but useful.
EDIT: for example, PIN_A2 is CN30, so you could swap tx back to U1TX and the interrupt to PIN_A2 and use the change notification interrupt. Then you just need to add a bit of code to determine if the interrupt was rising edge vs falling edge. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Wed Feb 12, 2014 6:58 pm |
|
|
Thanks for the suggestions. I think I can use the U2TX and U2RX pins for the com interface and get the programming interface from the third set. Then I can use the SPI1 set of pins and liberate Int0 for my external interrupt.
This is a very flexible chip.
Thanks, again. |
|
|
|