Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC PIC18F2550... (Glitch)

Status
Not open for further replies.

kylemaes

Banned
Heres the code: (Description of problem at bottom...)

Code:
#include <p18f2550.h>
#include <delays.h>
#include <adc.h>
#pragma config  PLLDIV = 12, CPUDIV = OSC1_PLL2, USBDIV = 2, FOSC = HS, FCMEN = OFF, IESO = OFF
#pragma config  PWRT = ON,  BOR = OFF, VREGEN = ON, WDT = OFF, PBADEN = OFF,  LPT1OSC = OFF,  MCLRE = OFF
#pragma config  STVREN = OFF,  LVP = OFF, DEBUG = OFF 
#define E RA5
#define RS RA4
#define RW RA3
int interruptnum = 0;
int huns =0;
int remain =0;
int tens =0;
int ones =0;
int fare =0;
int huns2 =0;
int tens2 =0;
int ones2 =0;
//__EEPROM_DATA(1,2,3,4,5,6,7,8); how to write to eeprom without using programmemory



const char ScreenData[10] = {
0x30, //0 28
0x31, //1 29
0x32, //2 30
0x33, //3 31
0x34, //4 32
0x35, //5 33
0x36, //6 34
0x37, //7 35
0x38, //8 36
0x39, //9 37
};

void Strobe_LCD()
{
	E=1; 
	_delay(4000);
    E=0;
}
/**********************************************************/

void Busy_Flag() 
{ 
  RW = 1;     //read mode
  while(RB7);     //Loop until finished 
  RW=0;       //default to write mode... 
} 

void Write_LCD(unsigned char d,unsigned char x)			//USE "Write_LCD(tabledata,1=cap0=lowercase);" (IF number Cap selection must equal 0!)
{
	char z = 0x00;
	if(!x)
		{
			z=0x20;
		}
	TRISB=0x00;
	PORTB=d+z;
	Strobe_LCD();
	Busy_Flag();
	TRISB=0xFF;
}

void AddressDisplay(unsigned char c) 
{ 
  Busy_Flag();    //check LCD ready
  RW = 0;     //write mode
  RS=0;       //command mode
  PORTB=c;     //place data on data port
  TRISB = 0;    //PORTB output
  Strobe_LCD();
  RS=1;
  TRISB = 0xFF;    //PORTB input
}

void lcd_init()
{
	Write_LCD(0x38,1);
	Write_LCD(0x0C,1);
	Write_LCD(0x01,1);
}



programname()
{
	RS=1;
			Write_LCD(' ',1);
			Write_LCD('C',1);
			Write_LCD('o',1);
			Write_LCD('m',1);
			Write_LCD('p',1);
			Write_LCD('o',1);
			Write_LCD('s',1);
			Write_LCD('t',1);
			Write_LCD('e',1);
			Write_LCD('r',1);
			Write_LCD(' ',1);
			Write_LCD(' ',1);
			Write_LCD('V',1);
			Write_LCD('e',1);
			Write_LCD('r',1);
			Write_LCD(':',1);
			Write_LCD('2',1);

	RS = 0;
}







void main()
{
	TRISA=0b000000111;
	TRISB=0;
	TRISC=0;
	ADCON0=0;
	ADRESL=0;

/*************************/
ADCON0=0b00000101;
ADCON1=0b00001100;
ADCON2=0b10001000;


/*************************/

IPEN = 1; /* Set Priorities */
GIEL = 0; /* disable low priority interrupts */
GIEH = 1; /* enable high priority interrupts */
T1CKPS1 = 0;
T1CKPS0 = 1;															//INTERRUPT SETUP TIMER0
TMR1CS = 0; /* Increment every instructrion cycle */
TMR1IP = 1; /* Make high priority interrupt */
TMR1ON = 1; /* Enable the timer */
TMR1IE = 1; /* Enable timer1 interrupt */ 

	lcd_init();
	programname();


	while(1)
		{

		}
}

void interrupt isr(void)
{
	if(interruptnum==1)
		{
			GO_DONE=1;
			while(GO_DONE)
			fare = ADRESL;		//TEMPERATURE
			fare = fare*100;
			fare = fare/255;
			huns = fare/100;
			remain = fare-(huns*100);
			tens = remain/10;
			ones = remain - (tens*10);
		}

	if(interruptnum==2)
		{
			RS=1;
			AddressDisplay(0xC0);			//FANSPEED
			Write_LCD('T',1);
			Write_LCD('e',1);
			Write_LCD('m',1);
			Write_LCD('p',1);
			Write_LCD('e',1);
			Write_LCD('r',1);
			Write_LCD('a',1);
			Write_LCD('t',1);
			Write_LCD('u',1);
			Write_LCD('r',1);
			Write_LCD('e',1);
			Write_LCD(':',1);
			Write_LCD(ScreenData[tens],1);
			Write_LCD(ScreenData[tens],1);
			Write_LCD(ScreenData[ones],1);
			Write_LCD(0xDF,1);
			RS=0;
		}
	if(interruptnum==3)
		{
			interruptnum=0;
		}
interruptnum++;
TMR1IF=0;
}



Some Pictures of the problem:

(This is the PIC working, But it freezes right on the second line and doesnt compute anymore)


The problem is when ADC registers (ADCON0,ADCON1,ADCON2) Are being set-up it does that. It works perfectly fine when the registers are not being setup. What is the problem?

I am using Hi-Tech C 18 Family

Thanks.

View attachment 60410
 
Last edited by a moderator:
As discussed in chat you need to sort your ISR so that it is not calling functions which are not reentrant.

Instead of doing lots of work in your ISR, simply set a flag and then do the processing in your main code, in the infinite loop. Declare interrupt globally as a volatile char then share it between your main code and the interrupt. Something like this (with everything else removed):

Code:
// MUST be volatile
volatile char interrupted = 0;

void main() {
 // Setup
 
 while(1) {
  if (interrupted) {
   // Do some stuff

   interrupted = 0;
  }
 }
}

void interrupt isr() {
 interrupted = 1;

 // Reset peripheral IF flags
}

You could also set the PCFG bits in ADCON1 differently. It looks like you are using AN1, but you are allowing AN0-AN2 to be analogue inputs. I'd suggest only allowing AN0 and AN1 (that's the most restrictive you can be with this chip).

I'd suggest typing variables to the smallest you need. A good optimising compiler will do this for you, but it is good to try and do it yourself. All of your variables are integers (16 bits) which are larger than the PIC can handle in a single instruction. For example your interrupt_num variable could easily be a char (8 bits) which takes less RAM and most operations take one instruction. Despite its name, a char is not only for characters. It's just the ANSI C primitive type for 8 bits.

Also you should probably initialise all variables to known states at the start of the program. This is normal best practise.
 
OK ADCON1 is the problem I remove it and it doesnt crash... I still am using AN1 and 2, (AN0 is glitchy on this PIC). And ill see if Char works because it didnt before just kept giving me errors... So what is wrong with ADCON1?
 
Fixed it the INIT for the LCD screen was after the interrupt and removing ADCON1 (used a certain amount of instructions) wouldnt jump to the interrupt during the LCD INIT (many many many instructions :p) Thankyou for your help again completely my fault -.-
 
Last edited:
There no glitch on the chip The 18f2550 has dependent ADC which means you have to use pins in a row if you want pin AN3 you turn on AN0 to AN3. There a lot of chips this way you cant pick AN3 by it's self but if you want just one pin you use AN0 two AN0 and AN1 and so on
 
8085? What do you mean?
be80be it says that in the data sheet thanks for the answer though :p

The glitch is it not working... i fixed the ADCON problem now I just dont get any input..
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top