|
|
View previous topic :: View next topic |
Author |
Message |
Andreas
Joined: 25 Oct 2004 Posts: 136
|
Interrupt Stops PIC16F886 |
Posted: Mon Nov 24, 2014 1:21 am |
|
|
Hello Friends
I am running into a very odd Problem with my easy 16F886 PIC program !
When using this code below i can see the Timer Interrupt running !
I can also see that the PIC is receiving data correct !
The function of this program is, generating a PWM Output and according to the received command Change the PWM Duty in 8 Steps.
And now my Troubles starting, after receiving the data the PIC should respond with an answer.
When responding with this : fputc('T',com1); everything works fine !
But when I respond with this: fprintf(com1,"*RSTAll#"); the interrupt stops and is never restored !!!!
Can anybody out there give me some hint what I am doing wrong here ???
with best regards and and thanks in advance
Andreas
Vienna, Austria (No Kangoroos) :-)
Code: |
#include <16F886.h>
#device ICD=TRUE
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES PROTECT //Code protected from reads
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //NO Reset when brownout detected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV21 //Brownout reset at 4.0V
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=Com1,errors)
#define LED1 PIN_A4
#define Mode PIN_A5
#define BTReset PIN_A7
#define BTLED PIN_B5 // LED Indicator from BT Module !
#define ICSPCLK PIN_B6
#define ICSPDAT PIN_B7
#define LED2 PIN_C4
#define KEY05 PIN_C5
#define TxDat PIN_C6
#define RxDat PIN_C7
#define Mot1A PIN_C0
#define Mot1B PIN_C1
int1 RcvOK = False;
int1 SendAck = 0;
int8 CycleHigh[10];
int8 CycleAll;
int8 Val[10];
int8 ch;
int8 Sequenz[10];
int8 Inbuf[40];
int8 outbuf[20];
int8 incnt = 0;
int8 CycArr[20];
int8 DirR;
int8 Chanel;
int8 MotServ;
int8 OutSet = 0;
int16 T1Val = 0xFF38;
#int_RDA
void RDA_isr(void)
{
int8 Coch;
RcvOK = True;
ch = getch(com1);
if (ch == '*') Incnt = 0;
inbuf[incnt++] = ch;
if (ch == '#')
{
// Standard Telegram for Motor or Servo
if ((inbuf[1] == 'S') && (inbuf[2] == 'E') && (inbuf[3] == 'T'))
{
if (inbuf[4] == 'M') MotServ = 'M';
if (inbuf[4] == 'S') MotServ = 'S';
Coch = (inbuf[5] - 0x30)*10;
Chanel = (inbuf[6] - 0x30) + Coch;
if (inbuf[7] == '+') DirR = 8;
else DirR = 0;
Coch = (inbuf[8] - 0x30)*10;
Coch = (inbuf[9] - 0x30) + Coch;
if (DirR ==8) Val[Chanel] = Coch + DirR;
else Val[Chanel] = 8 - Coch;
if (incnt == 15)
{
Sequenz[0] = inbuf[10];
Sequenz[1] = inbuf[11];
Sequenz[2] = inbuf[12];
Sequenz[3] = inbuf[13];
OutSet = 1;
}
else
{
OutSet = 2;
}
CycleHigh[Chanel] = CycArr[Val[Chanel]];
SendAck = 1;
}
incnt = 0;
}
}
#int_TIMER1
void TIMER1_isr(void)
{
set_timer1(T1Val);
output_toggle(LED1);
if (CycleHigh[1] > 0)
{
CycleHigh[1]--;
if (Val[1] > 8) output_High(Mot1A);
else output_High(Mot1B);
}
else
{
output_Low(Mot1A);
output_Low(Mot1B);
}
if (CycleAll > 0) CycleAll--;
if (CycleAll ==0)
{
CycleAll = 8;
CycleHigh[1] = CycArr[Val[1]];
}
}
void main()
{
setup_oscillator(OSC_8MHZ);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // Start timer 1
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(0xFFF8); // FFA6 1mS Timer
CycArr[1] = 14;
CycArr[2] = 7;
CycArr[3] = 6;
CycArr[4] = 5;
CycArr[5] = 4;
CycArr[6] = 3;
CycArr[7] = 2;
CycArr[8] = 0;
CycArr[9] = 2;
CycArr[10] = 3;
CycArr[11] = 4;
CycArr[12] = 5;
CycArr[13] = 6;
CycArr[14] = 7;
CycArr[15] = 14;
output_float(RxDat);
output_Low(KEY05);
output_low(Mode);
output_High(LED1);
output_low(LED1);
output_Low(BTReset);
delay_ms(100);
output_High(BTReset);
output_float(BTLED);
Chanel = 1;
Val[Chanel] = 8;
CycleAll = 14;
CycleHigh[Chanel] = CycArr[Val[Chanel]];
output_Low(Mot1A);
output_Low(Mot1B);
for (ch = 0; ch < 40; ch++) inbuf[ch] =0x20;
for (ch = 0; ch < 20; ch++) outbuf[ch] =0x20;
Val[0] = 0x00;
while(true)
{
if (SendAck == 1)
{
SendAck = 0;
// fprintf(com1,"*RSTAll#"); // This doenst work !! Int stops !!
fputc('T',com1); // This works !!!
}
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Mon Nov 24, 2014 2:23 am |
|
|
Start with comments (not the problem), your INT_RDA is too complex. You have things like multiplication in here, which means that interrupts will be disabled in mathematics in the main loop. Re-think, use a circular buffer or simple linear buffer, and when the '#' condition is seen, set a flag, and process the buffer in the main code.
There are lots of problems with your fuses. Most can't be used with debug. Some are pointless (FSCM, for example is designed to drop 'back' to internal clock, if an external clock fails - how can this be used with the internal clock...). IESO, requires an external clock. Have you got one?.
Then use a constant or define for the timer1 value. Currently the processor is having to load a variable, and write this to the timer register. About twice as much work as writing a constant....
Then you have a big problem with time. Timer1 is running off the instruction clock. Counting at 2Mhz. You set it to 0xFF38, and it counts to 0x10000. Total 0xC8 counts - just 200 instructions. You are doing perhaps 30 instructions of code in the ISR, and then another 30 in the interrupt handler, so your processor is spending over 30% of it's time just handling this routine. The PIC is just not capable of generating reliable software based pulses at this sort of speed, and doing anything much else useful. Rethink. This is going to cause problems in everything else. You say '1mSec timer', but your timer is running at 0.1mSec. 1mSec is useable. 0.1mSec is getting hard, requiring careful programming. As written, the pulses will sometimes be erratic. This may be acceptable, but are you confident it is?.
However, you don't give one critical piece of data. Compiler version?.
There was a problem a while ago, with 'printf' disabling the global interrupts. I'd suspect this is your actual problem. |
|
|
Andreas
Joined: 25 Oct 2004 Posts: 136
|
16F886 Int |
Posted: Mon Nov 24, 2014 8:00 am |
|
|
Hello Ttelmah !
Many thanks for your extensive reply !
My Compiler Version is: Version 5.012, 5801
I am using MPLAB IDE and PICKit3 for Debugging.
About the fuses, I just took a sample file and did not make any changes to optimize them, thanks for the hint.
I did some trying today and ended up with doing a lot of putc statements and it works.............
Testing the timing issues I found out that I really have time in spare.
Your info about global interrupt sounds to be the most likely reason, maybe You have more info about this issue
with best regards
Andreas |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Mon Nov 24, 2014 8:16 am |
|
|
A quick search here will find it. 5.012, sounds about right.
Just add 'enable_interrupts(GLOBAL);' to the loop immediately after the printf. |
|
|
Andreas
Joined: 25 Oct 2004 Posts: 136
|
|
Posted: Tue Nov 25, 2014 1:03 am |
|
|
Hello Ttelmah
Thanks a lot for your suggestion, it was really this compiler BUG !!!!!!!
But now I have one casic question, how did you made the search finding this answer ??
I am always struggling with the search function, either it gives thousands of answers or None..............
Also, to You think I can ask CCS for a compiler update because of this bug ?
Again, many thanks for your help
with best regards
Andreas |
|
|
|
|
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
|