📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の1版が非表示) | |||
| 405行目: | 405行目: | ||
<br> | <br> | ||
==== MSP430F149のI2C設定 ==== | ==== MSP430F149のI2C設定 ==== | ||
MSP430F149でI2C通信を正常に動作させるためには、以下の設定を行う必要がある。<br> | |||
<br> | <br> | ||
* クロック設定 | |||
*: MSP430F149では、複数のクロックソースが利用可能である。 | |||
*: ACLK (Auxiliary Clock) は、32.768[kHz]の低速クロックで、低電力動作に使用される。 | |||
<br> | *" MCLK (Master Clock) は、CPUのメインクロックで、1[MHz]〜8[MHz]で動作する。 | ||
*: SMCLK (Sub-Main Clock) は、ペリフェラル用のクロックで、I2C通信ではこのSMCLKを使用することが一般的である。 | |||
*: <br> | |||
* USARTモジュールをI2Cモードで使用 | |||
*# まず、U0CTLレジスタ (USART0の場合) のSWRSTビットをセットして、モジュールをリセット状態にする。 | |||
*# 次に、I2Cモードを有効にして、マスターまたはスレーブモードを選択する。<br>MSP430F149がI2Cマスターとして動作する場合は、I2CENビットとMSTビットをセットする。 | |||
*: <br> | |||
* クロック分周の設定 | |||
*: U0BRレジスタを使用してI2Cのクロック周波数を設定する。 | |||
*: 例えば、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 | ||
// 遅延マクロ ( | // 遅延マクロ (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を約1[MHz]に設定 (MSP430F149のキャリブレーション値を使用) | ||
BCSCTL1 = CALBC1_1MHZ; | BCSCTL1 = CALBC1_1MHZ; | ||
DCOCTL = CALDCO_1MHZ; | DCOCTL = CALDCO_1MHZ; | ||
// SMCLKの設定 (ペリフェラル用クロック) | // SMCLKの設定 (ペリフェラル用クロック) | ||
BCSCTL2 &= ~(DIVS_3); // SMCLK分周なし ( | 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); | |||
__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が1[MHz]の場合、I2Cクロックを100[kHz]に設定 | ||
// 分周比 = | // 分周比 = 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受信時の処理 | |||
I2CIFG &= ~NACKIE; // フラグをクリア | |||
// エラーハンドリング (必要に応じて実装) | |||
// ...略 | |||
} | } | ||
} | } | ||
| 738行目: | 757行目: | ||
{ | { | ||
// 電源投入後の安定化待ち | // 電源投入後の安定化待ち | ||
// | // 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_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++); | |||
} | } | ||
} | } | ||
| 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: | |||
address = 0x00 + col; | |||
break; | |||
case 1: | |||
address = 0x40 + col; | |||
break; | |||
case 2: | |||
address = 0x14 + col; | |||
break; | |||
case 3: | |||
address = 0x54 + col; | |||
break; | |||
default: | |||
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. | // クリアコマンドは実行に約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(); | ||