嘿,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++;
}
}
}