📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の1版が非表示)
405行目: 405行目:
<br>
<br>
==== MSP430F149のI2C設定 ====
==== MSP430F149のI2C設定 ====
MSP430F149でI2C通信を正常に動作させるためには、以下の設定を適切に行う必要がある。<br>
MSP430F149でI2C通信を正常に動作させるためには、以下の設定を行う必要がある。<br>
<br>
<br>
クロック設定の重要性について説明する。MSP430F149では、複数のクロックソースが利用可能である。ACLK (Auxiliary Clock) は通常32.768kHzの低速クロックで、低電力動作に使用される。MCLK (Master Clock) はCPUのメインクロックで、通常1MHzから8MHz程度で動作する。SMCLK (Sub-Main Clock) はペリフェラル用のクロックで、I2C通信ではこのSMCLKを使用することが一般的である。<br>
* クロック設定
<br>
*: MSP430F149では、複数のクロックソースが利用可能である。
USARTモジュールをI2Cモードで使用するには、まずU0CTLレジスタ (USART0の場合) のSWRSTビットをセットして、モジュールをリセット状態にする。次に、I2Cモードを有効にし、マスターまたはスレーブモードを選択する。MSP430F149がI2Cマスターとして動作する場合は、I2CENビットとMSTビットをセットする。<br>
*: ACLK (Auxiliary Clock) は、32.768[kHz]の低速クロックで、低電力動作に使用される。
<br>
*" MCLK (Master Clock) は、CPUのメインクロックで、1[MHz]〜8[MHz]で動作する。
クロック分周の設定では、U0BRレジスタを使用してI2Cのクロック周波数を設定する。例えば、SMCLKが1MHzで動作している場合、100kHzのI2C通信を実現するには、分周比を10に設定する必要がある。<br>
*: SMCLK (Sub-Main Clock) は、ペリフェラル用のクロックで、I2C通信ではこのSMCLKを使用することが一般的である。
<br>
*: <br>
I2Cアドレッシングについて、MSP430F149は7ビットアドレスと10ビットアドレスの両方をサポートしているが、SC2004のような一般的なI2Cデバイスは7ビットアドレスを使用する。スレーブデバイスのアドレスは、I2CSAレジスタに設定する。<br>
* USARTモジュールをI2Cモードで使用
<br>
*# まず、U0CTLレジスタ (USART0の場合) のSWRSTビットをセットして、モジュールをリセット状態にする。
割り込みを使用する場合は、I2CIEレジスタで適切な割り込みを有効にし、割り込みサービスルーチン (ISR) を実装する必要がある。I2C通信では、送信完了割り込み、受信完了割り込み、NACK受信割り込みなどが利用できる。<br>
*# 次に、I2Cモードを有効にして、マスターまたはスレーブモードを選択する。<br>MSP430F149がI2Cマスターとして動作する場合は、I2CENビットとMSTビットをセットする。
<br>
*: <br>
エラー処理も重要な要素である。I2C通信中にエラーが発生した場合、I2CSTATレジスタのエラーフラグを確認して、適切にエラー処理を行う。アービトレーション損失 (Arbitration Lost) 、NACK受信 (No Acknowledge) 、バスビジー (Bus Busy) などのエラー状態を検出できる。<br>
* クロック分周の設定
<br>
*: U0BRレジスタを使用してI2Cのクロック周波数を設定する。
低電力モードとの連携については、MSP430F149は複数の低電力モード (LPM0〜LPM4) をサポートしている。I2C通信を使用する場合、通信中はアクティブモードまたはLPM0で動作し、通信が完了したら低電力モードに移行することでバッテリ駆動時間を延ばすことができる。<br>
*: 例えば、SMCLKが1[MHz]で動作している場合、100[kHz]のI2C通信を実現するには、分周比を10に設定する必要がある。
*: <br>
* I2Cアドレッシング
*: MSP430F149は7ビットアドレスと10ビットアドレスの両方をサポートしているが、SC2004のような一般的なI2Cデバイスは7ビットアドレスを使用する。
*: スレーブデバイスのアドレスは、I2CSAレジスタに設定する。
*: <br>
* 割り込みの使用
*: I2CIEレジスタで適切な割り込みを有効にして、割り込みサービスルーチン (ISR) を使用する必要がある。
*: I2C通信では、送信完了割り込み、受信完了割り込み、NACK受信割り込み等が利用できる。
*: <br>
* エラーハンドリング
*: I2C通信中にエラーが発生した場合、I2CSTATレジスタのエラーフラグを確認して、適切にエラー処理を行う。
*: アービトレーション損失 (Arbitration Lost)、NACK受信 (No Acknowledge)、バスビジー (Bus Busy)等のエラー状態を検出できる。
*: <br>
* 低電力モードとの連携
*: MSP430F149は複数の低電力モード (LPM0〜LPM4) をサポートしている。
*: I2C通信を使用する場合、通信中はアクティブモードまたはLPM0で動作して、通信が完了したら低電力モードに移行することでバッテリ駆動時間を延ばすことができる。
<br>
<br>
==== SC2004の設定 ====
==== SC2004の設定 ====
SC2004は、I2Cスレーブデバイスとして動作する。I2C-LCD変換モジュール (一般的に、PCF8574またはPCF8574Aチップを使用) を介してHD44780互換のLCDコントローラと通信を行う。<br>
SC2004は、I2Cスレーブデバイスとして動作する。I2C-LCD変換モジュール (一般的に、PCF8574またはPCF8574Aチップを使用) を介してHD44780互換のLCDコントローラと通信を行う。<br>
560行目: 577行目:
  #define LCD_D7    0x80  // ビット7: データビット7
  #define LCD_D7    0x80  // ビット7: データビット7
   
   
  // 遅延マクロ (1MHz動作時)  
  // 遅延マクロ (1[MHz]動作時)
  #define DELAY_MS(x) __delay_cycles((x) * 1000)
  #define DELAY_MS(x) __delay_cycles((x) * 1000)
  #define DELAY_US(x) __delay_cycles((x))
  #define DELAY_US(x) __delay_cycles((x))
   
   
  // グローバル変数
  // グローバル変数
  uint8_t lcd_backlight = LCD_BL;  // バックライト状態 (デフォルトON)  
  uint8_t lcd_backlight = LCD_BL;  // バックライト状態 (デフォルトON)
   
   
  // 関数プロトタイプ宣言
  // 関数プロトタイプ宣言
587行目: 604行目:
     // ウォッチドッグタイマを停止
     // ウォッチドッグタイマを停止
     WDTCTL = WDTPW | WDTHOLD;
     WDTCTL = WDTPW | WDTHOLD;
   
     // システムクロックの設定
     // システムクロックの設定
     // DCOを約1MHzに設定 (MSP430F149のキャリブレーション値を使用)  
     // DCOを約1[MHz]に設定 (MSP430F149のキャリブレーション値を使用)
     BCSCTL1 = CALBC1_1MHZ;
     BCSCTL1 = CALBC1_1MHZ;
     DCOCTL = CALDCO_1MHZ;
     DCOCTL = CALDCO_1MHZ;
   
     // SMCLKの設定 (ペリフェラル用クロック)  
     // SMCLKの設定 (ペリフェラル用クロック)
     BCSCTL2 &= ~(DIVS_3);  // SMCLK分周なし (1MHz)  
     BCSCTL2 &= ~(DIVS_3);  // SMCLK分周なし (1[MHz])
   
     // I2Cの初期化
     // I2Cの初期化
     i2c_init();
     i2c_init();
   
     // LCDの初期化
     // LCDの初期化
     lcd_init();
     lcd_init();
   
     // テキストの表示
     // テキストの表示
     lcd_clear();
     lcd_clear();
     lcd_set_cursor(0, 0);
     lcd_set_cursor(0, 0);
     lcd_print("MSP430F149");
     lcd_print("MSP430F149");
   
     lcd_set_cursor(1, 0);
     lcd_set_cursor(1, 0);
     lcd_print("I2C LCD Demo");
     lcd_print("I2C LCD Demo");
   
     lcd_set_cursor(2, 0);
     lcd_set_cursor(2, 0);
     lcd_print("USART0 Mode");
     lcd_print("USART0 Mode");
   
     lcd_set_cursor(3, 0);
     lcd_set_cursor(3, 0);
     lcd_print("20x4 Display");
     lcd_print("20x4 Display");
   
     // メインループ
     // メインループ
     while(1) {
     while(1) {
        // 低電力モードに入る (割り込みで復帰)  
      // 低電力モードに入る (割り込みで復帰)
        __bis_SR_register(LPM0_bits + GIE);
      __bis_SR_register(LPM0_bits + GIE);
        __no_operation();
      __no_operation();
     }
     }
  }
  }
631行目: 648行目:
  {
  {
     // ポート3の機能選択レジスタを設定
     // ポート3の機能選択レジスタを設定
     // P3.1: SDA (USART0 STE/SIMO)  
     // P3.1: SDA (USART0 STE/SIMO)
     // P3.3: SCL (USART0 SCLK)  
     // P3.3: SCL (USART0 SCLK)
     P3SEL |= BIT1 | BIT3;
     P3SEL |= BIT1 | BIT3;
   
     // USART0制御レジスタの設定
     // USART0制御レジスタの設定
     // SWRSTビットをセットしてUSARTをリセット状態にする
     // SWRSTビットをセットしてUSARTをリセット状態にする
     U0CTL = SWRST;
     U0CTL = SWRST;
   
     // I2Cモードの設定
     // I2Cモードの設定
     // I2C = I2Cモード有効
     // I2C = I2Cモード有効
644行目: 661行目:
     // MST = マスターモード
     // MST = マスターモード
     U0CTL |= I2C | SYNC;
     U0CTL |= I2C | SYNC;
   
     // I2C制御レジスタの設定
     // I2C制御レジスタの設定
     // I2CRM = リピートモード無効
     // I2CRM = リピートモード無効
     // I2CSSEL1 = SMCLK選択 (ビット1)  
     // I2CSSEL1 = SMCLK選択 (ビット1)
     I2CTCTL = I2CSSEL1;
     I2CTCTL = I2CSSEL1;
   
     // I2C自身アドレス設定 (マスターモードでは使用しないが設定は必要)  
     // I2C自身アドレス設定 (マスターモードでは使用しないが設定は必要)
     I2COA = 0x01;
     I2COA = 0x01;
   
     // I2Cスレーブアドレス設定
     // I2Cスレーブアドレス設定
     I2CSA = LCD_ADDR;
     I2CSA = LCD_ADDR;
   
     // I2Cクロック分周器の設定
     // I2Cクロック分周器の設定
     // SMCLKが1MHzの場合、I2Cクロックを100kHzに設定
     // SMCLKが1[MHz]の場合、I2Cクロックを100[kHz]に設定
     // 分周比 = 1MHz / 100kHz = 10
     // 分周比 = 1[MHz] / 100[kHz] = 10
     I2CPSC = 0;      // プリスケーラなし
     I2CPSC = 0;      // プリスケーラなし
     I2CSCLH = 5;    // SCL High時間
     I2CSCLH = 5;    // SCL High時間
     I2CSCLL = 5;    // SCL Low時間
     I2CSCLL = 5;    // SCL Low時間
   
     // USARTをリセット状態から解除
     // USARTをリセット状態から解除
     U0CTL &= ~SWRST;
     U0CTL &= ~SWRST;
   
     // I2C割り込みを有効化 (必要に応じて)  
     // I2C割り込みを有効化 (必要に応じて)
     // I2CIE |= TXRDYIE | RXRDYIE | NACKIE;
     // I2CIE |= TXRDYIE | RXRDYIE | NACKIE;
  }
  }
677行目: 694行目:
     // マスターモードを確認
     // マスターモードを確認
     U0CTL |= MST;
     U0CTL |= MST;
   
     // スタートコンディションを生成
     // スタートコンディションを生成
     // STTビットをセットするとハードウェアがスタートコンディションを生成
     // STTビットをセットするとハードウェアがスタートコンディションを生成
     I2CTCTL |= I2CSTT;
     I2CTCTL |= I2CSTT;
   
     // スタートコンディション生成完了を待機
     // スタートコンディション生成完了を待機
     // STTビットは自動的にクリアされる
     // STTビットは自動的にクリアされる
     while(I2CTCTL & I2CSTT);
     while(I2CTCTL & I2CSTT);
   
     // スレーブアドレスと書き込みビット (0) を送信
     // スレーブアドレスと書き込みビット (0) を送信
     I2CDRB = (LCD_ADDR << 1) | 0;  // 書き込みモード
     I2CDRB = (LCD_ADDR << 1) | 0;  // 書き込みモード
   
     // 送信準備完了を待機
     // 送信準備完了を待機
     while((I2CIFG & TXRDYIFG) == 0);
     while((I2CIFG & TXRDYIFG) == 0);
701行目: 718行目:
     // STPビットをセットするとハードウェアがストップコンディションを生成
     // STPビットをセットするとハードウェアがストップコンディションを生成
     I2CTCTL |= I2CSTP;
     I2CTCTL |= I2CSTP;
   
     // ストップコンディション生成完了を待機
     // ストップコンディション生成完了を待機
     // STPビットは自動的にクリアされる
     // STPビットは自動的にクリアされる
     while(I2CTCTL & I2CSTP);
     while(I2CTCTL & I2CSTP);
   
     // 短い遅延を入れてバスを安定させる
     // 短い遅延を入れてバスを安定させる
     DELAY_US(10);
     DELAY_US(10);
718行目: 735行目:
     // データをI2Cデータレジスタに書き込む
     // データをI2Cデータレジスタに書き込む
     I2CDRB = data;
     I2CDRB = data;
   
     // 送信完了を待機
     // 送信完了を待機
     // TXRDYIFGフラグが立つまで待つ
     // TXRDYIFGフラグが立つまで待つ
     while((I2CIFG & TXRDYIFG) == 0);
     while((I2CIFG & TXRDYIFG) == 0);
   
     // NACKを受信していないか確認
     // NACKを受信していないか確認
     if(I2CIFG & NACKIE) {
     if(I2CIFG & NACKIE) {
        // NACK受信時の処理
      // NACK受信時の処理
        I2CIFG &= ~NACKIE;  // フラグをクリア
      I2CIFG &= ~NACKIE;  // フラグをクリア
        // エラーハンドリング (必要に応じて実装)  
      // エラーハンドリング (必要に応じて実装)
      // ...略
     }
     }
  }
  }
738行目: 757行目:
  {
  {
     // 電源投入後の安定化待ち
     // 電源投入後の安定化待ち
     // LCDコントローラの電源が安定するまで最低15ms必要
     // LCDコントローラの電源が安定するまで最低15[ms]必要
     DELAY_MS(50);
     DELAY_MS(50);
   
     // 初期化シーケンスの開始
     // 初期化シーケンスの開始
     // I2C-LCDモジュールを4ビットモードで初期化
     // I2C-LCDモジュールを4ビットモードで初期化
   
     // 最初の初期化コマンド (8ビットモード)  
     // 最初の初期化コマンド (8ビットモード)
     // これはLCDを既知の状態にリセットするための手順
     // これはLCDを既知の状態にリセットするための手順
     lcd_write_nibble(0x03, 0);
     lcd_write_nibble(0x03, 0);
     DELAY_MS(5);
     DELAY_MS(5);
   
     // 2回目の初期化コマンド
     // 2回目の初期化コマンド
     lcd_write_nibble(0x03, 0);
     lcd_write_nibble(0x03, 0);
     DELAY_US(150);
     DELAY_US(150);
   
     // 3回目の初期化コマンド
     // 3回目の初期化コマンド
     lcd_write_nibble(0x03, 0);
     lcd_write_nibble(0x03, 0);
     DELAY_US(150);
     DELAY_US(150);
   
     // 4ビットモードに切り替え
     // 4ビットモードに切り替え
     lcd_write_nibble(0x02, 0);
     lcd_write_nibble(0x02, 0);
     DELAY_US(150);
     DELAY_US(150);
   
     // 以降、通常のコマンド送信関数を使用
     // 以降、通常のコマンド送信関数を使用
   
     // Function Set: 4ビットモード、2行表示、5x8ドット
     // Function Set: 4ビットモード、2行表示、5x8ドット
     lcd_cmd(0x28);
     lcd_cmd(0x28);
   
     // Display Control: ディスプレイON、カーソルOFF、点滅OFF
     // Display Control: ディスプレイON、カーソルOFF、点滅OFF
     lcd_cmd(0x0C);
     lcd_cmd(0x0C);
   
     // Entry Mode Set: カーソル自動右移動、表示シフトなし
     // Entry Mode Set: カーソル自動右移動、表示シフトなし
     lcd_cmd(0x06);
     lcd_cmd(0x06);
   
     // Clear Display: 画面クリア
     // Clear Display: 画面クリア
     lcd_clear();
     lcd_clear();
778行目: 797行目:
  /**
  /**
   * LCD 4ビット書き込み関数
   * LCD 4ビット書き込み関数
   * @param nibble 送信する4ビットデータ (下位4ビットを使用)  
   * @param nibble 送信する4ビットデータ (下位4ビットを使用)
   * @param mode 送信モード (0=コマンド、1=データ)  
   * @param mode 送信モード (0=コマンド、1=データ)
   */
   */
  void lcd_write_nibble(uint8_t nibble, uint8_t mode)
  void lcd_write_nibble(uint8_t nibble, uint8_t mode)
  {
  {
     uint8_t data;
     uint8_t data;
   
     // 上位4ビットにニブルデータを配置
     // 上位4ビットにニブルデータを配置
     data = (nibble << 4) & 0xF0;
     data = (nibble << 4) & 0xF0;
   
     // モードビット (RS) とバックライトを設定
     // モードビット (RS) とバックライトを設定
     if(mode) {
     if(mode) {
        data |= LCD_RS;  // データモード
      data |= LCD_RS;  // データモード
     }
     }
     data |= lcd_backlight;  // バックライト状態を保持
     data |= lcd_backlight;  // バックライト状態を保持
   
     // Enableパルスを生成してデータを転送
     // Enableパルスを生成してデータを転送
     i2c_start();
     i2c_start();
810行目: 829行目:
  {
  {
     uint8_t data_h, data_l;
     uint8_t data_h, data_l;
   
     // 上位4ビットと下位4ビットに分割
     // 上位4ビットと下位4ビットに分割
     data_h = (cmd & 0xF0) | lcd_backlight;
     data_h = (cmd & 0xF0) | lcd_backlight;
     data_l = ((cmd << 4) & 0xF0) | lcd_backlight;
     data_l = ((cmd << 4) & 0xF0) | lcd_backlight;
   
     i2c_start();
     i2c_start();
   
     // 上位4ビットを送信
     // 上位4ビットを送信
     i2c_write(data_h | LCD_EN);  // Enable HIGH
     i2c_write(data_h | LCD_EN);  // Enable HIGH
822行目: 841行目:
     i2c_write(data_h);          // Enable LOW
     i2c_write(data_h);          // Enable LOW
     DELAY_US(1);
     DELAY_US(1);
   
     // 下位4ビットを送信
     // 下位4ビットを送信
     i2c_write(data_l | LCD_EN);  // Enable HIGH
     i2c_write(data_l | LCD_EN);  // Enable HIGH
     DELAY_US(1);
     DELAY_US(1);
     i2c_write(data_l);          // Enable LOW
     i2c_write(data_l);          // Enable LOW
   
     i2c_stop();
     i2c_stop();
   
     // コマンド実行完了待ち
     // コマンド実行完了待ち
     DELAY_MS(2);
     DELAY_MS(2);
841行目: 860行目:
  {
  {
     uint8_t data_h, data_l;
     uint8_t data_h, data_l;
   
     // 上位4ビットと下位4ビットに分割
     // 上位4ビットと下位4ビットに分割
     // RSビットをセット (データモード)  
     // RSビットをセット (データモード)
     data_h = (data & 0xF0) | LCD_RS | lcd_backlight;
     data_h = (data & 0xF0) | LCD_RS | lcd_backlight;
     data_l = ((data << 4) & 0xF0) | LCD_RS | lcd_backlight;
     data_l = ((data << 4) & 0xF0) | LCD_RS | lcd_backlight;
   
     i2c_start();
     i2c_start();
   
     // 上位4ビットを送信
     // 上位4ビットを送信
     i2c_write(data_h | LCD_EN);  // Enable HIGH
     i2c_write(data_h | LCD_EN);  // Enable HIGH
854行目: 873行目:
     i2c_write(data_h);          // Enable LOW
     i2c_write(data_h);          // Enable LOW
     DELAY_US(1);
     DELAY_US(1);
   
     // 下位4ビットを送信
     // 下位4ビットを送信
     i2c_write(data_l | LCD_EN);  // Enable HIGH
     i2c_write(data_l | LCD_EN);  // Enable HIGH
     DELAY_US(1);
     DELAY_US(1);
     i2c_write(data_l);          // Enable LOW
     i2c_write(data_l);          // Enable LOW
   
     i2c_stop();
     i2c_stop();
   
     // データ書き込み完了待ち
     // データ書き込み完了待ち
     DELAY_US(50);
     DELAY_US(50);
868行目: 887行目:
  /**
  /**
   * 文字列表示関数
   * 文字列表示関数
   * @param str 表示する文字列 (null終端)  
   * @param str 表示する文字列 (null終端)
   */
   */
  void lcd_print(const char *str)
  void lcd_print(const char *str)
874行目: 893行目:
     // 文字列の各文字を順次送信
     // 文字列の各文字を順次送信
     while(*str) {
     while(*str) {
        lcd_data(*str++);
      lcd_data(*str++);
     }
     }
  }
  }
880行目: 899行目:
  /**
  /**
   * カーソル位置設定関数
   * カーソル位置設定関数
   * @param row 行番号 (0-3)  
   * @param row 行番号 (0-3)
   * @param col 列番号 (0-19)  
   * @param col 列番号 (0-19)
   */
   */
  void lcd_set_cursor(uint8_t row, uint8_t col)
  void lcd_set_cursor(uint8_t row, uint8_t col)
  {
  {
     uint8_t address;
     uint8_t address;
   
     // DDRAMアドレスを行番号から計算
     // DDRAMアドレスを行番号から計算
     // 20x4 LCDのDDRAMアドレスマッピング:
     // 20x4 LCDのDDRAMアドレスマッピング:
894行目: 913行目:
     // 4行目: 0x54-0x67
     // 4行目: 0x54-0x67
     switch(row) {
     switch(row) {
        case 0:
      case 0:
            address = 0x00 + col;
          address = 0x00 + col;
            break;
          break;
        case 1:
      case 1:
            address = 0x40 + col;
          address = 0x40 + col;
            break;
          break;
        case 2:
      case 2:
            address = 0x14 + col;
          address = 0x14 + col;
            break;
          break;
        case 3:
      case 3:
            address = 0x54 + col;
          address = 0x54 + col;
            break;
          break;
        default:
      default:
            address = 0x00;
          address = 0x00;
     }
     }
   
     // Set DDRAM Address コマンド (最上位ビットを1に設定)  
     // Set DDRAM Address コマンド (最上位ビットを1に設定)
     lcd_cmd(0x80 | address);
     lcd_cmd(0x80 | address);
  }
  }
921行目: 940行目:
     // Clear Display コマンド
     // Clear Display コマンド
     lcd_cmd(0x01);
     lcd_cmd(0x01);
   
     // クリアコマンドは実行に約1.52ms必要
     // クリアコマンドは実行に約1.52[ms]必要
     DELAY_MS(2);
     DELAY_MS(2);
  }
  }
932行目: 951行目:
  {
  {
     lcd_backlight = LCD_BL;
     lcd_backlight = LCD_BL;
   
     // バックライト状態を更新
     // バックライト状態を更新
     i2c_start();
     i2c_start();
945行目: 964行目:
  {
  {
     lcd_backlight = 0;
     lcd_backlight = 0;
   
     // バックライト状態を更新
     // バックライト状態を更新
     i2c_start();
     i2c_start();