TCS3471光传感器库

时间:2019-03-08 09:32:27

标签: c++ c arduino i2c atmel

我正在尝试通过Arduino Mega的I2C总线与该光传感器进行通信。我在网上找到了这个I2C库(用C ++编写),但是我不知道如何将其翻译为C语言。 我在Atmel Studio 7.0中编程。 我的arduino内部的微控制器是atmega2560。 我已经创建了Bootloader,以便从atmel IDE加载程序。

代码如下:


TCS3471.C:


#include "TCS3471.h"

TCS3471::TCS3471(void (*i2cWriteFunc)(byte,byte,byte*),void (*i2cReadFunc)(byte,byte,byte*))
{
    _i2cWrite = i2cWriteFunc;
    _i2cRead = i2cReadFunc;
    _detected = false;
    _i2cAddress = 0;
}

bool TCS3471::detect()
{
    if (_detected)
        return true;
    else
    {
        _i2cAddress = TCS3471_ADDRESS_1;
        byte tmpaddr = read8(TCS3471_ID_REG);
        if (tmpaddr == 0x14 || tmpaddr == 0x1D)
            {
                _detected = true;
            }
        else
            {
                _i2cAddress = TCS3471_ADDRESS_2;
                tmpaddr = read8(TCS3471_ID_REG);
                if (tmpaddr == 0x14 || tmpaddr == 0x1D)
                    {
                        _detected = true;
                    }
                else
                    {
                        _i2cAddress = 0;
                    }
            }
    }
    return _detected;
}

bool TCS3471::enable()
{
    detect();
    if (_detected)
    {
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) | TCS3471_PON_BIT);
        delay(3);
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) | TCS3471_AEN_BIT);
        return true;
    }
    else
        return false;
}

void TCS3471::disable()
{
    if (_detected)
    {
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) & ~(TCS3471_PON_BIT | TCS3471_AEN_BIT));
    }
}

void TCS3471::setIntegrationTime(float integrationTime)
{
    if (_detected)
    {
        word aTime = (word)(integrationTime * 10);
        aTime = aTime / 24;
        if (aTime > 256)
            aTime = 256;
        aTime = aTime - 256;
        write8(TCS3471_ATIME_REG, (byte)aTime);
    }
}

void TCS3471::setWaitTime(float waitTime)
{
    if (_detected)
    {
        int32_t wTime = (int32_t)(waitTime * 10);
        if (wTime < 24)
        {
            write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) & ~TCS3471_WEN_BIT);
            return;
        }
        else if (wTime > 6144)
        {
            write8(TCS3471_CONFIG_REG, TCS3471_WLONG_BIT);
            if (wTime > 73728)
                wTime = 73728;
            wTime = wTime / 288;
        }
        else
        {
            write8(TCS3471_CONFIG_REG, 0x00);
            wTime = wTime / 24;
        }
        wTime = 256 - wTime;
        write8(TCS3471_WTIME_REG, (byte)wTime);
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) | TCS3471_WEN_BIT);
    }
}

void TCS3471::setGain(tcs3471Gain_t gain)
{
    if (_detected)
    {
        write8(TCS3471_CONTROL_REG, gain);
    }
}

void TCS3471::enableInterrupt()
{
    if (_detected)
    {
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) | TCS3471_AIEN_BIT);
    }
}

void TCS3471::disableInterrupt()
{
    if (_detected)
    {
        write8(TCS3471_ENABLE_REG, read8(TCS3471_ENABLE_REG) & ~TCS3471_AIEN_BIT);
    }
}

void TCS3471::clearInterrupt()
{
    if (_detected)
    {
        _i2cBuffer[0] = TCS3471_COMMAND_BIT | TCS3471_SPECIAL_BIT | TCS3471_INTCLEAR_BIT;
        _i2cWrite(_i2cAddress,1,_i2cBuffer);
    }
}

void TCS3471::interruptHighThreshold(word highThreshold)
{
    if (_detected)
    {
        write16(TCS3471_AIHTL_REG,highThreshold);
    }
}

void TCS3471::interruptLowThreshold(word lowThreshold)
{
    if (_detected)
    {
        write16(TCS3471_AILTL_REG,lowThreshold);
    }
}

void TCS3471::interruptPersistence(byte persistence)
{
    if (_detected)
    {
        byte valueToWrite = persistence;
        if (valueToWrite > 60)
            valueToWrite = 60;
        if (valueToWrite > 3)
            valueToWrite = valueToWrite / 5 + 3;
        write8(TCS3471_PERS_REG,valueToWrite & 0x0F);
    }
}

byte TCS3471::getChipID()
{
    detect();
    if (_detected)
    {
        return read8(TCS3471_ID_REG);
    }
    else
        return 0;
}

bool TCS3471::rgbcValid()
{
    if (_detected)
    {
        return (read8(TCS3471_STATUS_REG) & TCS3471_AVALID_BIT) == TCS3471_AVALID_BIT;
    }
    else
        return false;
}

word TCS3471::readCData()
{
    if (_detected)
    {
        return read16(TCS3471_CDATA_REG);
    }
    return 0;
}

word TCS3471::readRData()
{
    if (_detected)
    {
        return read16(TCS3471_RDATA_REG);
    }
    return 0;
}

word TCS3471::readGData()
{
    if (_detected)
    {
        return read16(TCS3471_GDATA_REG);
    }
    return 0;
}

word TCS3471::readBData()
{
    if (_detected)
    {
        return read16(TCS3471_BDATA_REG);
    }
    return 0;
}

void TCS3471::write8(byte reg, byte val)
{
    _i2cBuffer[0] = TCS3471_COMMAND_BIT | reg;
    _i2cBuffer[1] = val;
    _i2cWrite(_i2cAddress,2,_i2cBuffer);
}

void TCS3471::write16(byte reg, word val)
{
    _i2cBuffer[0] = TCS3471_COMMAND_BIT | TCS3471_AUTOINCR_BIT | reg;
    _i2cBuffer[1] = val & 0xFF;
    _i2cBuffer[2] = (val >> 8) & 0xFF;
    _i2cWrite(_i2cAddress,3,_i2cBuffer);
}

byte TCS3471::read8(byte reg)
{
    _i2cBuffer[0] = TCS3471_COMMAND_BIT | reg;
    _i2cWrite(_i2cAddress, 1, _i2cBuffer);
    _i2cRead(_i2cAddress, 1, _i2cBuffer);
    return _i2cBuffer[0];
}

word TCS3471::read16(byte reg)
{
    _i2cBuffer[0] = TCS3471_COMMAND_BIT | TCS3471_AUTOINCR_BIT | reg;
    _i2cWrite(_i2cAddress, 1, _i2cBuffer);
    _i2cRead(_i2cAddress, 2, _i2cBuffer);
    word ret = _i2cBuffer[1] << 8;
    ret |= _i2cBuffer[0];
    return ret;
}

TCS3471.H


#ifndef TCS3471_h
#define TCS3471_h

#if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
#else
    #include "WProgram.h"
#endif

// slave address
#define TCS3471_ADDRESS_1   0x29
#define TCS3471_ADDRESS_2   0x39

// registers
#define TCS3471_ENABLE_REG  0x00
#define TCS3471_ATIME_REG   0x01
#define TCS3471_WTIME_REG   0x03
#define TCS3471_AILTL_REG   0x04
#define TCS3471_AILTH_REG   0x05
#define TCS3471_AIHTL_REG   0x06
#define TCS3471_AIHTH_REG   0x07
#define TCS3471_PERS_REG    0x0C
#define TCS3471_CONFIG_REG  0x0D
#define TCS3471_CONTROL_REG 0x0F
#define TCS3471_ID_REG      0x12
#define TCS3471_STATUS_REG  0x13
#define TCS3471_CDATA_REG   0x14
#define TCS3471_CDATAH_REG  0x15
#define TCS3471_RDATA_REG   0x16
#define TCS3471_RDATAH_REG  0x17
#define TCS3471_GDATA_REG   0x18
#define TCS3471_GDATAH_REG  0x19
#define TCS3471_BDATA_REG   0x1A
#define TCS3471_BDATAH_REG  0x1B

// command register bits
#define TCS3471_COMMAND_BIT  0x80
#define TCS3471_AUTOINCR_BIT 0x20
#define TCS3471_SPECIAL_BIT  0x60
#define TCS3471_INTCLEAR_BIT 0x06

// enable register bits
#define TCS3471_AIEN_BIT     0x10
#define TCS3471_WEN_BIT      0x08
#define TCS3471_AEN_BIT      0x02
#define TCS3471_PON_BIT      0x01

// configuration register bits
#define TCS3471_WLONG_BIT    0x02

// control register bits
typedef enum
{
    TCS3471_GAIN_1X = 0x00,
    TCS3471_GAIN_4X = 0x01,
    TCS3471_GAIN_16X = 0x02,
    TCS3471_GAIN_60X = 0x03,
}
tcs3471Gain_t;

// ID register values
#define TCS3471_1_5_VALUE    0x14
#define TCS3471_3_7_VALUE    0x1D

// status register bits
#define TCS3471_AINT_BIT     0x10
#define TCS3471_AVALID_BIT   0x01

class TCS3471
{
public:
    TCS3471(void (*i2cWriteFunc)(byte,byte,byte*),void (*i2cReadFunc)(byte,byte,byte*));
    bool detect();
    bool enable();
    void disable();
    void setIntegrationTime(float integrationTime);
    void setWaitTime(float waitTime);
    void setGain(tcs3471Gain_t gain);
    void enableInterrupt();
    void disableInterrupt();
    void clearInterrupt();
    void interruptHighThreshold(word highThreshold);
    void interruptLowThreshold(word lowThreshold);
    void interruptPersistence(byte persistence);
    byte getChipID();
    bool rgbcValid();
    word readCData();
    word readRData();
    word readGData();
    word readBData();

    void write8(byte reg, byte val);
    void write16(byte reg, word val);
    byte read8(byte reg);
    word read16(byte reg);
private:
    byte _i2cBuffer[3];
    bool _detected;
    byte _i2cAddress;

    void (*_i2cWrite)(byte,byte,byte*);
    void (*_i2cRead)(byte,byte,byte*);
};

#endif

1 个答案:

答案 0 :(得分:0)

关于公开的代码,该库似乎并不太依赖C ++ OOP功能。恕我直言,大多数代码都可以轻松地转换为C。因此,我想展示适用于此目的的原则。

C ++示例类CPlusPlusThing

#include <iostream>

class CPlusPlusThing {
  private:
    int member1;
    int member2;
  public:
    CPlusPlusThing(int member1, int member2):
      member1(member1), member2(member2)
    { }

    void setMember1(int value) { member1 = value; }
    void setMember2(int value) { member2 = value; }

    void print();
};

void CPlusPlusThing::print()
{
  std::cout
    << "CPlusPlusThing {\n"
    << "  member1: " << member1 << '\n'
    << "  member2: " << member2 << '\n'
    << "}\n";
}

和一个简短的应用示例:

int main()
{
  { CPlusPlusThing thing(123, 0);
    thing.setMember2(321);
    thing.print();
  }
  { CPlusPlusThing *pThing = new CPlusPlusThing(234, 0);
    pThing->setMember2(432);
    pThing->print();
    delete pThing;
  }
  return 0;
}

经过编译和测试:

CPlusPlusThing {
  member1: 123
  member2: 321
}
CPlusPlusThing {
  member1: 234
  member2: 432
}

Live Demo on coliru

将其音译为C时,必须考虑以下几点:

  1. C中没有构造函数/析构函数。→如果构造函数仅初始化成员,则也可以执行简单的初始化。否则,应提供一个初始化函数。

  2. C中没有成员函数。→撇开virtual函数,成员函数不过是带有隐式this参数的函数。因此,this参数使用成员函数调用中.->的左操作数的表达式进行初始化。在C中,分别。指针只是第一个参数。在适当的情况下,this隐式地应用于成员函数内部,这在C语言中是不可能的。它必须显式地完成。

  3. 在C ++中,不同的类可能会提供具有相同名称的成员函数。成员函数调用将根据.->的左操作数的类型选择右一个。 C中没有机会。不同的函数必须具有不同的名称。通常的解决方法是将类名称包含在C API的函数名称中。

因此,这就是上面的示例在C语言中的样子:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int member1;
  int member2;
} CThing;

CThing* newCThing(int member1, int member2)
{
  CThing *pThis = malloc(sizeof (CThing));
  if (pThis) {
    pThis->member1 = member1;
    pThis->member2 = member2;
  }
  return pThis;
}

void deleteCThing(CThing *pThis)
{
  free(pThis);
}

void setCThingMember1(CThing *pThis, int member1)
{
  pThis->member1 = member1;
}

void setCThingMember2(CThing *pThis, int member2)
{
  pThis->member2 = member2;
}

void printCThing(CThing *pThis)
{
  printf(
    "CThing {\n"
    "  member1: %d\n"
    "  member2: %d\n"
    "}\n",
    pThis->member1, pThis->member2);
}

以及相应的应用示例:

int main()
{
  { CThing thing = { 123, 0 };
    setCThingMember2(&thing, 321);
    printCThing(&thing);
  }
  { CThing *pThing = newCThing(234, 0);
    setCThingMember2(pThing, 432);
    printCThing(pThing);
    deleteCThing(pThing);
  }
  return 0;
}

经过编译和测试:

CThing {
  member1: 123
  member2: 321
}
CThing {
  member1: 234
  member2: 432
}

Live Demon on coliru