You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPLAB X IDE v5.50中源文件与头文件语法问题求助

PIC32MK1024MCM ADC模块头文件/源文件整合错误排查

问题背景

我正在开发PIC32MK1024MCM项目代码,功能测试已经完成,现在正把所有模块整合到最终项目里(示例代码还没写完,但功能不是重点)。这是我第一次尝试用专业的方式,把不同模块的函数声明分离到头文件和源文件里,但ADC源文件几乎每一行都报错。我猜是源文件里漏了什么包含,但不确定具体是什么。第一次这么用头文件和源文件,求帮忙指出我明显漏了的内容。

现有代码

main.c

#include <xc.h>
#include <configuration_bits.c>

#include <toolchain_specifics.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "stdio.h"
#include <sys/attribs.h>

#include <analog_to_digital_conversion.h>

void main(void) {
    while (1){
    }
    return (EXIT_FAILURE);
}

configuration_bits.c

// DEVCFG3
#pragma config USERID = 0xFFFF // 输入十六进制值(输入十六进制值)
#pragma config PWMLOCK = OFF // PWM IOxCON锁(PWM IOxCON寄存器写入访问未被锁定或保护)
#pragma config FUSBIDIO2 = OFF // USB2 USBID选择(USBID引脚由端口功能控制)
#pragma config FVBUSIO2 = OFF // USB2 VBUSON选择位(VBUSON引脚由端口功能控制)
#pragma config PGL1WAY = OFF // 权限组单向锁定配置位(允许多次重新配置)
#pragma config PMDL1WAY = OFF // 外设模块禁用配置(允许多次重新配置)
#pragma config IOL1WAY = OFF // 外设引脚选择配置(允许多次重新配置)
#pragma config FUSBIDIO1 = OFF // USB1 USBID选择(USBID引脚由端口功能控制)
#pragma config FVBUSIO1 = OFF // USB2 VBUSON选择位(VBUSON引脚由端口功能控制)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1 // 系统PLL输入分频器(1分频)
#pragma config FPLLRNG = RANGE_BYPASS // 系统PLL输入范围(旁路)
#pragma config FPLLICLK = PLL_POSC // 系统PLL输入时钟选择(POSC作为系统PLL输入)
#pragma config FPLLMULT = MUL_4 // 系统PLL倍频器(PLL倍频4倍)
#pragma config FPLLODIV = DIV_2 // 系统PLL输出时钟分频器(2分频)
#pragma config BORSEL = HIGH // 欠压复位阈值(BOR阈值2.1v(非运算放大器设备操作))
#pragma config UPLLEN = OFF // USB PLL使能(USB PLL禁用)

// DEVCFG1
#pragma config FNOSC = POSC // 振荡器选择位(主振荡器(HS,EC))
#pragma config DMTINTV = WIN_0 // DMT计数窗口间隔(窗口/间隔值为0)
#pragma config FSOSCEN = OFF // 次级振荡器使能(禁用次级振荡器)
#pragma config IESO = ON // 内部/外部切换(启用)
#pragma config POSCMOD = HS // 主振荡器配置(HS振荡模式)
#pragma config OSCIOFNC = OFF // OSCO引脚输出CLKO信号(禁用)
#pragma config FCKSM = CSDCMD // 时钟切换与监控选择(时钟切换禁用,FSCM禁用)
#pragma config WDTPS = PS1 // 看门狗定时器预分频器(1:1)
#pragma config WDTSPGM = STOP // 闪存编程期间看门狗定时器停止(闪存编程时WDT停止)
#pragma config WINDIS = NORMAL // 看门狗定时器窗口模式(看门狗定时器处于非窗口模式)
#pragma config FWDTEN = OFF // 看门狗定时器使能(WDT禁用)
#pragma config FWDTWINSZ = WINSZ_25 // 看门狗定时器窗口大小(窗口大小为25%)
#pragma config DMTCNT = DMT31 // 看门狗定时器计数选择(2^31(2147483648))
#pragma config FDMTEN = OFF // 看门狗定时器使能(看门狗定时器禁用)

// DEVCFG0
#pragma config DEBUG = OFF // 后台调试器使能(调试器禁用)
#pragma config JTAGEN = OFF // JTAG使能(JTAG禁用)
#pragma config ICESEL = ICS_PGx1 // ICE/ICD通信通道选择(通过PGEC1/PGED1通信)
#pragma config TRCEN = OFF // 跟踪使能(CPU跟踪功能禁用)
#pragma config BOOTISA = MIPS32 // 启动ISA选择(启动代码和异常代码为MIPS32)
#pragma config FECCCON = ECC_DECC_DISABLE_ECCON_WRITABLE // 动态闪存ECC配置位(ECC和动态ECC禁用(ECCCON<1:0>位可写))
#pragma config FSLEEP = OFF // 闪存睡眠模式(设备处于睡眠模式时闪存断电)
#pragma config DBGPER = PG_ALL // 调试模式CPU访问权限(允许CPU访问所有权限区域)
#pragma config SMCLR = MCLR_NORM // 软主清除使能(MCLR引脚产生正常系统复位)
#pragma config SOSCGAIN = G3 // 次级振荡器增益控制位(增益为G3)
#pragma config SOSCBOOST = ON // 次级振荡器启动增强使能位(增强振荡器启动)
#pragma config POSCGAIN = G3 // 主振荡器粗增益控制位(增益等级3(最高))
#pragma config POSCBOOST = ON // 主振荡器启动增强使能位(增强振荡器启动)
#pragma config POSCFGAIN = G3 // 主振荡器细增益控制位(增益为G3)
#pragma config POSCAGCDLY = AGCRNG_x_25ms // AGC增益搜索步骤稳定时间控制(稳定时间=25ms x AGCRNG)
#pragma config POSCAGCRNG = ONE_X // AGC锁定范围位(范围1x)
#pragma config POSCAGC = Automatic // 主振荡器增益控制位(振荡器自动增益控制)
#pragma config EJTAGBEN = NORMAL // EJTAG启动使能(正常EJTAG功能)

// DEVCP
#pragma config CP = OFF // 代码保护(保护禁用)

// SEQ
#pragma config TSEQ = 0xFFFF // 启动闪存真实序列号(输入十六进制值)
#pragma config CSEQ = 0xFFFF // 启动闪存补全序列号(输入十六进制值)   

analog_to_digital_conversion.h

//**************************************************************************
// 模数转换头文件
//**************************************************************************

#include <analog_to_digital_conversion.c>

void Anaolog_to_Digital_Conversion_Setup (void);

void Anaolog_to_Digital_Conversion_Enable (void);

void Anaolog_to_Digital_Conversion_Disable (void);

uint16_t Anaolog_to_Digital_Conversion (void);

analog_to_digital_conversion.c

//**************************************************************************
// 模数转换源文件
//**************************************************************************

void Anaolog_to_Digital_Conversion_Setup (void){
    
    // 以下步骤均来自器件数据手册(无需ADC中断)

    ADCANCONbits.ANEN5 = 0b0; // 禁用模拟和偏置电路(用于设置校准)
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADC5CFGbits.ADCCFG = DEVADC5; // 将工厂校准ADC模块位复制到ADC配置寄存器
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCCON1bits.ON = 0b0; // 禁用ADC模块
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADC5TIMEbits.SAMC = 0b1111111111; // 采样时间设置为1025个TAD
    ADC5TIMEbits.ADCDIV = 0b1111111; // 254 * TQ = TAD(ADC时钟分频位)
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCANCONbits.WKUPCLKCNT = 0xF; // ADC预热时间设置为32768个ADC时钟周期(最大预热时间,100 MHz SYSCLK下约32微秒)
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCCON3bits.ADCSEL = 0b0; // 模数转换时钟源(TCLK)-> SYSCLK
    ADCCON3bits.CONCLKDIV = 0b000000; // TCLK = TQ
    ADCCON3bits.DIGEN5 = 0b0; // 禁用所有数字位(根据数据手册)
    ADCCON3bits.VREFSEL = 0b000; // 参考电压设置为AVdd和AVss
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCIMCON1bits.DIFF11 = 0b0; // AN11使用单端模式
    ADCIMCON1bits.SIGN11 = 0b0; // AN11使用无符号数据模式
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCTRGSNSbits.LVL11 = 0b0; // 模拟输入对触发信号的上升沿敏感(复位后默认值)
    //---------------------------------------------------------------
    ADCTRG3bits.TRGSRC11 = 0b00001; // AN11由软件触发
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCANCONbits.ANEN5 = 0b1; // 启用模拟和偏置电路
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCCON1bits.ON = 0b1; // 启用ADC模块
    //---------------------------------------------------------------
    while(!((ADCCON2bits.BGVRRDY)&&(ADCANCONbits.WKRDY5))); // 等待器件模拟环境就绪
    ADCCON3bits.DIGEN5 = 0b1; // 启用数字电路以进行数据处理
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCCON3bits.ADINSEL = 0b001011; // 选择模拟通道11进行转换
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------
    ADCCON1bits.ON = 0b0; // 禁用ADC模块
}

void Anaolog_to_Digital_Conversion_Enable (void){
       ADCCON1bits.ON = 0b1; // 启用ADC模块
}

void Anaolog_to_Digital_Conversion_Disable (void){
       ADCCON1bits.ON = 0b0; // 禁用ADC模块
}

uint16_t Anaolog_to_Digital_Conversion (void){
   uint16_t ADC_value = 0;
   
   ADCCON3bits.RQCNVRT = 1; // 触发转换
   
       while(!ADCDSTAT1bits.ARDY11); // 等待ADC结果就绪(100 MHz SYSCLK下转换约需2毫秒)
       
   ADC_value = ADCDATA11 & 0x000FFFF; // 获取ADC结果,寄存器为32位,但转换仅输出12位值,故去除高16位(均为0)
     
   return (ADC_value);
}

错误截图

ADC模块编译错误截图

错误原因及修复方案

1. ADC源文件缺少核心头文件包含

analog_to_digital_conversion.c里没有包含<xc.h>,所有PIC32的寄存器(如ADCANCONbits、ADC5CFGbits等)都未被定义,这是导致几乎每一行报错的核心原因。

修复:在analog_to_digital_conversion.c开头添加必要的头文件:

#include <xc.h>
#include <stdint.h>
#include "analog_to_digital_conversion.h"

2. 头文件错误包含源文件

analog_to_digital_conversion.h里的#include <analog_to_digital_conversion.c>完全错误,头文件的作用是声明函数/类型,包含源文件会导致代码重复编译,引发重复定义错误。

修复:删除该行,同时添加头文件保护(防止重复包含),并修正函数名拼写错误(Anaolog → Analog):

//**************************************************************************
// 模数转换头文件
//**************************************************************************
#ifndef ANALOG_TO_DIGITAL_CONVERSION_H
#define ANALOG_TO_DIGITAL_CONVERSION_H

#include <stdint.h>

void Analog_to_Digital_Conversion_Setup (void);

void Analog_to_Digital_Conversion_Enable (void);

void Analog_to_Digital_Conversion_Disable (void);

uint16_t Analog_to_Digital_Conversion (void);

#endif // ANALOG_TO_DIGITAL_CONVERSION_H

3. 函数名拼写不一致

所有函数名里的Anaolog是拼写错误,应该是Analog,会导致头文件声明和源文件定义不匹配。

修复:修改analog_to_digital_conversion.c里的所有函数名,和头文件保持一致:

void Analog_to_Digital_Conversion_Setup (void){
    // 原代码逻辑不变
}

void Analog_to_Digital_Conversion_Enable (void){
    // 原代码逻辑不变
}

void Analog_to_Digital_Conversion_Disable (void){
    // 原代码逻辑不变
}

uint16_t Analog_to_Digital_Conversion (void){
    // 原代码逻辑不变
}

4. 配置文件包含方式错误

main.c里#include <configuration_bits.c>会把配置文件的代码插入到main.c中,若configuration_bits.c同时被加入项目编译,会引发重复定义。

修复:将configuration_bits.c作为源文件直接加入项目编译,从main.c中删除该行包含。

5. 其他细节优化

  • ADC结果获取时,ADCDATA11 & 0x000FFFF可以改为ADCDATA11 & 0xFFF,因为12位结果只需要保留低12位。
  • 确保项目编译路径中包含头文件所在目录,避免找不到analog_to_digital_conversion.h。

内容的提问来源于stack exchange,提问作者Vilius Žalėnas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:31:41