如何解决我不知道我是否为 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 举报,一经查实,本站将立刻删除。