微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我不知道我是否为 PIC24F 正确初始化了 ADC

如何解决我不知道我是否为 PIC24F 正确初始化了 ADC

我正在使用 microchip Pic24f 板接收来自加速度计的 3 个模拟输入。

我收到 AN0 的信号,但 AN1 和 AN2 有信号,但值不正确。

这是我初始化 ADC 的代码

void InitADC(int amask) {
  AD1PCFG = 0xFFF8; // select AN0,AN1,AN2 as analog input
  AD1CON1 = 0x00E0; // auto convert @ end of sampling,Integer Data in.

  AD1CON2 = 0x0000; // use MUXA,AVss and AVdd used as Vref

  AD1CON3 = 0x1F01; // Tad = 2xTcy = 125ns. 31*Tad for conversion time.
  AD1CSSL = 0; // no scanning required
  AD1CHS=0;
  AD1CHS=1;
  AD1CHS=2;

  AD1CON1bits.ADON = 1; // Turn on the ADC
} // InitADC

在 main() 中:

TRISBbits.TRISB0 = 1;
TRISBbits.TRISB1 = 1;
TRISBbits.TRISB2 = 1;

然后我读取 AD1PCFG = 0xFFFE;用于不同功能中的每个模拟输入。

输入的结果由同一个函数读入

return ADC1BUF0;

我不确定对于 PIC24f 是否需要为每个 ANx 模拟输入使用 ADC1BUFx,或者我是否可以仅通过 ADC1BUF0 读取信号。

此外,我不知道是否需要扫描,对于 AD1CON2,由于使用了多个模拟输入,因此配置需要不同。

我对 PIC24f 还很陌生,到处寻找帮助,我能尝试的一切都让我在 LCD 上读取信号,但 AN1 和 AN2 数据不是它应该的样子。

如果有人能帮助我,我将不胜感激。

解决方法

这是一个示例,展示了我如何实现描述您可能使用的 ADC 类型的 Microchip 系列参考手册中的内容:

/*
 * File:   main.c
 * Author: dan1138
 * Target: PIC24FJ64GA002
 * IDE: MPLABX v5.45
 * Compiler: XC16 v1.61
 *  
 * Description:
 * 
 *  Initialize the ADC to convert voltage levels present on AN0,AN1 and AN5
 *  
 *  Map UART1 with TXD on RB0 and RXD on RB1.
 *  Map UART2 with TXD on RB8 and RXD on RB8.
 * 
 *  Initialize UART2 at 9600 baud and hook to printf.
 *
 * Created on March 11,2021,1:46 PM
 * 
 * See: https://stackoverflow.com/questions/66552251/i-do-not-know-if-i-am-initializing-adc-correctly-for-pic24f
 *
 *                            PIC24FJ64GA002
 *               +-----------------:_:-----------------+
 *   ICD_VPP -> :  1 MCLR                     VDD  28 : <- 3v3
 *           <> :  2 RA0/RP26/AN0             VSS  27 : <- GND
 *           <> :  3 RA1/RP27/AN1   AN9 /RP15/RB15 26 : <> LED4
 *   ICD_PGD <> :  4 RB0/PGD1/AN2   AN10/RP14/RB14 25 : <> LED5
 *   ICD_PGC <> :  5 RB1/PGC1/AN3   AN11/RP13/RB13 24 : <> LED6
 *           <> :  6 RB2/RP2/AN4    AN12/RP12/RB12 23 : <> LED7
 *       POT <> :  7 RB3/RP3/AN5         RP11/RB11 22 : <>
 *       GND -> :  8 VSS                 RP10/RB10 21 : <>
 * 7.3728MHz <> :  9 RA2/OSCI                 VCAP 20 : <- 10uF
 * 7.3728MHz <> : 10 RA3/OSCO                 VSS  19 : <- GND
 *           <> : 11 RB4/SOSC            RP9 /RB9  18 : <> RXD
 *           <> : 12 RA4/SOSC            RP8 /RB8  17 : <> TXD
 *       3v3 -> : 13 VDD           INT0/ RP7 /RB7  16 : <>
 *       SW1 <> : 14 RB5/RP5             RP6 /RB6  15 : <>
 *               +-------------------------------------+
 *                               DIP-28
 *
 */

// CONFIG2
#pragma config POSCMOD = NONE           // Primary Oscillator Select (Primary oscillator disabled)
#pragma config I2C1SEL = PRI            // I2C1 Pin Location Select (Use default SCL1/SDA1 pins)
#pragma config IOL1WAY = OFF            // IOLOCK Protection (IOLOCK may be changed via unlocking seq)
#pragma config OSCIOFNC = ON            // Primary Oscillator Output Function (OSC2/CLKO/RC15 functions as port I/O (RC15))
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = FRCPLL           // Oscillator Select (Fast RC Oscillator with PLL module (FRCPLL))
#pragma config SOSCSEL = SOSC           // Sec Oscillator Select (Default Secondary Oscillator (SOSC))
#pragma config WUTSEL = LEG             // Wake-up timer Select (Legacy Wake-up Timer)
#pragma config IESO = ON                // Internal External Switch Over Mode (IESO mode (Two-Speed Start-up) enabled)

// CONFIG1
#pragma config WDTPS = PS32768          // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128            // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = ON              // Watchdog Timer Window (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (Watchdog Timer is disabled)
#pragma config ICS = PGx1               // Comm Channel Select (Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1)
#pragma config GWRP = OFF               // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF                // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF             // JTAG Port Enable (JTAG port is disabled)

#define FCY (16000000ul)                // This define allows the delay macros to work

#include "xc.h"
#include <libpic30.h>
#include <stdio.h>

/* define map input pin numbers */
enum
{   
    RPI0  = 0,/* pin RB00 */ /* PGC1 */
    RPI1,/* pin RB01 */ /* PGD1 */
    RPI2,/* pin RB02 */
    RPI3,/* pin RB03 */
    RPI4,/* pin RB04 */
    RPI5,/* pin RB05 */
    RPI6,/* pin RB06 */
    RPI7,/* pin RB07 */
    RPI8,/* pin RB08 */
    RPI9,/* pin RB09 */
    RPI10,/* pin RB10 */
    RPI11,/* pin RB11 */
    RPI12,/* pin RB12 */
    RPI13,/* pin RB13 */
    RPI14,/* pin RB14 */
    RPI15,/* pin RB15 */
    RPI_NONE = 0x1f  
};  
    
/* define map output function numbers */
enum
{   
    RPO_NONE = 0,RPO_C1OUT,RPO_C2OUT,RPO_U1TX,RPO_U1RTS,RPO_U2TX,RPO_U2RTS,RPO_SDO1,RPO_SCK1OUT,RPO_SS1OUT,RPO_SDO2,RPO_SCK2OUT,RPO_SS2OUT,RPO_OC1=18,RPO_OC2,RPO_OC3,RPO_OC4,RPO_OC5,};  
    
/* Initialize this PIC */
void
PIC_Init(
    void
    )
{   
    /* 
    ** Disable all interrupt sources
    */ 
    __builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
    IEC0 = 0;
    IEC1 = 0;
    IEC2 = 0;
    IEC3 = 0;
    IEC4 = 0;
    __builtin_disi(0x0000); /* enable interrupts */

    CLKDIV =  0x0000; /* set for default clock operations */
    AD1PCFG = 0xffff; /* Set for digital I/O */
#ifdef AD1PCFGH
    AD1PCFGH = 0xffff;
#endif
    CMCON   = 0x0000;

    _NSTDIS = 1;    /* disable interrupt nesting */
    
    TRISA   = 0xFFFF;
    TRISB   = 0xFFFF;
    
    /* Unlock Registers */
    __builtin_write_OSCCONL(OSCCON & ~_OSCCON_IOLOCK_MASK);
    
    /* map inputs */
    
    _INT1R  = RPI_NONE; /* External Interrupt 1    */
    _INT2R  = RPI_NONE; /* External Interrupt 2    */
    _T2CKR  = RPI_NONE; /* Timer2 External Clock   */
    _T3CKR  = RPI_NONE; /* Timer3 External Clock   */
    _T4CKR  = RPI_NONE; /* Timer4 External Clock   */
    _T5CKR  = RPI_NONE; /* Timer5 External Clock   */
    _IC1R   = RPI_NONE; /* Input Capture 1         */
    _IC2R   = RPI_NONE; /* Input Capture 2         */
    _IC3R   = RPI_NONE; /* Input Capture 3         */
    _IC4R   = RPI_NONE; /* Input Capture 4         */
    _IC5R   = RPI_NONE; /* Input Capture 5         */
    _OCFAR  = RPI_NONE; /* Output Compare Fault A  */
    _OCFBR  = RPI_NONE; /* Output Compare Fault B  */
    _U1RXR  = RPI1;     /* UART1 Receive           */
    _U1CTSR = RPI_NONE; /* UART1 Clear To Send     */
    _U2RXR  = RPI9;     /* UART2 Receive           */
    _U2CTSR = RPI_NONE; /* UART2 Clear To Send     */
    _SDI1R  = RPI_NONE; /* SPI1 Data Input         */
    _SCK1R  = RPI_NONE; /* SPI1 Clock Input        */
    _SS1R   = RPI_NONE; /* SPI1 Slave Select Input */
    _SDI2R  = RPI_NONE; /* SPI2 Data Input         */
    _SCK2R  = RPI_NONE; /* SPI2 Clock Input        */
    _SS2R   = RPI_NONE; /* SPI2 Slave Select Input */
    
    /* map outputs */
    _RP0R   = RPO_U1TX;  /* U1 TXD */               /* pin RB00 */ /* PGC1 */
    _RP1R   = RPO_NONE;  /* U1 RXD */               /* pin RB01 */ /* PGD1 */
    _RP2R   = RPO_NONE;                             /* pin RB02 */
    _RP3R   = RPO_NONE;                             /* pin RB03 */
    _RP4R   = RPO_NONE;                             /* pin RB04 */
    _RP5R   = RPO_NONE;                             /* pin RB05 */
    _RP6R   = RPO_NONE;                             /* pin RB06 */
    _RP7R   = RPO_NONE;                             /* pin RB07 */
    _RP8R   = RPO_U2TX; /* U2 TXD */                /* pin RB08 */
    _RP9R   = RPO_NONE; /* U2 RXD */                /* pin RB09 */
    _RP10R  = RPO_NONE;                             /* pin RB10 */
    _RP11R  = RPO_NONE;                             /* pin RB11 */
    _RP12R  = RPO_NONE;                             /* pin RB12 */
    _RP13R  = RPO_NONE;                             /* pin RB13 */
    _RP14R  = RPO_NONE;                             /* pin RB14 */
    _RP15R  = RPO_NONE;                             /* pin RB15 */
    
    /* Lock Registers */
    __builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK);
}
/*
 * Initialize the ADC
 */
static const uint8_t Selector[] = {0x00,0x01,0x05};

void ADC_Init(void)
{
    AD1PCFGbits.PCFG0 = 0;  /* AN0/RA0 */
    AD1PCFGbits.PCFG1 = 0;  /* AN1/RA1 */
    AD1PCFGbits.PCFG5 = 0;  /* AN5/RB3 */

    TRISAbits.TRISA0 = 1;
    TRISAbits.TRISA1 = 1;
    TRISBbits.TRISB3 = 1;
    
    AD1CON1 = 0x0000;       // SAMP bit = 0 ends sampling and starts converting
    AD1CHS  = 0x0000;       // default to channel 0       
    AD1CSSL = 0;
    AD1CON3 = 0x0102;       // Manual Sample,TAD = 3 TCY,Auto-Sample Time 1 TAD
    AD1CON2 = 0;
    AD1CON1bits.ADON = 1;   // turn ADC ON

}
/*
 * ADC Read channel
 */
uint16_t ADC_ReadChannel(uint16_t Index)
{
    if(Index < sizeof(Selector))
    {
        AD1CHSbits.CH0SA = Selector[Index];
    }
    AD1CON1bits.SAMP = 1;   // start sampling...
    __delay_us(5);          // Ensure the correct sampling time has elapsed before starting conversion.
    AD1CON1bits.SAMP = 0;   // start converting
    for(;;)
    {
        if(AD1CON1bits.DONE) break; // conversion done?
    }
    
    return ADC1BUF0;  // yes then get ADC value
}
/*
 * Initialize UART2
 */
#define U2_BAUD 9600L
#define U2_BRGH_VALUE 0

#if U2_BRGH_VALUE
#define U2_BRGH_SCALE 4L
#else
#define U2_BRGH_SCALE 16L
#endif

#define U2_BRGREG (FCY/(U2_BRGH_SCALE * U2_BAUD)-1L)

#if U2_BRGREG > 65535
#error Cannot set up UART2 for the FCY and BAUDRATE. Correct values in init.h and uart.h files.
#endif

/*
** Check if baud error greater than 2.5 percent
*/
#define REAL_BAUDRATE ( FCY / ( U2_BRGH_SCALE * ( U2_BRGREG + 1L) ) )

#if (REAL_BAUDRATE > (U2_BAUD + (U2_BAUD * 25L) / 1000L)) || (REAL_BAUDRATE < (U2_BAUD - (U2_BAUD * 25L) / 1000L))
#error UART baudrate error greater than 2.5 percent for the FCY and U2_BAUD. Correct values in uart.c file.
#endif
#undef REAL_BAUDRATE

void UART2_Init(void)
{
    _U2TXIE = 0;
    _U2RXIE = 0;
    _U2ERIE = 0;
    _U2RXIP = 0b100;
    _U2TXIP = 0b100;
    _U2ERIP = 0b100;

    U2MODE = 0;
    U2STA = 0;

    U2BRG = U2_BRGREG;
    U2MODEbits.BRGH = U2_BRGH_VALUE;
    U2MODEbits.UARTEN = 1;
    U2STAbits.UTXEN  = 1;
}
void UART2_Write(uint8_t txData)
{
    while(U2STAbits.TRMT != 1);

    U2TXREG = txData;    // Write the data byte to the USART.
}
/*
 * hook for printf
 */
int __attribute__((__section__(".libc.write"))) write(int handle,void *buffer,unsigned int len) 
{
    unsigned int i;

    for (i = len; i; --i)
    {
        UART2_Write(*(char*)buffer++);
    }
    return(len);
}
/*
 * Main Application
 */
int main(void) 
{
    uint16_t ADC_results[sizeof(Selector)];
    uint16_t ADC_value;
    uint16_t NewResults;
    uint16_t Index;
    
    PIC_Init();
    ADC_Init();
    UART2_Init();
    
    printf("\r\nPIC24FJ64GA002 start,built on %s at %s\r\n",__DATE__,__TIME__);
    /*
     * Application loop
     */
    NewResults = 1;
    for(;;)
    {
        for(Index = 0; Index < sizeof(Selector); Index++)
        {
            ADC_value = ADC_ReadChannel(Index);
            if (ADC_value != ADC_results[Index])
            {
                NewResults |= 1;
            }
            ADC_results[Index] = ADC_value;
        }
        if(NewResults)
        {
            NewResults = 0;
            printf("Values");
            for(Index = 0; Index < (sizeof(ADC_results)/sizeof(*ADC_results) ); Index++)
            {
                printf(" AN%1u = %5u",Selector[Index],ADC_results[Index]);
            }
            printf("\r\n");
        }
        
    }
    return 0;
}

您在帖子中没有提供足够的信息来了解您实际使用的 55 个控制器中的哪一个。

我使用了我现在可以找到的 PIC24FJ64GA002 控制器,它具有您可以使用的 ADC 硬件。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。