lbed

2013/07/15からのアクセス回数 4542

温度センサーLM73とつなぐ

LCDでLCDに表示することができたので、 次は温度センサーとつないでみます。 ここで使う温度センサーは、I2Cという通信インタフェースを使用します。 I2Cインタフェースでは、SDA, SCLにプルアップ抵抗が必要なので、手元にあった 4.7KΩの抵抗を使ってプルアップしています。

LM73.png

I2Cがp27, p28を使用するので、LCDの接続以下に変更します。 MyARM: StartBoard

LM73*1とMyARMの接続は、

LM73_setting.png

テストプログラム

テスト用のプログラムは、以下の通りです。 1秒ごとに温度をLM73から読み取り表示します。

#include<cr_section_macros.h>
#include<NXP/crp.h>
__CRP extern const unsigned int CRP_WORD = CRP_NO_CRP;

#include"lbed.h"
#include "TextLCD.h"
#include "LM73.h"

int main(void) {
     wait_init();
     DigitalOut myled(LED2);
     TextLCD lcd(p8, p25, p24, p26, p29, p30); // rs, e, d4-7
     LM73 lm73(p28, p27);
     lcd.print("Hello World");

     while (1) {
          float t = lm73.read();
          lcd.locate(0, 1);
          lcd.print("Temp:");
          lcd.print(t);
          myled = !myled;
          wait_ms(1000);
     }
     return 0;
}

LM73クラスについて

LM73クラスは、LM73チップ用に私が作成したユーザライブラリです。

raspberrypi/Raspberry PiでIO制御でも説明していますが、コンストラクターで

後は、readメソッドで2バイト読み込み、バイトスワップを行った後、14bitを取り出し、 補正係数を掛けて温度を計算するだけです。

#include "lbed.h"
#include "LM73.h"

LM73::LM73(PinName sda, PinName scl) : i2c(sda, scl)
{
     char cmd[2];
     // LM73設定
     cmd[0]    = 0x04;     // register 4
     cmd[1]    = 0x60;        // 14bit resolution
     i2c.write( LM73_ADDR, cmd, 2);
     // ポインタを0にしておく(readするだけで温度が読めるようになる)
     cmd[0]    = 0x00;
     i2c.write( LM73_ADDR, cmd, 1);
}

LM73::~LM73()
{
}

float LM73::read()
{
     char cmd[2];

     i2c.read( LM73_ADDR, cmd, 2); // Send command string   
     int int_val = cmd[0] <<1 | cmd[1]>>7;
     int ceil_val = ((cmd[1] & 0x7f)*200) >>8;
     return float(int_val + ceil_val/100.0);
}

I2Cのクラスについて

I2Cのクラスは、LPC11xx-LPCXpresso-CMSIS-updateのサンプルプログラムを使用しています。

問題は、I2Cが割り込み関数を使っているのですが、C++のメソッドを割り込み関数にできないため、 Cで書かれた割り込み関数を使用しなければなりません。

今回は、i2c.hを_i2c.hに名前を変え*2 ヘッダファイルの先頭に

#ifdef __cplusplus
extern"C" {
#endif

終わりに

#ifdef __cplusplus
}
#endif

を付けて、C++からI2C用の共通関数を使えるように修正します。

このようにサンプルプログラムの共通関数を活用することで、I2Cは以下の様に簡単に記述することができました。

#include "platform.h"
#include "PinNames.h"
#include "I2C.h"

#include "LPC11xx.h"               /* LPC11xx Peripheral Registers */
#include "type.h"
#include "_i2c.h"

extern volatile uint32_t I2CCount;
extern volatile uint8_t I2CMasterBuffer[BUFSIZE];
extern volatile uint8_t I2CSlaveBuffer[BUFSIZE];

extern volatile uint32_t I2CMasterState;
extern volatile uint32_t I2CReadLength, I2CWriteLength;

I2C::I2C(PinName sda, PinName scl, const char *name) {
     _name = (char *) name;
     if (I2CInit((uint32_t) I2CMASTER) == FALSE) /* initialize I2c */
     {
          while (1)
               ; /* Fatal error */
     }
}

int I2C::read(int address, char *data, int length, bool repeated) {
    for (int i = 0; i < length; i++)
         I2CSlaveBuffer[i] = 0x00;
    I2CWriteLength = 2;
    I2CReadLength = length;
    getI2CMasterBuffer()[0] = address;
    getI2CMasterBuffer()[1] = 0x00;          /* address */
    getI2CMasterBuffer()[2] = address | RD_BIT;
    I2CEngine();
    for (int i = 0; i < length; i++)
         data[i] = getI2CSlaveBuffer()[i];
    return length;
}

int I2C::read(int ack) {
    I2CReadLength = 1;
    I2CEngine();
     return getI2CSlaveBuffer()[0];
}

int I2C::write(int address, const char *data, int length, bool repeated) {
    I2CWriteLength = length+1;
    I2CReadLength = 0;
    getI2CMasterBuffer()[0] = address;
    for (int i = 0; i < length; i++)
         getI2CMasterBuffer()[i+1] = data[i];
    I2CEngine();
    return 1;
}

int I2C::write(int ack) {
    I2CWriteLength = 2;
    I2CReadLength = 0;
    getI2CMasterBuffer()[1] = ack;
    I2CEngine();
    return 1;
}

コメント

選択肢 投票
おもしろかった 0  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。


(Input image string)

*1 △の付いたところが1番で反時計回りに番号が振られている
*2 MacOSXでは大文字時を区別しないので、I2Cとの区別のため

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc