接收“未定义符号".有关plib I2C功能的XC8错误 [英] Receiving "undefined symbols" error with XC8 concerning plib I2C functions

查看:192
本文介绍了接收“未定义符号".有关plib I2C功能的XC8错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,那里有StackOverflow!

Hey there StackOverflow!

我的问题与以下(远)粘贴的程序中的报告错误有关.目标器件是 PIC12LF1552 ,它具有一个串行外设,我认为可以与Microchip XC8编译器提供的库一起使用.互联网上的一些消息来源说,只有PIC18系列中的高端设备才支持库功能,另一些消息来源则说库功能可以正常工作.因此,我决定不想从头开始重写I2C函数,也不想为该项目编写任何程序集.因此,我决定使用XC8随附的提供的外围设备库.我阅读了有关如何获取它们的编译器文档(如下面的i2c.h所示).我知道根据文档和一些示例,我对这些命令进行了一些错误检查,但就目前而言,我假设主机和从机都将表现良好,因此我可以解决这个问题地面.

My question concerns errors being reporting within the program pasted (far) below. The target device is the PIC12LF1552, it has one serial peripheral on it that I assumed could be used in conjunction with the library supplied with Microchip's XC8 compiler. Some sources on the internet have said that only higher end devices in the PIC18 line would support the library functions, other sources have said the library functions work just fine. So I decided that I didn't want to rewrite the I2C functions from scratch, nor did I want to write any amount of assembly for this project. Thus I settled on using the provided peripheral library that comes with XC8. I read up on the compiler documentation for how to source them (as seen in i2c.h below). I know theres some error checking to do on those commands as per the documentation and some examples I've seen, but for the time being I'm assuming that both the master and the slave will behave perfectly just so I can get this thing off the ground.

我已经包含了所有相关路径,这就是为什么我认为它在编译过程中走得那么远的原因.关于C语言和编译器的内部工作,我的知识水平非常有限,我只知道如何在基本水平上使用这些工具,因此这里可能缺少一些基本知识.

I have included all relevant paths, which is why I assume it gets this far in the compilation process. My level of knowledge when it comes to the inner workings of a C language and compiler is very limited, I only know how to use these tools at a basic level, so there might be something fundamental I'm missing here.

无论如何,当我在MPLABX v1.95中编译此代码时,我得到了:

Anyways, when I compile this code in MPLABX v1.95, I get this:

:0: error: undefined symbols: _AckI2C(dist/pickit3/production\strobe.X.production.obj) _ReadI2C(dist/pickit3/production\strobe.X.production.obj) _IdleI2C(dist/pickit3/production\strobe.X.production.obj) _OpenI2C(dist/pickit3/production\strobe.X.production.obj) _StopI2C(dist/pickit3/production\strobe.X.production.obj) _NotAckI2C(dist/pickit3/production\strobe.X.production.obj) _WriteI2C(dist/pickit3/production\strobe.X.production.obj) _StartI2C(dist/pickit3/production\strobe.X.production.obj)

:0: error: undefined symbols: _AckI2C(dist/pickit3/production\strobe.X.production.obj) _ReadI2C(dist/pickit3/production\strobe.X.production.obj) _IdleI2C(dist/pickit3/production\strobe.X.production.obj) _OpenI2C(dist/pickit3/production\strobe.X.production.obj) _StopI2C(dist/pickit3/production\strobe.X.production.obj) _NotAckI2C(dist/pickit3/production\strobe.X.production.obj) _WriteI2C(dist/pickit3/production\strobe.X.production.obj) _StartI2C(dist/pickit3/production\strobe.X.production.obj)

我在Google,StackOverflow上找不到任何相关的内容,或者从我的特定上下文中未找到与此问题相关的其他内容(另一个人从Microchip的旧版C18编译器移植时遇到了非常相似的问题,但是我已经做了所有可以解决的事情)他的问题).

I couldn't find anything relevant on Google, StackOverflow, or otherwise concerning this problem from my specific context (another guy had a very similar issue when porting from Microchip's legacy C18 compiler, but I already did everything that guy did to solve his problem).

所以我想,问题是,为什么会出现此编译器错误,而导致这种情况的C语言或Microchip的实现背后的机制是什么?

/* 
 * File:   i2c.h
 * Author: James
 *
 * Created on July 23, 2014, 9:02 PM
 */

#ifndef I2C_H
#define I2C_H

#ifdef  __cplusplus
extern "C" {
#endif

#ifdef  __cplusplus
}
#endif

#include <plib\pconfig.h>
#include <plib\i2c.h>

#define SLAVE_ADDRESS 0b11110000

void Connect();
void Disconnect();
void Read(unsigned char address, unsigned char * data, unsigned char length);
void Write(unsigned char address, unsigned char * data, unsigned char length);

#endif  /* I2C_H */


#include "i2c.h"

void Connect()
{
    OpenI2C(MASTER, SLEW_OFF);
}

void Disconnect()
{
    CloseI2C();
}

void Read(unsigned char address, unsigned char * data, unsigned char length)
{
    IdleI2C();                                          // Wait until the bus is idle
    StartI2C();                                         // Send START condition
    IdleI2C();                                          // Wait for the end of the START condition
    if (WriteI2C(SLAVE_ADDRESS | 0x01)) return;         // Send slave address with R/W cleared for write
    IdleI2C();                                          // Wait for ACK
    if (WriteI2C(address)) return;                      // Send register address
    IdleI2C();                                          // Wait for ACK
    for(int i = 0; i < length; i++)
    {
        data[i] = ReadI2C();                            // Write nth byte of data
        AckI2C();                                       // Wait for ACK
    }
    NotAckI2C();                                        // Send NACK
    StopI2C();                                          // Hang up, send STOP condition
}

void Write(unsigned char address, unsigned char * data, unsigned char length)
{
    IdleI2C();                                          // Wait until the bus is idle
    StartI2C();                                         // Send START condition
    IdleI2C();                                          // Wait for the end of the START condition
    if (WriteI2C(SLAVE_ADDRESS | 0x01)) return;         // Send slave address with R/W cleared for write
    IdleI2C();                                          // Wait for ACK
    if (WriteI2C(address)) return;                      // Send register address
    IdleI2C();                                          // Wait for ACK
    for(int i = 0; i < length; i++)
    {
        WriteI2C(data[i]);                              // Write nth byte of data
        IdleI2C();                                      // Wait for ACK
    }
    StopI2C();                                          // Hang up, send STOP condition
}

/* 
 * File:   main.c
 * Author: James
 *
 * Created on July 14, 2014, 11:00 PM
 */

/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

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

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <stdio.h>
#include <stdlib.h>
#include <pic12lf1552.h>
#include "i2c.h"

/******************************************************************************/
/* Defines                                                                    */
/******************************************************************************/

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

__CONFIG
(
    MCLRE_ON &
    CP_OFF &
    BOREN_OFF &
    WDTE_OFF &
    PWRTE_OFF &
    FOSC_INTOSC
);

void main(void)
{
    ANSELA = 0;
    TRISA = 0b101111;
    OPTION_REG = 0b01111111;
    APFCONbits.SDSEL = 1;

    unsigned char state = 0;
    unsigned char count = 0;
    unsigned char data[8] = { 0 };

    Connect();
    Read
    (
        0x01, // System register
        data, // Data buffer
        0x01  // Read length
    );
    LATAbits.LATA4 = data[0];

    while(1)
    {
        switch (state)
        {
            case 0: // IDLE/OFF
                if (LATAbits.LATA4) LATAbits.LATA4 = 0;
                break;
            case 1: // ON
                if (!LATAbits.LATA4) LATAbits.LATA4 = 1;
                break;
            case 2: // BLINK (slow)
                LATAbits.LATA4 = !LATAbits.LATA4;
                __delay_ms(100);
                break;
            case 3: // BLINK (fast)
                LATAbits.LATA4 = !LATAbits.LATA4;
                __delay_ms(50);
                break;
            case 4: // BEAT DETECT
                LATAbits.LATA4 = PORTAbits.RA5;
                break;
            default:
                state = 0;
                break;
        }

        if (TMR0 > 0)
        {
            while (count < 20)
            {
                if (!PORTAbits.RA2) count = 0;
                __delay_ms(10);
                count++;
            }
            TMR0 = 0;
            state++;
        }
    }
}

推荐答案

问题定义

此处的核心问题是,Microchip XC8外设库(如其前身C18外设库)不支持PIC18系列以外的微控制器.因此,尽管有很多相似之处,但是有一堆头文件可以正确配置外设,并且所有寄存器宏都特定于PIC18系列.

Problem Definition

The core problem here is that the Microchip XC8 peripheral library, like its predecessor the C18 peripheral library does not support microcontrollers outside of the PIC18 series. So theres a whole bunch of header files that configure the peripherals correctly and all the register macros are specific to the PIC18 line, although there are vast similarities.

但是,由于Microchip在以下目录中为其外围设备库提供了源代码:/path/to/xc8/install/directory/version/sources/pic18/plib

However, as Microchip provides the sources to their peripheral library inside this directory: /path/to/xc8/install/directory/version/sources/pic18/plib

在我的情况下,特别是对于Windows x64计算机上的i2c源: C:\Program Files (x86)\Microchip\xc8\v1.21\sources\pic18\plib\i2c

Specifically in my case for the i2c sources on a Windows x64 machine: C:\Program Files (x86)\Microchip\xc8\v1.21\sources\pic18\plib\i2c

对于 PIC12LF1552 ,该芯片具有一个MSSP,因此您需要复制i2c _ *.c源并将其连接起来,如果您的PC上有任何Linux/Unix实用程序,则可以为此:cat i2c_* > i2c.c

For the PIC12LF1552, the chip has one MSSP so you'll want to copy the i2c_*.c sources and concatenate them, if you have any Linux/Unix utilities on your PC, you can do this: cat i2c_* > i2c.c

现在,首先,要么删除文件中的所有I2C版本定义,要么更简单地进入当前构建配置文件下的xc8编译器设置,并设置以下define宏:I2C_V1

Now, first things first, either rip out all the I2C version defines in the files, or, more simply, go into your xc8 compiler settings under your current build profile and set the following define macro: I2C_V1

此后,您需要对v1.21版本的源进行一些修改,以使其与设备兼容:

Afterwards, there are a few modifications you'll need to make from the v1.21 version of the sources for it to be compatible with the device:

  • 在您的i2c.c版本的头文件中输入:#include <pic12lf1552.h>,以便其余代码具有所有寄存器定义的内容
  • i2c.h中为您的SDA和SCL引脚添加定义,以便OpenI2C()起作用或只是将OpenI2C()更改为特定于设备:
    • #define I2C_SCL TRISAbits.TRISA1
    • #define I2C_SDA TRISAbits.TRISA2TRISAbits.TRISA3,具体取决于您的APFCONbits.SDSEL设置.尽管在PIC12LF1552上,RA3始终设置为输入.
    • In the header file for your version of i2c.c put: #include <pic12lf1552.h> so that the rest of the code has all the register defines
    • Add the defines for your SDA and SCL pins in i2c.h so that OpenI2C() works or simply change OpenI2C() to be specific to the device:
      • #define I2C_SCL TRISAbits.TRISA1
      • #define I2C_SDA TRISAbits.TRISA2 OR TRISAbits.TRISA3 depending on your APFCONbits.SDSEL setting. Although on the PIC12LF1552, RA3 is always set to input.
      • SSPSTATbits.R_W -> SSPSTATbits.R_nW
      • PIR1bits.SSPIF -> PIR1bits.SSP1IF
      • PIR2bits.BCLIF -> PIR2bits.BCL1IF
      • 我发现后两个很奇怪,因为数据表中的定义仍然没有IF之前的1,但是谁知道,也许Microchip有一个特殊的内部原因
      • SSPSTATbits.R_W -> SSPSTATbits.R_nW
      • PIR1bits.SSPIF -> PIR1bits.SSP1IF
      • PIR2bits.BCLIF -> PIR2bits.BCL1IF
      • The latter two I found odd as the datasheet still defines them without the 1 before the IF, but who knows, maybe Microchip has a special internal reason for that

      所有这些之后,您仍然需要编写自己的包装程序,以像我所提出的那样为主/从模式执行基本的完全形成的功能.

      After all of this, you'll still need to write your own wrappers to perform basic fully formed functions for Master/Slave modes as I have in my question.

      可以这么说,这整个过程比拔牙还差. Microchip的社区是自大的还是不屑一顾的(使用汇编",自己编写"等等). Microchip自己的支持也无济于事.最重要的是,实际代码需要很小的面向细节的更改,这几乎没有任何意义,IF -> 1IF认真吗?毕竟,您需要为这些功能编写自己的包装程序以进行逻辑I2C事务,更不用说测试整个设备以确保它不会浮出水面.难怪没有自定义布局和/或成本要求的人会使用Arduino.

      This entire process was worse than pulling teeth, so to speak. Microchip's community was arrogant or dismissive ("use assembly", "write it yourself", and so forth). Microchip's own support was also unhelpful. And on top of this, the actual code needed very small detail oriented changes that make almost no sense, IF -> 1IF seriously? And after all of that you need to write your own wrappers for those functions to make a logical I2C transaction and not to mention test the entire apparatus to make sure it doesn't fall on its face. No wonder people who don't have custom layout and/or cost requirements use Arduinos.

      这篇关于接收“未定义符号".有关plib I2C功能的XC8错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆