![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
LCD disables interrupt... |
Posted: Sun Feb 24, 2013 9:09 am |
|
|
When I compile this code I get this warning;
Warning 216 Interrupts disabled during call to prevent re-entrancy(@delay_ms1)
Warning 216 Interrupts disabled during call to prevent re-entrancy(lcd_sent_nibble)
Warning 216 Interrupts disabled during call to prevent re-entrancy(lcd_send_byte)
and my program is never being interrupted.
Here is my code: Code: |
#include <18F2520.h>
#DEVICE ADC=10
#fuses NOMCLR,NOWDT,PUT,INTRC_IO
#use delay(clock = 8M)
#DEFINE restr input(pin_a6)
#DEFINE LED PIN_A1
#define LCD_RS_PIN PIN_b0
#define LCD_RW_PIN PIN_b1
#define LCD_ENABLE_PIN PIN_b2
#define DATA0 PIN_b4
#define DATA1 PIN_b5
#define DATA2 PIN_b6
#define DATA3 PIN_b7
#include <lcd.c>
int duty;
int adc_val;
signed int correction;
#INT_TIMER0
void timer0_overflow()
{
output_toggle(led);
printf(lcd_putc,"Duty = %u",duty);//This one disable my interupts
}
void main()
{
SETUP_CCP1(CCP_PWM);
SETUP_TIMER_2(T2_DIV_BY_16,100,16);
SETUP_ADC(ADC_CLOCK_DIV_32);
SETUP_ADC_PORTS(AN0);
SET_ADC_CHANNEL(0);
SETUP_TIMER_0(T0_DIV_4);
ENABLE_INTERRUPTS(INT_TIMER0);
ENABLE_INTERRUPTS(GLOBAL);
lcd_init();
while(true)
{
adc_val = read_adc()/8;
duty = adc_val+correction;
if(restr)
{
if(duty>1)
correction-=1;
}
else
{
if(duty<100)
correction+=1;
}
set_pwm1_duty(duty);
delay_us(1000);
}
} |
_________________ A person who never made a mistake never tried anything new. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Feb 24, 2013 10:23 am |
|
|
Printing and writing to LCDs in ISRs is inherently a bad idea.
With ISRs you need to get in, get out ASP.
In other words, set a flag and print/write LCD in main.
The real reason for your problem is that the LCD routines include delays.
You're thus calling for delays both in main and the ISR, hence the recursion problem.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Sun Feb 24, 2013 11:36 am |
|
|
You may also find you need a delay before the "lcd_init()" call - those things typically tend to wake up quite a bit slower than the processor does - sometimes a second or more.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Sun Feb 24, 2013 1:19 pm |
|
|
Ok but I want to print my text with slower frequncy then my while(true) cycle has. My while(true) cycle overflows every 1mS but I want to update my lcd text every 100mS. So if I put printf inside main I will have updating every 1ms which I don't want to.
Thats why I use timer interruption to call printf with diferent frequency that I want. _________________ A person who never made a mistake never tried anything new. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Feb 24, 2013 1:57 pm |
|
|
One of the arts of engineering is to find ways round this sort of problem.
For starters, try things the other way round:-
Use the interrupt to initiate your fast (1ms) loop.
Then (as I suggested) put the LCD code in main with the 100ms delay.
OR
Time everything in multiples of 1ms chunks.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Sun Feb 24, 2013 3:01 pm |
|
|
As has been said, just use a counter.
However as a comment, most text LCD's won't update at 10Hz. They commonly have a 'refresh time' (time between receiving new data and displaying it), of 250mSec.
Cut the rate you update the display to no faster than 4Hz.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Mon Feb 25, 2013 10:39 am |
|
|
Thanк you guys for the useful advices!
I thinк I am going to use counter which will increase its value every cycle. So every 100th cycle I will text my massage thus I will avoid interruption. _________________ A person who never made a mistake never tried anything new. |
|
![](templates/subSilver/images/spacer.gif) |
sabonjuan
Joined: 12 Feb 2014 Posts: 2
|
|
Posted: Wed Feb 12, 2014 2:35 pm |
|
|
Hi, i have the same trouble, but i can not put a flag on main because i have a lot of functions very long, and with a lot of user interface. this warning can cause many problems later or just a warning?
Copy my interruptions code (sorry, i don't write on english very well)
Code: |
///Interrupciones (Interruptions)
#int_RTCC
void RTCC_isr(void)
{
estado.lcd.refresh++;
if(estado.lcd.refresh == 60)//una vez por minuto refrescamos la pantalla
{
estado.lcd.refresh = 0;
lcd_reinit();
}
}
#int_TIMER1
void TIMER1_isr(void)
{
disable_interrupts(INT_TIMER1);;
if((estado.lcd.box == 0)&&Ext_Display_In_pin)
{
Ext_Display_On;
estado.lcd.box = 1;
lcd_reinit();
}
else if((estado.lcd.box == 1)&&!Ext_Display_In_pin)
{
Ext_Display_Off;
estado.lcd.box = 0;
lcd_reinit();
}
enable_interrupts(INT_TIMER1);
}
#int_LOWVOLT
void LOWVOLT_isr(void)
{
//apagar equipo
apagar_equipo_urgente();
}
////LCD_reinit function
///-----------------------------------------------------------------------------
///Funciones
void lcd_reinit()
{
int i;
lcd_init(estado.lcd.w_cursor);
delay_ms(500);
lcd_gotoxy(1,1);
for(i=0;i<16;i++)
{
lcd_putc(estado.lcd.msg_l1[i]);
delay_ms(5);
}
delay_ms(10);
lcd_gotoxy(1,2);
for(i=0;i<16;i++)
{
lcd_putc(estado.lcd.msg_l2[i]);
delay_ms(5);
}
delay_ms(10);
lcd_gotoxy(1,3);
for(i=0;i<16;i++)
{
lcd_putc(estado.lcd.msg_l3[i]);
delay_ms(5);
}
delay_ms(10);
lcd_gotoxy(1,4);
for(i=0;i<16;i++)
{
lcd_putc(estado.lcd.msg_l4[i]);
delay_ms(5);
}
delay_ms(10);
if(estado.lcd.w_cursor)
{
lcd_gotoxy(estado.lcd.x,estado.lcd.y);
delay_ms(5);
}
estado.lcd.recent_sw = 1;
} |
OK, some explanation:
#int_TIMER1: i have two 16x4 lcd displays, one on my main case, the second is on my interface case, and when i connect the interface case, the uc switch the power lines and data lines from main case display to interface case. I am using PIC18f46k20
#int_RTCC: refresh lcd
#int_LOWVOLT: also, i am working with a lot of power (2KW ) that the pic have to control. When i have an energy trouble i need to discharge capacitors and inductors. _________________ Abuelito dime tu, abuelito dime tu!
TU!!!
Gracias abuelito! |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Feb 12, 2014 3:49 pm |
|
|
sabonjuan wrote: | Hi, i have the same trouble, but i can not put a flag on main because i have a lot of functions very long, and with a lot of user interface. this warning can cause many problems later or just a warning?
OK, some explanation:
#int_TIMER1: i have two 16x4 lcd displays, one on my main case, the second is on my interface case, and when i connect the interface case, the uc switch the power lines and data lines from main case display to interface case. I am using PIC18f46k20
#int_RTCC: refresh lcd
#int_LOWVOLT: also, i am working with a lot of power (2KW ) that the pic have to control. When i have an energy trouble i need to discharge capacitors and inductors. |
I can't even begin to understand your problem, but like I said earlier, sort out your priorities.
Set up counters or timers which do urgent tasks first, less important ones later.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
sabonjuan
Joined: 12 Feb 2014 Posts: 2
|
|
Posted: Wed Feb 12, 2014 5:55 pm |
|
|
Thank you mike, I added this code that I thought would be useful, but now i think that may confuse.
My problem is I can not put a flag in the interrupt for lcd_reinit what the code is run on the main, because i have a lot of processes that shows information, and do not return to main until this process finish. I can not add all the code because is too long.
Exist any other chance for remove this warnings? or, this warning can give me any error on the future?
Sorry i am using google translate.
Thank you Mike! _________________ Abuelito dime tu, abuelito dime tu!
TU!!!
Gracias abuelito! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Thu Feb 13, 2014 2:10 am |
|
|
In your case, not really.....
Think about it for moment. Imagine you are writing to the LCD in the main code, and while inside this routine (so LCD lines are being controlled by the main code at this point), you call an interrupt that also tries to write to the LCD. The LCD is half way through a write, and suddenly starts to try to do another....
Anything like this that controls hardware, has to block any other function from controlling the same hardware at the same time.
Now for other types of things, there are ways of avoiding this. The delay for example, can avoid problems by having two sets of delay code. But when dealing with a single set of hardware, no, it can't be avoided....
There is a solution, but it gets slightly more complex.
Some time ago, I had to write a message to an LCD, from inside an interrupt handler, and also do messages from other parts of the code. Like you, because of the nature of the code, I wanted to retain the ability to actually trigger the display from the interrupt, wherever the main code 'was' at the time. The solution I used, was a 'message queue' (buffer). I got rid of the standard LCD code, and instead did a version that wrote one character to the LCD, if one was waiting, from inside a 200Hz interrupt. Now if you look at the timing diagrams for conventional LCD's, all commands take less than 5mSec (1.64mSec worst case for a CLS). So the interrupt can simply write one character to the LCD, without checking timings etc.. The only code that had interrupts disabled, was the routine to write characters to the buffer (which took a few uSec only). So 'main' puts it's messages into the buffer, and the interrupt does the same. Interrupts are disabled while main writes to the buffer, but the delay is tiny. This way the code doesn't have to wait for the slow LCD.
Messages have to be complete 'entities' for this to work (so for instance, a 'goto', followed by the characters to write).
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|