PIC12 DAC no tiene salida

1

Tengo un PIC12F1571 (hoja de datos aquí: enlace ) que he programado para leer un entrada analógica, realice algún procesamiento en el valor leído y, a continuación, obtenga un valor relacionado en el DAC de onchip.

Para las pruebas, he conectado un potenciómetro a la entrada analógica y puedo ver en el depurador de MPLAB que el PIC está leyendo el valor correcto (ADRESH / ADRESL están configurados adecuadamente por el ADC). También he verificado que los bits DAC se configuran correctamente en los registros DACCON0 y DACCON1. En el depurador puedo ver que el DAC se configura en la salida correcta, pero no hay voltaje en el pin de salida.

He comprobado dos veces la dirección de mi registro TRISA para los pines apropiados, me he asegurado de que el registro de función de pin alternativo no tenga conflictos y que todo lo demás esté deshabilitado.

El código está debajo. He configurado el PIC para que RA4 - pin 3 (Canal analógico 3) se use como entrada ADC y RA0 - pin 7 como salida DAC.

#if defined(__XC)
  #include <xc.h>         /* XC8 General Include File */
#endif

#include <stdio.h>
#include <stdlib.h>

#include <pic12f1571.h>

#define SYS_FREQ        500000L
//#define FCY             SYS_FREQ/4

//Set up using the Memory View (Window -> PIC Memory Views -> Configuration Bits
// CONFIG1
#pragma config FOSC = INTOSC       //  (ECH, External Clock, High Power Mode (4-32 MHz); device clock supplied to CLKIN pin)
#pragma config WDTE = OFF        // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOREN = OFF    // Low Power Brown-out Reset enable bit (LPBOR is disabled)
#pragma config LVP = OFF         // Low-Voltage Programming Enable (Low-voltage programming enabled)


void setup(void)
{
 /* Configure Interrupts
 * INTCON - Interrupt Control Register:
 * Set GIE (Global Interrupt Enable)
 * Set PEIE (Peripheral Interrupt Enable bit (for ADC interrupts)
 * Set TMR0IE (Timer0 Overflow Interrupt Enable bit)
 *
 * PEI1 - Peripheral Interrupt Enable Register:
 * Set ADIE (ADC Interrupt Enable bit)
 */
    INTCON = 0xE0;
    PIE1 = 0x40;
    PIE2 = 0x00;
    PIE3 = 0x00;

/* Configure PORTA for the following:
 *
 * Configure TRISA for Port A Direction Control
 * only have 1 input pin - RA4
 * 1 output pin - RA0 (for DAC1)
 *
 * Configure ODCONA for Open-drain Control
 * PORTA configured as standard push-pull
 *
 * Configure SLRCONA for Slew Rate Control
 * Slew rate is unlimited
 *
 * Configure INLVLA for Input Threshold Control
 * Doesn't need to be set since all input is analog
 *
 * Configure ANSEL registers for ADC operation on AN3 (RA4/pin 3)
 */
    TRISA = 0x10;
    ODCONA = 0x00;
    SLRCONA = 0x00;
    INLVLA = 0x00;
    ANSELA = 0x10;

    /* Configure TIMER0
     *
     * In OPTION_REG:
     * Select Internal instruction clock
     * Select no prescaler on the timer
     *
     *  */
    OPTION_REG = 0x84;

    /* Configure ADC
     *
     * Set ADCON0 to the following:
     * CHS set to analog channel AN3 = 00011 (RA4/pin 3)
     * ADON set to ADC enabled = 1
     *
     * Set ADCON1 to the following:
     * ADFM set to left justified = 0 (so that we can get away with reading a
     *   single byte for our converted value)
     * ADCS Conversion clock source set to Fosc/8 = 001
     * ADPREF set to Vdd reference = 00
     *
     * Set ADCON2 to trigger on Timer0 overflow
     * ADCON2:TRIGSEL = 0011

     */
    ADCON0 = 0x0D;
    ADCON1 = 0x10;
    ADCON2 = 0x30;

    /* Configure up DAC
     * Set DACCON0 register:
     * DACEN set to DAC enabled = 1
     * DACOE set to voltage level output = 1
     * DACPSS<1:0> is set to Vdd = 00
     *
     * DACCON1 register contains the DACR bits (i.e. the output value)
     *
     */
    DACCON0 = 0xA0;
    DACCON1 = 0x00;

    // Set APFCON register to
    APFCON = 0xFF;
}

void interrupt isr(void)
{
    if(TMR0IF)
    {
        TMR0IF = 0; /* Clear TIMER0 Overflow Interrupt Flag*/
        //ADC will automatically start converting now

    //    ++counter;
    }

    if(ADIF)
    {   /* Clear ADC Completion Interrupt Flag */
        ADIF = 0;
        DACCON1 = ADRESH >> 3;
    }
}

int main(int argc, char** argv) {
    setup();
    while(1);
    return (EXIT_SUCCESS);
}

¿Qué me estoy perdiendo? Esto debería ser fácil ...

    
pregunta Antony M.

4 respuestas

3

Creo que el código funcionó todo el tiempo, el problema era que el DAC no generaba nada cuando el PIC estaba programado para el modo de depuración. Esto se debe a que el pin RA0 también se usa para ICSPDAT, así que hubo un conflicto y supongo que el compilador / IDE decidió no emitir nada en realidad. Verifiqué que no era solo un tirón hacia abajo en el programador de PICKit3. desconectando el cable. Definitivamente un problema con la programación del PIC en modo de depuración.

Programó el PIC en modo regular y las salidas DAC simplemente bien, aunque si el PICKit3 se deja conectado al pin de salida DAC, el voltaje máximo es 1/3 de Vdd. Esto también tiene sentido.

Al final, su error de usuario.

    
respondido por el Antony M.
0

No parece que le esté diciendo a su ADC que haga una conversión, aunque haya habilitado el módulo. En el PIC18F que uso, tengo que escribir específicamente un 1 en el bit GO / ~ DONE de ADCON0 para decirle que quiero que se convierta algo. Cuando esté hecho, levantará la interrupción. No se convierte sin que usted lo solicite primero, por lo que al mirar su código nunca lo hace, simplemente espera para siempre. Echando un vistazo a la hoja de datos, este parece que funciona igual que el chip que utilizo.

    
respondido por el BB ON
0

Si habla de DAC, le mostraré un código siguiente.

Pero creo que estás confundiendo ADC con DAC.

Funciona exactamente con mi propio pic12f1572.

int main(void)
{    
    OSCCON = 0b01111000; // for example,16 MHz    
    ANSELA = 0b00000000; // all pins to digital    
    PORTA  = 0b00000000; // all port bits off    
    TRISA  = 0b00001000; // all pins to outputs except RA3 (MCLR)    
    ADCON0 = 0b01111000;  // use DAC   
    DACCON0= 0b10100000;  // DAC enable, VDD as reference  
    DACCON1= 0b00011111;  // for example,32 as output = VDD
}
    
respondido por el John
0

Estoy usando el pic12F1572 para proporcionar un DAC pero, si puse un alcance en la salida, se vio la respuesta correcta, pero si me conecté a una carga mucho menor que 100k, la salida fue no lineal o cero. Revisé la hoja de datos e implicaba que esto era un relé destinado a generar voltajes de referencia para ser usados dentro del chip. Mi solución fue poner un pequeño amplificador operacional FET en la salida como controlador y todo está bien.

    
respondido por el Ruaridh

Lea otras preguntas en las etiquetas