Library for LCD ACM1602NI connected using I2C on Nucleo F401 is not to be found. Using I2C class offered by mbed, I cannot program for this LCD on Nucleo F401. So I programmed for this LCD to control by direct accsessing registors for I2C in STM32F401RE. Nucleo F401 で使用できる,I2C 接続の LCD ACM1602NI 用のライブラリ.このライブラリでは,I2C クラスのコンストラクタとクロック周波数設定のメンバ関数は使っているが,その他のメンバ関数などは使っていない.その理由は,タイミングの関係だと思うが,I2C クラスのメンバ関数では正常に動くプログラムを,どうしても作れないことによる.しょうがないので,MCU の I2C 関係のレジスタに直接アクセスするようなプログラムを作ったたところ,動くようになった.Nucleo の F401RE 以外については確認していない.動かない場合は,I2C 用のレジスタのアドレスを,使っている MCU に応じて書きかえる必要がある.
Dependents: ACM1602NI_Nucleo_Demo
Diff: ACM1602NI.cpp
- Revision:
- 3:b2a573e31cc9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ACM1602NI.cpp Mon Dec 01 03:47:45 2014 +0000 @@ -0,0 +1,109 @@ +//------------------------------------------------------ +// Class for LCD, ACM1602NI +// +// 2014/08/27, Copyright (c) 2014 MIKAMI, Naoki +//------------------------------------------------------ + +#include "ACM1602NI.hpp" + +namespace Mikami +{ + // Constructor + Acm1602Ni::Acm1602Ni(PinName sda, PinName scl, uint32_t clock, + bool cursor, bool blink) + : i2c_(sda, scl) + { + uint32_t i2cAddr = 0; + if ( ((sda == PB_9) || (sda == PB_7)) && + ((scl == PB_8) || (scl == PB_6)) ) + i2cAddr = I2C_1; // I2C1 will be used + if ( (sda == PB_3) && (scl == PB_10) ) + i2cAddr = I2C_2; // I2C2 will be used + if ( ((sda == PC_9) || (sda == PB_4)) && + (scl == PA_8) ) + i2cAddr = I2C_3; // I2C3 will be used + + i2c_cr1_ = (uint32_t *)i2cAddr; + i2c_dr_ = (uint32_t *)(i2cAddr + 0x10); + i2c_sr1_ = (uint32_t *)(i2cAddr + 0x14); + i2c_sr2_ = (uint32_t *)(i2cAddr + 0x18); + + connected_ = Clear(); // Clear display + if (!connected_) return; + + if (clock != 100000) i2c_.frequency(clock); + + WriteCmd(0x38); // data length:8-bit, 2-line, 5×8 dots + WriteCmd(0x0C | (cursor << 1) | blink); + WriteCmd(0x06); // cursor direction: rightward + } + + // All clear + bool Acm1602Ni::Clear() + { + bool ok = WriteCmd(0x01); + wait_ms(50); + return ok; + } + + // Write string from specified position + void Acm1602Ni::WriteString(const char str[], uint8_t x, uint8_t y) + { + SetXY(x, y); + for (int n=0; n<16; n++) + if (str[n] == 0) break; + else WriteChar(str[n]); + } + + //------------------------------------------------------------------------------ + // Following: private functions + + // Send command and data + bool Acm1602Ni::LcdTx(uint8_t cmdData, uint8_t data) + { + if (!Start()) return false; + TxDR(cmdData); // "cmdData" defines king of "data" in next statement + TxDR(data); // Send command or RAM dataspecify specified by "cmdData" + wait_us(500); // indispensable + SetCR1(0x200); // Generate stop condition + return true; + } + + // Preparation for send of command and data + bool Acm1602Ni::Start() + { + const uint8_t WAIT = 20; + const uint8_t LENGTH = 10; + uint8_t n; + + // wait for I2C not busy + for (n=0; n<LENGTH; n++) + { + wait_us(WAIT); + if (!Check(i2c_sr2_, 0x02)) break; + } + if (n == LENGTH) return false; + + // Generate start condition + SetCR1(0x100); + // Confirm start condition and master mode + for (n=0; n<LENGTH; n++) + { + wait_us(WAIT); + if (Check(i2c_sr1_, 0x01) && Check(i2c_sr2_, 0x03)) break; + } + if (n == LENGTH) return false; + + // Send slave address + TxDR(LCD_ADDRESS_); + // Confirm on transmit mode + for (n=0; n<LENGTH; n++) + { + wait_us(WAIT); + if (Check(i2c_sr1_, 0x82) && Check(i2c_sr2_, 0x07)) break; + } + if (n == LENGTH) return false; + + return true; + } +}