View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Problem when implement ADC, RS-232, Timer0 in Pic16f887 |
Posted: Tue May 15, 2012 3:57 am |
|
|
Hi all
My project which i'm doing have used ADC, Rs232 and timer 0.
I used timer 0 interrupt to update value temperature from AN0 channel.
and RS-232 to interface with GSM modem.
My code is conflicted when using timer0 (inside timer0 ISR, I update value from ADC channel - AN0 ), RDA interrupt is not working.
I used :
+ pic 16f887
+ PCH version 4.078
and here is mycode :
-- Define in main
Code: |
#include <16f887.h>
#include <def_877a.h>
#device *=16 adc=10
#fuses NOWDT, HS
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,bits=8,stop=1,parity=n)
#include <LCD_DRIVER_4BIT.c>
|
-- RDA interrupt
Code: |
void ngat_rda(void)
{
char c;
c=getc();
//putc(c);
switch(c)
{
case 10: index=0; // bat ki tu LF :ve dau dong
break;
case 13: kiemtra();// bat ki tu CR : enter
break;
default:
{
buffer_gsm[index]=c;
index++;
}
break;
}
}
|
-- timer0 ISR
Code: |
#int_timer0
void update_temp()
{
count++;
if(count==3)
{
value_temp =(float)read_adc();
value_temp = value_temp/2.048;
delay_ms(100);
count=0;
}
}
|
-- main loop programe
Code: |
void main()
{
trisa = 0xFF;
trisb = 0;
trisc = 0x80;
trisd = 0;
portd=0xff;
porta=0;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
set_timer0(0);
enable_interrupts(global);
enable_interrupts(int_timer0);
enable_interrupts(int_rda);
setup_adc_ports(RA0);
setup_adc(adc_clock_internal);
set_adc_channel (0);
delay_ms(100);
LCD_init();
delay_ms(100);
demo1();
while(1)
{
if(check_what==1)
{
printf("AT+CMGS=\"0905638093\"");
putc(13);
delay_ms(500);
//printf(" Nhiet do :%3.1f , Gas: %3.1f ",value_temp,value_temp);
//printf(" Nhiet do , Gas: ");
printf(" He Thong OK !!! ");
putc(26);
delay_ms(1000);
printf("AT+CMGD=1");
putc(13);
delay_ms(500);
check_what=0;
}
if(value_temp>=35)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"Nhiet do cao !!!");
delay_ms(1000);
printf("AT+CMGS=\"0905638093\"");
putc(13);
delay_ms(200);
printf(" He Thong Qua Nhiet Do Cho Phep !!! ");
putc(26);
delay_ms(1000);
}
}
}
|
Pls show mw way to solved problems!
thnks and regards! _________________ Begin Begin Begin !!! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Tue May 15, 2012 5:17 am |
|
|
from your code...
#int_timer0
void update_temp()
{
count++;
if(count==3)
{
value_temp =(float)read_adc();
value_temp = value_temp/2.048;
delay_ms(100);
count=0;
}
}
#1 NEVER EVER use floating point functions inside any ISR(they take 'forever'...)
#2 NEVER EVER use delay_xx(nnn) functions inside any ISR(they are HUGE time wasters..)
#3 ALWAYS have very short,fast code inside ALL ISRs.Set flags,capture raw data,reset variables.
#4 in Main, you should do all your setup code before you enable any interrupts.
#5. setup_adc(adc_clock_internal); no....please read the ADC section for correct values for adc setup for your clock value. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue May 15, 2012 5:37 am |
|
|
You're breaking the cardinal rule on ISRs.
Do as little as possible. Get in, do what you HAVE to, get out.
In an ISR do NOT:-
(1) Use milli-second delays.
(2) Perform fp maths.
I suggest you reduce your ISR to
Code: |
#int_timer0
void update_temp()
{
count++;
}
|
Move every thing else to main().
Always add ERRORS to your RS232 #use.
Its more than likely that the time spent in your ISR is causing the hardware UART to overflow.
Mike |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue May 15, 2012 9:11 am |
|
|
Code: |
buffer_gsm[index]=c;
index++; |
is just begging to overflow and corrupt other memory nearby .......... |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Wed May 16, 2012 8:50 pm |
|
|
Thank you, temtronic, Mike Walne
I fixed code according to your instructions and it runs correctly.
Thank you, thank you and regards ! _________________ Begin Begin Begin !!! |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Wed May 16, 2012 8:54 pm |
|
|
asmboy wrote: | Code: |
buffer_gsm[index]=c;
index++; |
is just begging to overflow and corrupt other memory nearby .......... |
Thanks asmboy
This is code to get string data from gms modem.
It uses AT command to interface so that its always beginning and ending with CR LF.
In RDA interrupt, I processed clear index variable with CR or LF. _________________ Begin Begin Begin !!! |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu May 17, 2012 8:19 am |
|
|
The problem is that you don't limit INDEX to size of buffer array
or CHECK that overflow will occur after index++.
What happens if MORE characters are received without line terminator ?
Answer: memory corruption for next data location(s) after buffer allocated size.
CCS compiler does not check in RUNTIME for such things. |
|
|
|