3

こんにちは、StackOverflow!

私の質問は、下に(はるかに)貼り付けられたプログラム内で報告されているエラーに関するものです。ターゲット デバイスはPIC12LF1552で、シリアル ペリフェラルが 1 つ搭載されており、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++;
        }
    }
}
4

2 に答える 2

0
  • MC plib コードを出発点として使用して、i2c lib コードを書き直すアプローチを取ることを検討してください。変換を行うよりも高速な場合があります。また、CCS のような別のコンパイラを検討してください - それらはより堅牢で十分に文書化されたライブラリを持っている可能性があります (ここで誰かがこれを試しましたか?)

    ええ、MCのドキュメントは時々陰気です。なぜ10億ドルの会社なのかわからない。これ以上のことはできません。すべての関数とマクロが文書化されているわけではなく、i2c eeprom コードの例のように、例が現実的でない場合もあります。

    コードがブロッキング IO 呼び出しを使用し、バスの問題から回復しないという点で、このライブラリにも問題があります。例: i2c デバイスで PCB をテストするテスト ギアを作成しています。ただし、plib 操作中に接続が中断されると、plib コードは PIC18 i2c ポートにアクセスできなくなります。これは、テスト ギアには受け入れられません。

于 2014-10-05T16:52:17.953 に答える