Microcontroladores PIC en Linux.
¿Quieres reaccionar a este mensaje? Regístrate en el foro con unos pocos clics o inicia sesión para continuar.

SDCC: Driver para ADC PIC16f87x.

3 participantes

Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty SDCC: Driver para ADC PIC16f87x.

Mensaje por arcachofo Miér 3 Dic 2008 - 9:07

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:

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
arcachofo
Participante Activo
Participante Activo

Mensajes : 91
Fecha de inscripción : 26/11/2008

Volver arriba Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty SDCC: Driver para ADC PIC16f87x. Versión en ASM

Mensaje por arcachofo Jue 25 Dic 2008 - 23:33

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



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
arcachofo
Participante Activo
Participante Activo

Mensajes : 91
Fecha de inscripción : 26/11/2008

Volver arriba Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty Hola Gente

Mensaje por Lalo Mar 16 Ago 2011 - 10:57

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
Participante

Mensajes : 12
Fecha de inscripción : 03/03/2009
Edad : 46
Localización : Oberá

Volver arriba Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty Re: SDCC: Driver para ADC PIC16f87x.

Mensaje por Pikitin Miér 17 Ago 2011 - 16:45

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.

Pikitin
veterano
veterano

Mensajes : 623
Fecha de inscripción : 26/11/2008

http://linuxmicros.blogspot.com/

Volver arriba Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty Re: SDCC: Driver para ADC PIC16f87x.

Mensaje por Lalo Mar 23 Ago 2011 - 13:07

Muchas gracias Pikitin..un saludo

Lalo
Participante
Participante

Mensajes : 12
Fecha de inscripción : 03/03/2009
Edad : 46
Localización : Oberá

Volver arriba Ir abajo

SDCC: Driver para ADC PIC16f87x. Empty Re: SDCC: Driver para ADC PIC16f87x.

Mensaje por Contenido patrocinado


Contenido patrocinado


Volver arriba Ir abajo

Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.