|
|
View previous topic :: View next topic |
Author |
Message |
JaviarV
Joined: 25 Feb 2011 Posts: 3 Location: Argentina
|
ADC Problem With 16F886 At 3.4V |
Posted: Fri Feb 25, 2011 11:00 am |
|
|
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
|
|
Posted: Fri Feb 25, 2011 2:01 pm |
|
|
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
|
|
Posted: Fri Feb 25, 2011 2:06 pm |
|
|
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
|
|
Posted: Fri Feb 25, 2011 4:04 pm |
|
|
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
|
|
Posted: Wed Mar 02, 2011 4:11 pm |
|
|
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. |
|
|
|
|
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
|