【发布时间】:2014-08-10 00:56:30
【问题描述】:
嘿,StackOverflow!
我的问题涉及在下面粘贴(远)的程序中报告的错误。目标设备是PIC12LF1552,它上面有一个串行外设,我认为可以与Microchip XC8 编译器提供的库一起使用。互联网上的一些消息来源说只有 PIC18 系列中的高端设备才能支持库函数,其他消息来源说库函数工作得很好。所以我决定我不想从头开始重写 I2C 函数,也不想为这个项目编写任何数量的程序集。因此,我决定使用 XC8 附带的提供的外设库。我阅读了编译器文档以了解如何获取它们(如下面的i2c.h 所示)。我知道根据文档和我见过的一些示例,需要对这些命令进行一些错误检查,但目前我假设主机和从机都会表现得很好,这样我就可以把这件事弄下来地面。
我已经包含了所有相关的路径,这就是为什么我认为它在编译过程中会走到这一步。对于 C 语言和编译器的内部工作,我的知识水平非常有限,我只知道如何在基本水平上使用这些工具,所以这里可能缺少一些基本的东西。
无论如何,当我在 MPLABX v1.95 中编译这段代码时,我得到了这个:
: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 编译器移植时遇到了非常类似的问题,但我已经做了那个人所做的一切来解决他的问题)。
所以我想,问题是,为什么会出现此编译器错误,以及导致此错误的 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++;
}
}
}
【问题讨论】:
-
你是在
#includ的标题中加上AckI2C之类的吗? -
库函数在
#include <plib/i2c.h>中定义,它包含在我的i2c.h文件中(我知道命名约定不好,但在编译时并不违法,我不认为)。我的i2c.h文件包含在我的main.c文件中。我的i2c.c文件是我的i2c.h文件结束位置和main.c开始之前之间的代码块... -
#ifndef I2C_H #define I2C_H行是为了强制不包含两次i2c.h。问题可能是您的文件i2c.h以`#ifndef I2C_H #define I2C_H` 开头,然后是#include <plib\i2c.h>。如果plib\i2c.h以 `#ifndef I2C_H #define I2C_H, nothing will be included ! You may try to rename youri2c.h` 开头为myi2c.h并将`#ifndef I2C_H #define I2C_H` 更改为`#ifndef MEI2C_H #define MYI2C_H` -
并且需要在
i2c.h中选择I2C的版本。在#include <plib\i2c.h>之前添加类似#define I2C_V6的内容,这可能会解决您的问题。更有可能是之前的评论。 -
好的!我们正在取得一些进展,我已经按照@francis 的建议完成了工作,并将我自己的 i2c 文件和#ifndef 块和
#define I2C_V1重命名为#include <plib/i2c.h>。所以我仍然收到未定义符号错误,但其中一些符号已从列表中删除。值得注意的是,不再抱怨仅定义包装寄存器设置的“功能”。然而,在 plib/i2c.h 中存在原型的实际函数是现在被抱怨的函数。我不知道从这里去哪里......