TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: matocomasi en 17 de Septiembre de 2009, 18:31:24
-
Hola a todos,
Hoy traigo una pregunta que a lo mejor alguien me puede resolver, pero que de momento no he podido encontrar por ningun lado.
Se me ha ocurrido hacer un diseño con el PIC16f886 y sus 11 entradas analogicas, con un codigo muy basico en CCS y que despues simulo en Proteus.
Ahora me ha surgido un problema, a traves del puerto serie y con el virtual terminal del proteus voy viendo los valores de las entradas analogicas, pero las entradas AN11, AN12 y AN13 no funcionan, es mas si en CCS uso la funcion set_adc_channel(11) set_adc_channel(12) o set_adc_channel(13), proteus lanza un mensaje:
"Write to ADCON0 register selects channel 11. Threre is no such channel in PIC16F886 device."
"Attempt to sample non-existant ADC channel 11 (zero assumed)"
Alguien sabe si esto se debe a un fallo en el modelo del PIC16F886 en proteus o por el contrario es un error en la libreria del CCS.
Saludos.
-
postea el codigo, has intentado escribir directamente en el ADCON0 para elegir el canal?
intentá asi, definiendo el ADCON0
BYTE ADCON0=0X1F
cuando vayas a leer el ADC antes escribis sobre ADCON0 el canal que necesitas (bits 5 al 2) y luego realizar la lectura del canal...
saludos
-
Este es el codigo, como podeis ver es muy simple, esta hecho para CCS:
#include <16F886.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define delay 25
void main()
{
int8 a=0;
unsigned int16 recbuf[11];
unsigned int16 recbuf_ant[11];
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
while(TRUE)
{
set_adc_channel(0);
delay_us(delay);
recbuf[0]=read_adc();
set_adc_channel(1);
delay_us(delay);
recbuf[1]=read_adc();
set_adc_channel(2);
delay_us(delay);
recbuf[2]=read_adc();
set_adc_channel(3);
delay_us(delay);
recbuf[3]=read_adc();
set_adc_channel(4);
delay_us(delay);
recbuf[4]=read_adc();
set_adc_channel(8);
delay_us(delay);
recbuf[5]=read_adc();
set_adc_channel(9);
delay_us(delay);
recbuf[6]=read_adc();
set_adc_channel(10);
delay_us(delay);
recbuf[7]=read_adc();
set_adc_channel(11);
delay_us(delay);
recbuf[8]=read_adc();
set_adc_channel(12);
delay_us(delay);
recbuf[9]=read_adc();
set_adc_channel(13);
delay_us(delay);
recbuf[10]=read_adc();
for(a=0;a<=10;a++)
{
if(recbuf[a]!=recbuf_ant[a])
{
printf("recbuf[%d]=%Lu\r\n",a,recbuf[a]);
recbuf_ant[a]=recbuf[a];
}
}
}
}
Saludos
-
lo probaste en circuito armado? puede ser que funcione, sino, pienso que es un bug del CCS, y se tendría que hacer con defines de los registros, y seleccionarlo por ese medio
saludos
-
No, no lo he montado, solo lo he programado y simulado con proteus, normalmente primero lo simulo y cuando tengo certeza que su funcionamiento, entonces lo monto.
Saludos
-
proteus no es una herramienta de la cual hay que confiar mucho
te recomiendo que lo montes para descartar error del CCS
-
La librería 16f886.h nunca permite que se ingrese el número del puerto directamente, es decir, no puedes poner
set_adc_channel(1);
Tienes que usar los defines de la librería para que funcione correctamente.
// Constants used in SETUP_ADC_PORTS() are:
#define sAN0 1 //| A0
#define sAN1 2 //| A1
#define sAN2 4 //| A2
#define sAN3 8 //| A3
...
#define sAN11 0x80000 //| B4
#define sAN12 0x100000 //| B0
#define sAN13 0x200000 //| B5
#define NO_ANALOGS 0 // None
#define ALL_ANALOG 0x1F00FF // A0 A1 A2 A3 A5 E0 E1 E2 B0 B1 B2 B3 B4 B5
Lo valores que veías en el PRINTF también eran erróneos ya que solo debes elegir un puerto a la vez y al poner '5' por ejemplo estás eligiendo el puerto 0 y 3 al mismo tiempo.
-
Siento no estar de acuerdo contigo, siguiendo tus recomendaciones el proteus si que se vuelve loco.
Mi codigo tal y como está funciona correctamente excepto las tres ultimas entradas analogicas, el problema en mi opinion es que o bien el CCS o bien el proteus no esta gestionando correctamente los registros ADCON0 y ADCON1 y como a este nivel todos los registros estan ocultos al programador, no se bien que valores estan tomando. En ensamblador el programador tiene todo el control de los registros pero en C no sabe realmente los valores que toman.
Saludos
-
cargando en proteus el .cof que genera CCS, se puede hacer una especie de debug paso a paso, puedes ver las variables que tu creaste y los registros del micro
-
y como a este nivel todos los registros estan ocultos al programador, no se bien que valores estan tomando. En ensamblador el programador tiene todo el control de los registros pero en C no sabe realmente los valores que toman.
CCS tambien te muestra el codigo ASM que genera ahi puede revisar q valores se estan cargando en el ADCON0 y ADCON1
-
Otro error que veo en el programa es que nunca estableces el valor I/O del tris de cada pin a usar como analógico.
-
Si, ahi tienes razon, pero ya le puse los parametros del TRIS y sigue igual.
-
Hola de nuevo
Probé el programa con ligeras modificaciones... usando el set_adc_channel como tú lo haces (yo estaba mal)...
#include <16F886.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
#use standard_io(A)
#use standard_io(B)
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define delay 25
void main()
{
int8 a=0;
int16 recbuf[11];
set_tris_a(0xFF);
set_tris_b(0xFF);
set_tris_c(0xFF);
setup_adc_ports(ALL_ANALOG | VSS_VDD);
setup_adc(ADC_CLOCK_DIV_32);
while(TRUE)
{
set_adc_channel(0);
delay_us(delay);
recbuf[0]=read_adc();
set_adc_channel(1);
delay_us(delay);
recbuf[1]=read_adc();
set_adc_channel(2);
delay_us(delay);
recbuf[2]=read_adc();
set_adc_channel(3);
delay_us(delay);
recbuf[3]=read_adc();
set_adc_channel(4);
delay_us(delay);
recbuf[4]=read_adc();
set_adc_channel(8);
delay_us(delay);
recbuf[5]=read_adc();
set_adc_channel(9);
delay_us(delay);
recbuf[6]=read_adc();
set_adc_channel(10);
delay_us(delay);
recbuf[7]=read_adc();
set_adc_channel(11);
delay_us(delay);
recbuf[8]=read_adc();
set_adc_channel(12);
delay_us(delay);
recbuf[9]=read_adc();
set_adc_channel(13);
delay_us(delay);
recbuf[10]=read_adc();
for(a=0;a<11;++a)
printf("recbuf[%u]=%Lu\r\n",a,recbuf[a]);
}
}
El compilador CCS elige correctamente el canal a medir, especialmente los 11, 12 y 13, llenando correctamente ADCON0 con el valor CHS<3:0> = 1011 para canal 11 por ejemplo.
Cuando Proteus pasa por la selección del canal 11, 12 o 13 avisa que ese analógico no existe en el modelo 886, pero eso es un error. Asumo que es un bug del modelo 886 de Proteus, porque CCS compila correctamente. Si lo llegas a probar físicamente nos avisas si funciona.
(http://img27.imageshack.us/img27/3610/proteus.th.png) (http://img27.imageshack.us/img27/3610/proteus.png)
En una segunda prueba cambié el set_adc_channel a 5, recordando que el 886 no tiene AN5 y Proteus no se queja de ninguna manera, aunque se sigue quejando con el 11, 12 y 13.
Es muy seguro que sea un bug y que por implementar el 886 de manera rápida, la gente de Proteus haya ignorado que AN5, An6 y AN7 no existen en el modelo, pero sí existen AN11, 12 y 13.
-
Finalmente me voy a decicir a montarlo.
Tan pronto como lo haya probado posteare los resultados ya que seguramente a alguien le será de ayuda saber si realmente el Proteus tiene un bug en el pic16f886.
Gracias a todos
-
Hola a todos,
Hoy he montado el circuito con el pic16f886 y efectivamente el problema estaba en PROTEUS, el circuito funciona correctamente, asi que por mi parte cierro este tema.
Saludos
-
OK, gracias por avisarnos.
Yo lo probé en Proteus 7.5 SP3 sin éxito, ¿qué versión tienes tú?
-
Hola a todos,
Hoy he montado el circuito con el pic16f886 y efectivamente el problema estaba en PROTEUS, el circuito funciona correctamente, asi que por mi parte cierro este tema.
Saludos
viste? :P
-
Yo uso la version 7.2 sp0
-
¿No existira alguna forma de corregir ese error de proteus?
es decir entrar en el programa y cambiarle esos datos para que no produsca esos errores.
-
Talvez se pueda, pero creo que habría que empezar decompilando las DLL de los pics...
C:\Archivos de programa\Labcenter Electronics\Proteus 7 Professional\MODELS\pic16.DLL
Es mucho más fácil hablar a soporte técnico de Labcenter y comentar el bug.