忍者ブログ

Azukish

消えゆく世界と流れる未来に最後の灯を since 2006/4/3

2024/04/30

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

コメント

ただいまコメントを受けつけておりません。

2019/08/03

MSP-EXP430FR2433でHDC2080と通信して温湿度を取ってみる。

I2C通信の練習がてらMSP-EXP430FR2433でHDC2080と通信して温湿度データを取ってみた。
このデータをどうするかはまあ置いておくことにして、ソースコードも備忘録的に貼っておくので、参考にしたい人は参考にしてください。




参考資料としては、
NXP UM10204: I2Cバス仕様およびユーザーマニュアル
http://www.ti.com/jp/lit/ds/symlink/hdc2080.pdf
あたりですかね。
特に上のNXPのユーザーマニュアルの図9とかはどんな通信をしているか非常にわかりやすく描いてあると思われる。

#include <msp430.h> 

volatile unsigned char RXData[0x10];  // RX Data array
volatile unsigned char TXData[10];  // TX Data array
volatile unsigned char RXByteCnt=0; // RX number
volatile signed char TXByteCnt=9; // TX Counter
volatile unsigned char read=0;

int main(void) {
  WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

  P1SEL0 |= BIT2 | BIT3;      // I2C pins
  P1OUT &= ~(BIT0 | BIT1);    // Communication Indicator
  P1DIR |= BIT0 | BIT1;
  P2IE  |= BIT0;
  P2IES &= ~BIT0;
  PM5CTL0 &= ~LOCKLPM5;
  P2IFG &= ~BIT0;

  // Configure USCI_B0 for I2C mode
  UCB0CTLW0 |= UCSWRST;             // put eUSCI_B in reset state
  UCB0CTLW0 |= UCMODE_3 | UCMST;    // I2C master mode, SMCLK
  UCB0CTLW1 |= UCASTP_2;            // Automatic stop generated
  UCB0BRW   = 0x8;                 // baudrate = SMCLK(1MHz) / 16
  UCB0I2CSA = 0x40;                 // Slave address = 0x40 = 1000000b (ADDR=GND or open)
  UCB0CTLW0 &= ~UCSWRST;            // clear reset register

  UCB0IE    |= UCTXIE0 | UCNACKIE;  // transmit and NACK interrupt enable
  TXData[9] = 0x07;    // Address
  TXData[8] = BIT7;    // 0x07: Interruption Setting = DRDY_ENABLE
  TXData[7] = 0;       // 0x08: Temperature Offset Adjustment = none
  TXData[6] = 0;       // 0x09: Humidity Offset Adjustment = none
  TXData[5] = 0;       // 0x0a: Temperature Threshold LOW = none
  TXData[4] = 0xff;    // 0x0b: Temperature Threshold HIGH = none
  TXData[3] = 0;       // 0x0c: Humidity Threshold LOW = none
  TXData[2] = 0xff;    // 0x0d: Humidity Threshold HIGH = none
  TXData[1] = BIT1 | BIT2 | BIT4 | BIT6; // 0x0e: DRDY/INT = Active High, DRDY Enable, 1Hz Auto measurement
  TXData[0] = BIT0; // 0x0f: Measurement start
  __delay_cycles(200);
  while (UCB0CTLW0 & UCTXSTP);
  UCB0CTLW0 |= UCTR | UCTXSTT;    // transmit START condition
  __bis_SR_register(LPM0_bits | GIE);
}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void) {
  switch (__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) {
    // NACK
    case USCI_I2C_UCNACKIFG:
      UCB0CTL1 |= UCTXSTT;  //resend start if NACK
      break;

    // TX Interruption
    case USCI_I2C_UCTXIFG0:
      if (TXByteCnt+1) {      // Write multiple bytes until TXByteCnt=0
        P1OUT |= BIT0;
        UCB0TXBUF = TXData[TXByteCnt];
        TXByteCnt--;
      } else {
        if (read) { // Read data
          UCB0IE |= UCRXIE | UCBCNTIE;
          UCB0IE &= ~UCTXIE0;
          UCB0CTLW0 &= ~UCTR;
          __delay_cycles(20);
          while (UCB0CTLW0 & UCTXSTP);
          UCB0CTLW0 |= UCTXSTT;
        } else {   // Write data finishes
          while (UCB0CTLW0 & UCTXSTP);
          UCB0CTLW0 |= UCTXSTP;    // transmit STOP condition
        }
        P1OUT &= ~BIT0;
      }
      UCB0IFG &= ~UCTXIFG;
      break;

    // RX Interruption
    case USCI_I2C_UCRXIFG0:
      RXData[RXByteCnt] = UCB0RXBUF;
      RXByteCnt++;
      break;

    // RX Counter reached
    case USCI_I2C_UCBCNTIFG:
      P1OUT &= ~BIT1;
      break;
    default:
      break;
  }
}

#pragma vector=PORT2_VECTOR
__interrupt void Port2_ISR(void) {
  P1OUT |= BIT1;
  P2IFG &= ~BIT0;
  RXByteCnt = 0;
  TXByteCnt = 0;
  UCB0TBCNT = 0x04;                 // Counter for multiple-byte read
  read = 1;
  TXData[0] = 0x00; // address
  UCB0IE |= UCTXIE0;
  __delay_cycles(20);
  while (UCB0CTLW0 & UCTXSTP);
  UCB0CTLW0 |= UCTR | UCTXSTT;    // transmit START condition
}


プログラムの内容をメモ程度に下に書いておく。プログラム内のコメントも参照されたし。

TXData[0-9]で予めHDC2080の設定項目を入れておく(29-38行目)。
TXData[0-9]の内容としては、0番はレジスタアドレスで、1-8は0x00 (TEMPERATURE LOW)から0x07 (INTERRUPT ENABLE)レジスタまでの設定を格納してある。
41行目でスタートコンディションを投げるとともに通信開始。
スタートコンディションとアドレス(7bit=0x40)、リードライトビット(R/W=0)がMSP430側からHDC2080へ投げられる。
次に、アドレスが合っていれば、HDC2080→MSP430の向きで1bitのアクノリッジビット(ACK=H)が投げられる。これは続けてデータを受け入れる準備がHDC2080にできていることを示している。
このACKによってI2Cの割り込み処理が起き、8bitずつデータ(TXData[0-9])をMSP430→HDC2080の向きで送る。(54-58行目)
8ビットのデータが送られるたびにHDC2080はACKを出すので、MSP430には割り込み処理が発生する。
以上のようにして、TXData[0-9]のデータをすべて送り終えたら、今度は読み込みに入るので、通信の終了を示すノット・アクノリッジ(NACK)とストップコンディションを続けて送る。(60行目)
HDC2080にはオート測定の設定を送っているため、データが準備でき次第INTピンによってMSP430のP2.0に通知を出す。これによって、GPIOの割り込みが発生する。(91行目)
MSP430は再びI2C通信を開始し、レジスタアドレス(0x00 TEMPERATURE LOW)を送付する。(103行目)
ACKビットで割り込みが発生し、変数readが経っているため、読み込み作業に移行する。(60行目) ここでは、今度はR/W=1にして再度スタートコンディションを投げる。
R/W=1になっている場合、8bitデータ(HDC2080が送る)→ACK(MSP430が送る)→8bitデータ(HDC2080)→ACK(MSP430)...というやり取りが行われる。この間も、8bitのデータを受信するたびに76-80行目の割り込み処理が起きる。
割り込み処理では、レジスタアドレス0x00 (TEMPERATURE LOW)から0x03 (HUMIDITY HIGH)までのうち8bit分のデータが順番にそれぞれRXData[0-3]に格納されていく。
UCB0TBCNT=0x04の設定があるので、上記32ビット分(8bit x 4octet)のデータ通信が終わった時点で83行目の割り込み処理が起き、同時にMSP430→HDC2080の向きで通信の終了を示すNACK+ストップコンディションが送られる。

最後まで処理が終わると次のGPIO割り込みが起きるまで待つ、というのが処理の内容です。
以上、割と疲れましたでござる。

拍手

コメント













カレンダー

03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

アーカイブ

AD

Azkishはamazon.co.jpを宣伝しリンクすることによって サイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。