SDCC: Driver para ADC PIC16f87x.
3 participantes
Página 1 de 1.
SDCC: Driver para ADC PIC16f87x.
Todavía un primer "boceto" hecho a partir del adc para pic18f* pero simplificado... aunque en realidad las funciones son bastante diferentes, no lo he probado, pero ahí vá:
EDITO:
Arreglados algunos fallos y probado que funciona en un pic16f876a, tanto el archivo para descargar como el código mostrado han sido actualizados.
Faltaría confirmar que funciona en otros pics y sinó ver como solucionarlo.
Archivo para descargar: adc_sdcc_sgr.h
Y aquí se puede echar un ojo al código:
EDITO:
Arreglados algunos fallos y probado que funciona en un pic16f876a, tanto el archivo para descargar como el código mostrado han sido actualizados.
Faltaría confirmar que funciona en otros pics y sinó ver como solucionarlo.
Archivo para descargar: adc_sdcc_sgr.h
Y aquí se puede echar un ojo al código:
- Código:
/*****************************************************************************
******************************************************************************
**** ****
**** --- DRIVER ADC para PIC16F --- ****
**** ****
******************************************************************************
******************************************************************************
FUNCIONES DISPONIBLES:
------------------------------------------------------------------------------
adc_init( FOSC_32, A5_R0, INT_OFF); iniciar módulo ADC, donde:
FOSC_32:
Frecuencia de adc, en este caso 1/32 de la del oscilador del pic
A5_R0:
Definir entradas analógicas y Vref, en este caso todas las 5 del pic16f876a como analógicas y ninguna como Vref, Vref serán Vdd y GND (ver las posibles combinaciones en el driver y datasheet del pic a usar.
INT_OFF:
Interrupciones ADC deshabilitadas, la otra posiblidad es INT_ON.
adc_read(1); Leer canal ADC.
adc_close(); cerrar módulo ADC.
******************************************************************************
*****************************************************************************/
/* flag de interrupciones on/off */
#define INT_OFF 0x00
#define INT_ON 0x01
/* frequencia de oscillador */
#define FOSC_2 0x00
#define FOSC_4 0x04
#define FOSC_8 0x01
#define FOSC_16 0x05
#define FOSC_32 0x02
#define FOSC_64 0x06
#define FOSC_RC 0x07
/* configuracion de entradas y Vref(PCFG en ADCON1) */
#define A8_R0 0x00
#define A7_R1 0x01
#define A5_R0 0x02
#define A4_R1 0x03
#define A3_R0 0x04
#define A2_R1 0x05
#define A0_R0 0x06
#define A6_R2 0x08
#define A6_R0 0x09
#define A5_R1 0x0a
#define A4_R2 0x0b
#define A3_R2 0x0c
#define A2_R2 0x0d
#define A1_R0 0x0e
#define A1_R2 0x0f
void adc_init(unsigned char fosc, unsigned char pcfg, unsigned char config)
{
ADCON0 = 0;
ADCON0 = (fosc & 0x03) << 6; // establecer frecuencia
ADCON1 = (pcfg & 0x0F) | 0x080; // establecer entradas
if (fosc & 0x04)
ADCS2 = 1;
if (config & INT_ON) // establecer interrupciones
{
ADIF = 0;
ADIE = 1;
PEIE = 1;
}
ADON = 1; // habilitar módulo ADC
}
void adc_close(void) // deshabilitar módulo ADC
{
ADON = 0;
ADIE = 0;
}
unsigned int adc_read(unsigned char canal)
{
unsigned int valor;
ADCON0 &= 0xC7; // borrar anteriores selecciones
ADCON0 |= (canal & 0x07) << 3; // establecer canal seleccionado
GO = 1; // iniciar conversión
while (GO); // esperar que termine
valor = ADRESH << 8 | ADRESL; // leer valor
return valor;
}
Última edición por arcachofo el Jue 25 Dic 2008 - 23:35, editado 1 vez
arcachofo- Participante Activo
- Mensajes : 91
Fecha de inscripción : 26/11/2008
SDCC: Driver para ADC PIC16f87x. Versión en ASM
Pues ahí vá una nueva versión del driver ADC, esta vez está escrita en ASM y dividiendo la función adc_read(canal) en dos: adc_open(canal) y adc_read() , así se disminuye el tamaño del ejecutable generado en caso de leer varias veces el mismo canal, también he sacado las funciones de interrupciones por adc: adc_int_on() y adc_int_off(). Dividiendo las funciones también se ahorran lineas ya que solo se insertan las que se usan.
Al estar escrito directamente en asm y todo lo optimizado que he podido, el tamaño del código generado es mucho menor, casi la mitad en comparación con el driver escrito en C.
EDITO:
Las funciones han cambiado un poco:
adc_init( fosc, channel ); //las posibles opcines las puedes ver en los #defines
ejemplo:
adc_init( FOSC_4, A2_R2 ); // fosc/4 y 2 entradas adc + 2 Vref (RA2 como - y RA3 como +)
adc_init( FOSC_64, A1_R0 ); //fosc/64 y 1 entrada adc + ninguna Vref
Para ver las distintas combinaciones de entradas adc y Vref ver el datasheet.
He separado la apertura y la lectura del canal, para ahorrar código y aumentar velocidad en caso de leer varias veces el mismo canal; tambien uso algunos #defines para disminuir instrucciones, en vez de poner el número del canal hay que ponerlo como: CH_1, CH_2, CH_3... etc.:
adc_open( CH_1 ); // abrir canal 1
adc_read(); // lee canal previamente abierto
adc_close(); //deshabilita módulo adc
Al estar escrito directamente en asm y todo lo optimizado que he podido, el tamaño del código generado es mucho menor, casi la mitad en comparación con el driver escrito en C.
EDITO:
Las funciones han cambiado un poco:
adc_init( fosc, channel ); //las posibles opcines las puedes ver en los #defines
ejemplo:
adc_init( FOSC_4, A2_R2 ); // fosc/4 y 2 entradas adc + 2 Vref (RA2 como - y RA3 como +)
adc_init( FOSC_64, A1_R0 ); //fosc/64 y 1 entrada adc + ninguna Vref
Para ver las distintas combinaciones de entradas adc y Vref ver el datasheet.
He separado la apertura y la lectura del canal, para ahorrar código y aumentar velocidad en caso de leer varias veces el mismo canal; tambien uso algunos #defines para disminuir instrucciones, en vez de poner el número del canal hay que ponerlo como: CH_1, CH_2, CH_3... etc.:
adc_open( CH_1 ); // abrir canal 1
adc_read(); // lee canal previamente abierto
adc_close(); //deshabilita módulo adc
- Código:
/*
This code is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// frequencia de oscillador: bit5=_ADCON1.ADCS2, bit6=_ADCON0.ADCS0, bit7=_ADCON0.ADCS1
#define FOSC_2 0x00
#define FOSC_4 0x20
#define FOSC_8 0x40
#define FOSC_16 0x60
#define FOSC_32 0x80
#define FOSC_64 0xA0
#define FOSC_RC 0xE0
// configuracion de entradas y Vref(PCFG0-3 en _ADCON1)
#define A8_R0 0x00
#define A7_R1 0x01
#define A5_R0 0x02
#define A4_R1 0x03
#define A3_R0 0x04
#define A2_R1 0x05
#define A0_R0 0x06
#define A6_R2 0x08
#define A6_R0 0x09
#define A5_R1 0x0a
#define A4_R2 0x0b
#define A3_R2 0x0c
#define A2_R2 0x0d
#define A1_R0 0x0e
#define A1_R2 0x0f
// selección de canal: usados bits 3-5 = ADCON0.CHS0-CHS2
#define CH_0 0x00
#define CH_1 0x08
#define CH_2 0x10
#define CH_3 0x18
#define CH_4 0x20
#define CH_5 0x28
#define CH_6 0x30
#define CH_7 0x38
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void adc_init(unsigned char fosc, unsigned char channel)
{
fosc;
channel;
_asm
BANKSEL STK01
MOVWF STK01 ;// fosc
// Ajustar _ADCON1
RLF STK01,W
ANDLW 0x40 ;// selecciona bit 6 de fosc (5º rotado)
IORWF STK00,W ;// Une channel y bit 6 de fosc (5º rotado)
BANKSEL ADCON1
MOVWF ADCON1 ;// Establece configuración de entradas y frecuencia (ADCS2)
BSF ADCON1,7 ;// Establece justificado a la derecha
// Ajustar _ADCON0
MOVF STK01,W ;// fosc
ANDLW 0xC0 ;// selecciona bits 6-7 de fosc (W)
BANKSEL ADCON0;
MOVWF ADCON0 ;// Establece frecuencia en _ADCON0 (ADCS0, ADCS1)
BSF ADCON0,0 ;// Habilita módulo ADC
_endasm;
}
void adc_open (unsigned char channel)
{
channel;
_asm
BANKSEL ADCON0
BCF ADCON0,3 ;// Borra anteriores selecciones
BCF ADCON0,4
BCF ADCON0,5
IORWF ADCON0,F ;// Establece canales abiertos (chanel en W)
_endasm;
}
unsigned int adc_read()
{
_asm
BANKSEL ADCON0
BSF ADCON0,2 ;// Inicia conversión
BTFSC ADCON0,2 ;// Espera que termine
GOTO $-1
BANKSEL ADRESL
MOVF ADRESL,W
BANKSEL STK00
MOVWF STK00
BANKSEL ADRESH
MOVF ADRESH,W
_endasm;
}
void adc_int_on()
{
_asm
BANKSEL PIE1
BSF PIE1,6 ;// Activa interrupciones ADC
BSF INTCON,6 ;// Activa inerrupciones periféricos
BANKSEL PIR1;
BCF PIR1,6 ;// Borra flag interrupciones ADC
_endasm;
}
void adc_int_off()
{
_asm
BANKSEL PIE1
BCF PIE1,6 ;// Desactiva interrupciones ADC
BANKSEL PIR1
BCF PIR1,6 ;// Borra flag interrupciones ADC
_endasm;
}
void adc_close()
{
adc_int_off();
_asm
BCF ADCON0,0 ;// Deshabilita módulo ADC
_endasm;
}
arcachofo- Participante Activo
- Mensajes : 91
Fecha de inscripción : 26/11/2008
Hola Gente
Bueno les hago una consulta, he visto que existe una librería adc para el 16f876, es posible usarla o modificarla para poder usar esa librería para el 16f818 o el 12f675, de ser así agradecería me pudieran ayudar..muchas gracias
Lalo- Participante
- Mensajes : 12
Fecha de inscripción : 03/03/2009
Edad : 46
Localización : Oberá
Re: SDCC: Driver para ADC PIC16f87x.
El tema sería mirar los datasheets de 16f818 y el 12f675, comparar los adcs con el del 16f876 y si usan los mismos registros pues se podría usar tla como está.
No estoy seguro pero creo que el 12f675 es distinto, pero el 16f818 quizás sea igual.
Saludos.
No estoy seguro pero creo que el 12f675 es distinto, pero el 16f818 quizás sea igual.
Saludos.
Re: SDCC: Driver para ADC PIC16f87x.
Muchas gracias Pikitin..un saludo
Lalo- Participante
- Mensajes : 12
Fecha de inscripción : 03/03/2009
Edad : 46
Localización : Oberá
Temas similares
» SDCC: Driver para LCD. PIC16F*
» SDCC: Driver para Usart PIC16*
» Librerías y ejemplos para SDCC
» ADC para PIC16F*, driver y ejemplo.
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
» SDCC: Driver para Usart PIC16*
» Librerías y ejemplos para SDCC
» ADC para PIC16F*, driver y ejemplo.
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.