CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Pic24 a-d problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pieter



Joined: 16 Jan 2011
Posts: 27

View user's profile Send private message

Pic24 a-d problem
PostPosted: Sun Jan 16, 2011 1:11 pm     Reply with quote

The code below displays the first 10 a-d channels in hex on a lcd but it reads nothing. I measure the input voltages on the pins but the code yields nothing. Please see where the mistake may be?

Thanks, Pieter
Code:

#include <c:\mpc\devices\24HJ64GP204.h>
#device ADC=8

//////// Fuses: WRTB,NOWRTB,BSSH8K,BSSS8K,NOBSS,PROTECT,NOPROTECT,WRT,NOWRT
//////// Fuses: FRC,FRC_PLL,PR,PR_PLL,NOCKSFSM,CKSFSM,SOSC,LPRC,OSCIO
//////// Fuses: NOOSCIO,EC,HS,NOPR,WDT,NOWDT,WINDIS,NOWINDIS,WPRES128
//////// Fuses: WPRES32,WPOSTS1,WPOSTS2,WPOSTS3,WPOSTS4,WPOSTS5,WPOSTS6
//////// Fuses: WPOSTS7,WPOSTS8,WPOSTS9,WPOSTS10,WPOSTS11,WPOSTS12,WPOSTS13
//////// Fuses: WPOSTS14,WPOSTS15,WPOSTS16,NOPUT,PUT2,PUT4,PUT8,PUT16,PUT32
//////// Fuses: PUT64,PUT128,XT,FRC_PS,IESO,NOIESO,PROTECTH,NORSS,RSS256
//////// Fuses: RSS2048,RSS4096,NOSSS,SSSS32K,SSSH32K,WRTSS,NOWRTSS,NORBS
//////// Fuses: RBS128,RBS256,RBS1024,DEBUG,NODEBUG,JTAG,NOJTAG,ICSP1,ICSP2
//////// Fuses: ICSP3,CKSNOFSM,BSSH4K,BSSS4K,BSSH1K,BSSS1K,SSSH16K,SSSS16K
//////// Fuses: SSSH8K,SSSS8K,PROTECT_HIGH

#FUSES WDT                    //No Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOBSS                    //No boot segment
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES FRC_PLL             //Internal Fast RC Oscillator with PLL Enabled
//#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOOSCIO                    //OSC2 is general purpose output
#FUSES NOPR                     //Pimary oscillaotr disabled
//#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES PUT128                   //Power On Reset Timer value 128ms
//#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NORSS                    //No secure segment RAM
#FUSES NOSSS                    //No secure segment
#FUSES NOWRTSS                  //Secure segment not write protected
#FUSES NORBS                    //No Boot RAM defined
#FUSES NODEBUG                  //No Debug mode for ICD
//#FUSES NOCOE                    //Device will reset into operational mode
#FUSES NOJTAG                   //JTAG disabled
//#FUSES ICSP3                    //ICD uses PGC3/PGD3 pins
//#FUSES NOALTI2C                 //I2C mapped to alternate pins

#use delay(clock=40000000, RESTART_WDT)
#use rs232(baud=4800, xmit=PIN_b11, rcv=PIN_b10)  // baud=38400


#id      0x0001
#PRAGMA   ZERO_RAM

#include <RM_Disp.c>

//
//            Software Versions:
//
//
//
//*****************************************************************************
//
//         GLOBAL VARIABLES
//
//*****************************************************************************
//
//*****************************************************************************
//

#define Led   Pin_B9

//
// vartiables
//
//**********************************************************************************
//
int      Rch;
int      Rcl;
long                   Rcx;
int      Rdl;
long                   cursor;      // cursor position: 0xXXdY  xx=1 to 20 y=1 to 4 y=0 for < else > cursor
long   lcdcfc;            // lcd curser flash counter

int      ledcnt;
int      t1test;
int1      tdone;
int   Vad[12];
int16   adval;
int      adcnt;


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

#int_Timer1                  // clock div 2,     div bt 2^16,   div set timer prescale
void   Timer1_handler(void)
{
   t1test++;
   if (t1test==38)
   {
       t1test=0;
      ledcnt++;
      tdone=1;
   }
}



#int_Adc1                  // a-d int reads the input and saves it in ram
void   Adc_handler(void)
{
         adval=read_adc(adc_read_only);
         Vad[adcnt]=adval;
         adcnt++;
         if (adcnt > 11) adcnt=0;
         set_adc_channel(adcnt);
         read_adc(adc_start_only);
}
//
//**********************************************************************************
//
//Byte Const   MenuS1[54]=  { 6,80, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, Main menu
//                                       26,27,28,29,30,31,32,33,34,35,36,37,87,38,39,40,41,42,43,44,
//                                       45,46,47,48,49,50,51,52,53,82,83,84,85,86};

void   printStart()                  // print strings
{
      printf(lcd_putc, "\f");                               // clear lcd
      delay_ms(40);                                       // 20
      printf(lcd_putc, "\f   Hello World  ");
      printf(lcd_putc, "\n Start Message  ");
}
//
//**********************************************************************************
//
//
//**********************************************************************************
//



//
//**********************************************************************************
//
main()
{
   RESTART_WDT();
   SET_TRIS_A(0xfb7f);   // 1111 1011 0111 1111
   SET_TRIS_B(0x0c1f);   // 0000 1100 0001 1111
   SET_TRIS_C(0xffc3);   // 1111 1111 1100 0011
   Output_A(0x0000);
   Output_B(0x0000);
   Output_C(0x0000);
   Output_High(Led);
   delay_ms(500);
//
   lcd_init();          // init the LCD.
   printf(lcd_putc, "\f");    // clear lcd
   delay_ms(500);
   printstart();
   Cursor=0x0114;         
    delay_ms(100);
//
   printf("Hello World");
//
   setup_comparator(nc_nc_nc_nc);
//
   setup_adc(adc_clock_internal  | adc_clock_div_16); // | adc_tad_mul_16); //
   setup_adc_ports(all_analog);   //   san2 | san3); // tried every possible setting here
   enable_interrupts(int_adc1);   // the interrups on a-d complete works
   set_adc_channel(0);      // just to start the ints
   read_adc(adc_start_only);
//
   setup_timer1(tmr_internal | tmr_div_by_8);   // Timer 0
   enable_interrupts(INT_Timer1);         // T0 int setup
//
   printf(lcd_putc, "\f");          // clear lcd
   lcd_gotoxy(2,1);                           // pos,line
   printf(lcd_putc," #1 ");         // display menu number
   delay_ms(50);
   lcd_gotoxy(12,1);                           // pos,line
   printf(lcd_putc," #2 ");         // display menu number



   while (TRUE)               // main routine
   {
      RESTART_WDT();            // reset watchdog
      Output_High(Led);
      delay_ms(100);
      Output_Low(Led);
      delay_ms(100);
      if (tdone)
      {
         tdone=0;
      }
//
      for (rcl=0;rcl<10;rcl++)      // display the 8 a-d hex values on lcd
      {
         rch=Vad[rcl];
         if (rcl < 5)
         {
            lcd_gotoxy((rcl*3+1),1);   // goto lcd pos,line
         }
         else
         {
            lcd_gotoxy(((rcl-5)*3+1),2);   // goto lcd pos,line
         }
         delay_ms(10);
         printf(lcd_putc,"%x",rch);
         delay_ms(10);
      }
   }
}
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Sun Jan 16, 2011 1:53 pm     Reply with quote

The first thing I notice is with all the ones I am familiar with, there has to be a delay between the two calls below - there is a settling time after setting the channel before you can start a conversion. See the set_adc_channel( ) example in the CCS compiler manual.

set_adc_channel(adcnt);
---- need a delay here ---
read_adc(adc_start_only);

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
pieter



Joined: 16 Jan 2011
Posts: 27

View user's profile Send private message

PostPosted: Sun Jan 16, 2011 3:28 pm     Reply with quote

Thank you mikey but that is not the problem.
I put a delay in but it makes no difference.
The read happens then setup next channel and then start only.
Then it waits for the interrupt to occur again.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Sun Jan 16, 2011 3:37 pm     Reply with quote

pieter wrote:
Thank you mikey but that is not the problem.
I put a delay in but it makes no difference.
The read happens then setup next channel and then start only.
Then it waits for the interrupt to occur again.


It may not be the ONLY problem, but it CERTAINLY is a problem. Put in a 30us delay or any reading you do get will be lousy.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sun Jan 16, 2011 3:49 pm     Reply with quote

Seriously, you are trying to use the interrupts for the wrong thing.
Generally, it takes longer to get into, and out of an interrupt handler, than to simply wait for the ADC conversion to complete in the external code. Normally, the _only_ time the ADC interrupt should be used, is when you use a programmable timer to trigger the actual reading automatically.
What you are doing though, ought to work, with one big caveat (see the bottom of my post).

Two suggestions:
1) Use your timer, instead of using the ADC interrupt. On successive timer ticks, trigger a reading, then on the next tick, read the value, and advance to the next channel. Next tick, go back to taking the reading.
2) Perform your operation just by selecting, waiting for the capacitor to charge, and taking an ADC reading, in the external code.

I think the main problem, is you are configuring the ADC incorrectly. The division ratios, are not available with the internal RC oscillator. Check the diagram for your chip. You should be OK on the charging time, since on your chip this can be added to the acquisition 'automatically', and you are doing this, but it may not be working, because you are mixing 'invalid' values in the setup.

Best Wishes
pieter



Joined: 16 Jan 2011
Posts: 27

View user's profile Send private message

PostPosted: Mon Jan 17, 2011 1:59 pm     Reply with quote

Ok, here is the correct code:
It reads the first 6 12-bit a-d's of the pic24hj64gp204 and displays the result in 16bit hex on a lcd. The a-d's are read in the a-d interrupt routine.
Add your own display routine (disp.c) and it should compile fine.

The problem was: (nothing of the advice given above....)
If I change the port settings from #use fast_io(port) to default, it seems that the compiler makes the pins i/o's, outputs, and thus pulls down the signals to ground. The a-d's then read 0's.

The working code:
Code:

//
#list
#include <c:\mpc\devices\24HJ64GP204.h>
#device ADC=12

//////// Fuses: WRTB,NOWRTB,BSSH8K,BSSS8K,NOBSS,PROTECT,NOPROTECT,WRT,NOWRT
//////// Fuses: FRC,FRC_PLL,PR,PR_PLL,NOCKSFSM,CKSFSM,SOSC,LPRC,OSCIO
//////// Fuses: NOOSCIO,EC,HS,NOPR,WDT,NOWDT,WINDIS,NOWINDIS,WPRES128
//////// Fuses: WPRES32,WPOSTS1,WPOSTS2,WPOSTS3,WPOSTS4,WPOSTS5,WPOSTS6
//////// Fuses: WPOSTS7,WPOSTS8,WPOSTS9,WPOSTS10,WPOSTS11,WPOSTS12,WPOSTS13
//////// Fuses: WPOSTS14,WPOSTS15,WPOSTS16,NOPUT,PUT2,PUT4,PUT8,PUT16,PUT32
//////// Fuses: PUT64,PUT128,XT,FRC_PS,IESO,NOIESO,PROTECTH,NORSS,RSS256
//////// Fuses: RSS2048,RSS4096,NOSSS,SSSS32K,SSSH32K,WRTSS,NOWRTSS,NORBS
//////// Fuses: RBS128,RBS256,RBS1024,DEBUG,NODEBUG,JTAG,NOJTAG,ICSP1,ICSP2
//////// Fuses: ICSP3,CKSNOFSM,BSSH4K,BSSS4K,BSSH1K,BSSS1K,SSSH16K,SSSS16K
//////// Fuses: SSSH8K,SSSS8K,PROTECT_HIGH

//#FUSES WDT, NOPROTECT, NOJTAG, NOWRT, NODEBUG, NOIESO, FRC, NOOSCIO, NOPR //, NOIOL1WAY

#FUSES WDT                    //No Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOBSS                    //No boot segment
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES FRC_PLL             //Internal Fast RC Oscillator with PLL Enabled
//#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOOSCIO                    //OSC2 is general purpose output
#FUSES NOPR                     //Pimary oscillaotr disabled
//#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES PUT128                   //Power On Reset Timer value 128ms
//#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NORSS                    //No secure segment RAM
#FUSES NOSSS                    //No secure segment
#FUSES NOWRTSS                  //Secure segment not write protected
#FUSES NORBS                    //No Boot RAM defined
#FUSES NODEBUG                  //No Debug mode for ICD
//#FUSES NOCOE                    //Device will reset into operational mode
#FUSES NOJTAG                   //JTAG disabled
//#FUSES ICSP3                    //ICD uses PGC3/PGD3 pins
//#FUSES NOALTI2C                 //I2C mapped to alternate pins

#use delay(clock=40000000, RESTART_WDT)
#use rs232(baud=4800, xmit=PIN_b11, rcv=PIN_b10)  // baud=38400

#list
#id      0x0001
#PRAGMA   ZERO_RAM

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)


#include <Disp.c>
//
//            Software Versions:
//
//

//   Pin definitions
#define Led   Pin_B9
//

// ram
//
//**********************************************************************************
//
int      Rch;
int      Rcl;
int16   Rcx;
int      Rdl;
long   cursor;            // cursor position: 0xXXdY  xx=1 to 20 y=1 to 4 y=0 for < else > cursor
long   lcdcfc;            // lcd curser flash counter

int      ledcnt;
int      t1test;
int      tdone;
int16   Vad[12];
int16   adval;
int      adcnt;



//
//**********************************************************************************
//
#int_Timer1                        // clock div 2,     div bt 2^16,   div set timer prescale
void   Timer1_handler(void)
{
   t1test++;
   if (t1test==38)
   {
       t1test=0;
      ledcnt++;
      tdone=1;
   }
}

#int_Adc1
void   Adc_handler(void)
{
         adval=read_adc(adc_read_only);
         Vad[adcnt]=adval;
         adcnt++;
         if (adcnt > 5) adcnt=0;
         set_adc_channel(adcnt);
         read_adc(adc_start_only);
}
//
//**********************************************************************************
//

void   printStart()                  // print strings
{
      printf(lcd_putc, "\f");                               // clear lcd
      delay_ms(40);                                       // 20
      printf(lcd_putc, "\f   Hello world       ");
      printf(lcd_putc, "\n A-D Test           ");
}
//
//**********************************************************************************

main()
{
   RESTART_WDT();
   SET_TRIS_A(0xfb7f);   // 1111 1011 0111 1111
   SET_TRIS_B(0x0c1f);   // 0000 1100 0001 1111
   SET_TRIS_C(0xffc3);   // 1111 1111 1100 0011
   Output_A(0x0000);
   Output_B(0x0000);
   Output_C(0x0000);
   Output_High(Led);
   delay_ms(500);
//
   lcd_init();                 // init the LCD.
   printf(lcd_putc, "\f");    // clear lcd
   delay_ms(500);
   printstart();
   Cursor=0x0114;                              // pos=xxxx xxxx cursor=xxxx line=xxxx
    delay_ms(100);
//
   printf("Hello World");
//
   setup_comparator(nc_nc_nc_nc);
//
   setup_adc_ports(san0 | san1 | san2 | san3 | san4 | san5 | VSS_VDD);
   setup_adc(adc_clock_internal  | adc_clock_div_32);      // | adc_tad_mul_16);   //
   enable_interrupts(int_adc1);
   set_adc_channel(0);
   read_adc(adc_start_only);
//
   setup_timer1(tmr_internal | tmr_div_by_8);            // Timer 1
   enable_interrupts(INT_Timer1);                            // T1 int setup
//
   printf(lcd_putc, "\f");    // clear lcd
   lcd_gotoxy(2,1);                           // pos,line
   printf(lcd_putc," #1 ");         // display menu number
   delay_ms(50);
   lcd_gotoxy(12,1);                           // pos,line
   printf(lcd_putc," #2 ");         // display menu number
   delay_ms(500);
   printf(lcd_putc, "\f");    // clear lcd

   while (TRUE)               // main routine
   {
      RESTART_WDT();            // reset watchdog
      Output_High(Led);
      delay_ms(100);
      Output_Low(Led);
      delay_ms(100);
      if (tdone)
      {
         tdone=0;
      }
//
      for (rcl=0;rcl<6;rcl++)
      {
         rcx=Vad[rcl];
         if (rcl < 3)
         {
            lcd_gotoxy((rcl*5+1),1);            // goto lcd pos,line
         }
         else
         {
            lcd_gotoxy(((rcl-3)*5+1),2);            // goto lcd pos,line
         }
         printf(lcd_putc,"%LX",rcx);
         delay_ms(2);
      }
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Mon Jan 17, 2011 3:22 pm     Reply with quote

Seriously, do a simple test. Set a pin before you read all the channels. Then reset it when the routine finishes. Then replace the code with simple read_adc commands, without using the interrupt, and without the separate start/read operations. You may be quite appalled at how much _worse_ the interrupt driven code is.
The main point I was trying to make, was _not_ to use the ADC interrupt, unless_ you are triggering this from something else, and want the synchronous sampling this allows. Otherwise, all using the interrupt does, is cost you time.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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