MSP430のI2CでLCD表示
このソフトは…
Universal Serial Interface (USI) を持ったMSP430G2を使って、 ST7032i 搭載の LCDモジュールを 制御するものです。 I2Cを使う際の参考にどうぞ。 ちなみにMSP430がマスタになって LCD モジュールに一方的にデータを 送りつけているだけです。
ハードウェア
- Strawberry Linux で売っていた I2C LCDモジュール を使いました。
- Launch Pad を使う場合、I2C の SCL を出す P1.6 のピンが LED につながっているので (P1.6 の)ジャンパをはずしておきます。
- MSP430 の P1.6, P1.7 に対応したピンを 2〜3 kΩ程度の 抵抗でプルアップしてモジュールの 2 番と 3 番にそれぞれつなげます。 モジュールはMSP430と電源を共有します。
基本的にそれだけです。うまく動けば画面に文字が表示されます。 通信に失敗している場合は(Launch Padの場合)P1.0のLEDが光るように なってるので、光ったら回路を確認してください。
ソース
// i2c_lcd.c by Yagshi 2011
#include <io.h>
#include <msp430/usi.h>
#include <signal.h>
#define kPeriod 12 // 12000 / 12 = 1000 [Hz]
#define kSlaveAddr 0x3e
char buf[] = {
0x80, 0x38, // normal instruction set
0x80, 0x39, // extension instruction set
0x80, 0x14, // freq.
0x80, 0x78, // contrast
0x80, 0x5f, // power/icon/contrast
0x80, 0x6a, // follower control
};
char buf2[] = {
0x80, 0x0f, // display=on, cursor=on, blink=on
0x80, 0x01, // CLS
0x80, 0x06,
};
char buf3[] = {0x40, 'T', 'e', 's', 't', 'Y', 'o', 'u', '!' };
void initializeMCU(void)
{
WDTCTL = WDTPW + WDTHOLD; // shut up the dog
BCSCTL3 |= LFXT1S_2; // Select VLO for ACLK
P1DIR |= BIT0;
// setup TIMER_A
TACTL = TASSEL__ACLK + ID_0 + MC__UP;
TACCR0 = kPeriod;
TACCTL0 |= CCIE; // enable interrupt
// setup clock (DCO = 15 MHz)
DCOCTL |= DCO1 + DCO0;
BCSCTL1 |= RSEL3 + RSEL2 + RSEL1 + RSEL0;
// setup USI
P1SEL |= BIT6 + BIT7;
USICTL0 |= USISWRST;
USICTL0 &= ~USISWRST; // start USI
USICTL0 |= USIPE7 + USIPE6 + USIMST;
USICTL1 = USII2C; // I2C mode
USICKCTL = USIDIV_7 + USISSEL_2 + USICKPL; // div = 128, SMCLK,
}
interrupt(TIMERA0_VECTOR) interruptTimerA0(void)
{
_BIC_SR_IRQ(SCG1 | SCG0 | CPUOFF);
}
void waitMs(int aMs)
{
while(aMs--){
_BIS_SR(SCG1 | SCG0 | CPUOFF);
};
}
void i2cMakeStartCondition(void)
{
while(!(P1IN & BIT6));
USISRL = 0;
USICTL0 |= USIGE + USIOE;
USICTL0 &= ~USIGE;
}
void i2cMakeStopCondition(void)
{
USICTL0 |= USIOE;
USISRL = 0;
USICNT = 1;
while(!(USICTL1 & USIIFG));
USISRL = 0xff;
USICTL0 |= USIGE;
USICTL0 &= ~(USIGE + USIOE);
}
/**
* @brief I2C transmission (1 byte)
* @params aData the data byte
* @return 1 if NACK, 0 if ACK
*/
int i2cTransmit(int aData)
{
while(!(P1IN & BIT6));
USISRL = aData;
USICTL0 |= USIOE;
USICNT = 8;
while(!(USICTL1 & USIIFG));
// receive ACK
USICTL0 &= ~USIOE;
USICNT = 1;
while(!(USICTL1 & USIIFG));
return USISRL & 1;
}
int main(void)
{
int i;
initializeMCU();
_BIS_SR(GIE);
P1OUT &= ~BIT0;
i2cMakeStopCondition();
waitMs(40);
i2cMakeStartCondition();
i2cTransmit(kSlaveAddr << 1);
for(i = 0; i < sizeof(buf); i ++){
if(i2cTransmit(buf[i])) P1OUT |= BIT0;
}
waitMs(200);
for(i = 0; i < sizeof(buf2); i ++){
if(i2cTransmit(buf2[i])) P1OUT |= BIT0;
}
waitMs(200);
for(i = 0; i < sizeof(buf3); i ++){
if(i2cTransmit(buf3[i])) P1OUT |= BIT0;
}
i2cMakeStopCondition();
for(;;) _BIS_SR(SCG1 | SCG0 | CPUOFF); // goes into LPM3
return 0;
}