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

ADC Problem With 16F886 At 3.4V

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



Joined: 25 Feb 2011
Posts: 3
Location: Argentina

View user's profile Send private message

ADC Problem With 16F886 At 3.4V
PostPosted: Fri Feb 25, 2011 11:00 am     Reply with quote

Hi all this is my fist post, I hope some one can help me.

I'm working on a project powered by lion battery, but my problem is with the adc conversion at 3.4V VDD.
I post the code, this code work well when the pic is powered with 5V, but when I power the pic with 3.4V the AD port always read 1023 and if I test the pin with multimeter I get 3.8V even when set the pin as input, or output Float.
Code:

//------------------------ Definiciones Basicas --------------------------------
#include <16F886.h>
#device *=16            // Esto permite el uso de toda la RAM.
#DEVICE ADC=10
#define FOSC 8000000    // Frecuencia de trabajo del PIC.

//------------------------ Definicion de Fusibles ------------------------------
#fuses INTRC_IO           //Cristal 4[MHz]
#fuses NOWDT              //Usamos watchdog para evitar que se cuelgue
//#fuses BORV21            //Para que se resetee si baja la tensiĆ³n
#fuses NOBROWNOUT
#fuses NOPROTECT,NOLVP,PUT,MCLR,NODEBUG
#use delay(clock=FOSC)


//---------------- Definicion de pines (Uso de los Puertos) --------------------
//#USE STANDARD_IO (A)
#define IN_AN1       PIN_A0   //Pines del BUS A
#define IN_AN2       PIN_A1
#define IN_DIR       PIN_A2
#define IN_PTC1      PIN_A3
#define IN_PTC2      PIN_A4
#define LED1         PIN_A5
#define GSM_PWRKEY   PIN_A6
#define LED2         PIN_A7

#define ONE_WIRE_3   PIN_B0  //Pines del BUS B
#define ONE_WIRE_2   PIN_B1
#define ONE_WIRE_1   PIN_B2
#define V_BAT        PIN_B3
#define SERIAL_TX    PIN_B4
#define SERIAL_RX    PIN_B5

#define GSM_RI       PIN_C0   //Pines del BUS C
#define GSM_CTS      PIN_C1
#define GSM_VDD_EXT  PIN_C2
#define EEPROM_SCL   PIN_C3
#define EEPROM_SDA   PIN_C4
#define GSM_N_RESET  PIN_C5
#define GSM_RX       PIN_C6
#define GSM_TX       PIN_C7

#define IS_LEAP(year) (year%4 == 0)

// Valores ROM

//------------------------------- Includes -------------------------------------
//#include <lcd_f.c> 
#include <stdlib.h>

//--------------- Definicion de Usos de perifericos embebidos ------------------
#use rs232(STREAM=SERIAL,BAUD=9600,XMIT=SERIAL_TX,RCV=SERIAL_RX,DISABLE_INTS)
//#use rs232(STREAM=GSM,baud=115200,UART1,ERRORS)

//Variables tipo int1 de un bit.
int1              eco=0;
int1              cmd_start=0;
int1              r_error_touch;
int1              s_present;

//Variables tipo int o int8 con y sin signo.
int               CMD_Count;
int               i ;
int8 seconds = 05, Year=11,Month=2,Days=21,Hours=20,Minutes=48;
UNSIGNED INT      norebote_pluv=0;
UNSIGNED INT      norebote_wind=0;

//Variables tipo INT16 con y sin signo.

int16             pluv_factor;
//int16             segundos = 0 ;
unsigned int16    USec = 0 ;
unsigned INT16    speed_cont=0;
unsigned INT16    cent=0;
UNSIGNED int16    wind_time=0;
UNSIGNED INT16    pluv_count1;
UNSIGNED INT16    pluv_count2;
UNSIGNED INT32    wind_max;
UNSIGNED INT32    wind_factor;
UNSIGNED INT32    wind_prom;
unsigned int32    wind_speed;

// LONG

unsigned long y;

//Variables tipo Char.
char              Buffer[20];
char              factor[4];
char              CMD=0x00;
char              ID[4];
char              VER[4];


//Variables tipo Byte.
byte        i_buffer[8];
byte        temp_buffer[9];
byte        family;
byte        CRC;
   
// ***** Definicion de Funciones

void Long_String (UNSIGNED INT16 VALUE );
void var_write (int16 direccion);
void wind_calc (void);

void Test_CMD(void);
void Ejecutar(void);
void tx_msg(void);

int1 Escape=0; //Bandera utilizada para aplicar escape en caso de enter u otra forma que no sea con la tecla esc.
int1 Viaje=0; //
int1 Salida_msg_lcd; //
int1 Servicio; //Bandera de estado 1= En Servicio 0= Fuera de Servicio
int1 ExitRead=0;
int1              rs_rx_ex=1;

//int i;         //contador general**************

int menu=0;    //Contador de opcion del menu (se utiliza en la ejecucion)
int inter_menu=0;//Contador de menu antes de la eleccion del mismo se utiliza para mostrar las opciones
unsigned int mempos=0;    //Bariable de posision de memoria utilizado en la escritura de los mensajes
int count_actual;
unsigned int readmsg;

//char buffer[80];**************

CHAR mensaje[63];

#int_RB
// VERIFICO ENTRADAS DE LA INTERUPCION RB
void entradas_rb(void){
//disable_interrupts(GLOBAL);
output_toggle(LED1);
 
if (kbhit(SERIAL)){
   //if (SERIAL_RX != rs_rx_ex){
      output_toggle(LED2);
      CMD=fgetc(SERIAL);
      fputc(CMD,SERIAL);
   }
//enable_interrupts(GLOBAL);
}

void main (void){

//setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   // setup interrupts
//SETUP ADC
//   port_b_pullups(0);
  SET_TRIS_A( 0xFF );
  setup_comparator(NC_NC_NC_NC);
  setup_adc_ports( sAN3|sAN1|sAN0|sAN2|VSS_VDD );//AN0 AN1 AN9
  setup_adc( ADC_CLOCK_INTERNAL );
 
  DELAY_MS(500);
 
  fprintf(SERIAL,"PLACA DESARROLLO ESTACION VER 1.0 \r\n");
  //config_read();
 
   //set_timer1 (0);
  //input (PIN_B3);
  output_high(LED1);
  output_low(LED2);
   DELAY_MS(500);
  //Print_reset();
  //set_timer1(SetTimer);
  //enable_interrupts(INT_TIMER1);
  //able_interrupts(INT_EXT);
  enable_interrupts(INT_RB);
  enable_interrupts(GLOBAL);
  wind_prom=0; //Limpio el valor maximo de viento
  wind_max=wind_prom; //Limpio el valor maximo de viento
 
//isable_interrupts(GLOBAL);
  //fprintf(SERIAL,"\n\r Input CHAR: ");
//enable_interrupts(GLOBAL);
 while(1) {
 restart_wdt();
 if (kbhit(SERIAL)){
    CMD=fgetc(SERIAL);
    fputc(CMD,SERIAL);
   
    if (CMD=='0'){
       output_float(pin_a0);
       //delay_us(1);
       set_adc_channel(0);
       delay_ms(120);
       Read_ADC(ADC_START_ONLY );
       delay_ms(100);
       y=Read_ADC(ADC_READ_ONLY );
       fprintf(SERIAL,"\n\r AD1:%li",y);
    }
    if (CMD=='1'){
       set_adc_channel(1);
       delay_ms(110);
       y=Read_ADC();
       delay_ms(100);
       fprintf(SERIAL,"\n\r AD2:%li",y);
    }
    if (CMD=='2'){
       set_adc_channel(2);
       delay_ms(110);
       y=Read_ADC();
       delay_ms(100);
       fprintf(SERIAL,"\n\r AD2:%li",y);
    }
    if (CMD=='3'){
       set_adc_channel(3);
       delay_ms(110);
       y=Read_ADC();
       delay_ms(100);
       fprintf(SERIAL,"\n\r AD3:%li",y);
    }
 }
   
 }
 }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 2:01 pm     Reply with quote

Quote:

but when I power the pic with 3.4V the AD port always read 1023 and if I test the pin with multimeter I get 3.8V even when set the pin as input, or output Float.

Does this mean the Vdd for the PIC is 3.4 volts, and input voltage that you
connect to pin AN0 is 3.8 volts ? If so, that violates the Absolute Maximum
specification in the 16F886 data sheet. It says the input voltage can only
be up to Vdd + 0.3 volts, which is 3.7 volts in your case.

My advice is to cut the program down to a very small test program, with
only about 10 lines of code. Also, simplify the hardware. Only make
a connection to pin AN0 on the PIC. Make sure the input voltage on AN0
is less than the maximum limit allowed by the data sheet.

Also, don't use the Internal ADC clock. Every PIC data sheet has this
note in the A/D section:
Quote:

4: When the device frequency is greater than 1 MHz, the FRC clock source
is only recommended if the conversion will be performed during Sleep.

This table shows the correct A/D divisor for an 8 MHz oscillator is 32.
Quote:
TABLE 9-1: ADC CLOCK PERIOD (TAD) VS. DEVICE OPERATING FREQUENCIES (VDD > 3.0V)

That means you should use ADC_CLOCK_DIV_32 instead of
ADC_CLOCK_INTERNAL.

There are some other things wrong with your program. You have very
large delays after changing the A/D channel. You really only need a 5 us
delay, according to the 16F886 data sheet. You could use 10 us to be safe.


Also, you have a problem with your #int_rb function. You must read
Port B inside that interrupt function, to clear the "mismatch condition".
See this post for an example of how to do this:
http://www.ccsinfo.com/forum/viewtopic.php?t=44333&start=1


Quote:

#int_RB
// VERIFICO ENTRADAS DE LA INTERUPCION RB
void entradas_rb(void){
//disable_interrupts(GLOBAL);
output_toggle(LED1);

if (kbhit(SERIAL)){
//if (SERIAL_RX != rs_rx_ex){
output_toggle(LED2);
CMD=fgetc(SERIAL);
fputc(CMD,SERIAL);
}
//enable_interrupts(GLOBAL);
}

All the lines that you have commented out are incorrect, and should be
deleted or fixed. Don't enable/disable GLOBAL interrupts inside an
interrupt service routine. The compiler and the PIC will handle it.

Also, you can't read an i/o pin by testing its Pin constant value.
If you want to read the pin, you must use the input() function. Example:
Code:
if(input(SERIAL_RX) != rs_rx_ex)


There might be other things wrong with your program, but those are the
most immediate problems.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 2:06 pm     Reply with quote

There are a _lot_ of problems with this code.
1) You use INT_RB, but don't read portB in this interrupt. The RB 'changed' interrupt, is triggered when any of the portB pins differs from the state when it was last read. Once triggered, it'll trigger _for ever_, untill the port is read. This will hang the code.
2) ADC_CLOCK_INTERNAL, is _not_ recommended for operation above 1MHz.
3) Don't fiddle around starting the ADC and waiting. Just use 'read_adc()'.
4) Get rid of your TRIS settings. These are not needed, unless you are using FAST_IO mode.
5) Tidy your code. You have things like a comment saying 'Definicion de Funciones ', but most of what follows are variable defintions not functions. If you tidy things up you may be able to see why things don't work. There seem to be huge numbers of data defintions, and I/O defintions that are not actually being used...
6) Don't use serial receive/transmit in the portB change interrupt. Doing so, will lead to interrupts being disabled round these routines in the external code....

At this point I lost track.....

Best Wishes
JaviarV



Joined: 25 Feb 2011
Posts: 3
Location: Argentina

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 4:04 pm     Reply with quote

Hi, thanks for the reply.
The code was actually longer but I was only taking part to test the ADC port.
I post the code but I don't think that is a code problem because when I power the pic with 5V works OK.

The strange thing is that I'm using an0 and how it works would seem to have a pullup resistance.
JaviarV



Joined: 25 Feb 2011
Posts: 3
Location: Argentina

View user's profile Send private message

PostPosted: Wed Mar 02, 2011 4:11 pm     Reply with quote

Thank you all for your time, and found the problem, thanks to PCM programmer, I base that was not a code problem. If not something in the hardware, and so was the max232 I am using to connect to the PC was powered with 5V, and the zener to place on the circuit was 5.1V, replaces the zener with one of 3.1V and place a resistor Pin 1k RX_Serial and ready. ADC port works. Before placing the 3.1V Zener voltage is 4V had on RX_Serial.
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