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
Revision 3:b2a573e31cc9, committed 2014-12-01
- Comitter:
- MikamiUitOpen
- Date:
- Mon Dec 01 03:47:45 2014 +0000
- Parent:
- 2:edf345c86b3b
- Commit message:
- 4
Changed in this revision
--- /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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ACM1602NI.hpp Mon Dec 01 03:47:45 2014 +0000 @@ -0,0 +1,77 @@ +//------------------------------------------------------ +// Class for LCD, ACM1602NI (Header) +// +// Default pin assignments +// D14 SDA ---- to pin5 of LCD module +// D15 SCL ---- to pin4 of LCD module +// +// Assignment of I2C ports +// SDA SCL +// I2C1 PB_7 or PB_9(D14) PB_6(D10) or PB_8(D15) +// I2C2 PB_3(D3) PB_10(D6) +// I2C3 PB_4(D5) or PC_9 PA_8(D7) +// +// 2014/08/27, Copyright (c) 2014 MIKAMI, Naoki +//------------------------------------------------------ + +#ifndef ACM1602NI_HPP +#define ACM1602NI_HPP + +#include "mbed.h" + +namespace Mikami +{ + class Acm1602Ni + { + public: + // Constructor + Acm1602Ni(PinName sda = D14, // SDA + PinName scl = D15, // SCL + uint32_t clock = 100000, // clock: 100 kHz + bool cursor = false, // cursor: off + bool blink = false); // blink: off + // Return false if LCD is not connected + bool GetOk() { return connected_; } + // All clear + bool Clear(); + // Send command + bool WriteCmd(uint8_t cmd) { return LcdTx(0x00, cmd); } + // Write character + void WriteChar(char data) { LcdTx(0x80, data); } + // Specify display position, x: 0 - 15, y: 0, 1 + void SetXY(uint8_t x = 0, uint8_t y = 0) { WriteCmd(x + y*0x40 | 0x80);} + // Write string from specified position + void WriteString(const char str[], uint8_t x = 0, uint8_t y = 0); + // Clear of specified line + void ClearLine(uint8_t line) + { WriteString(" ", 0, line); } + + private: + // Slave address of ACM1602NI (0x50) + static const uint8_t LCD_ADDRESS_ = 0x50 << 1; // left-justified 7-bit address + + bool connected_; // Set false in constructor if LCD is not connected + + bool LcdTx(uint8_t cmdData, uint8_t data); + bool Start(); + + // Forbid to use copy constructor + Acm1602Ni(const Acm1602Ni&); + // Forbid to use substitution operator + Acm1602Ni& operator=(const Acm1602Ni&); + + uint32_t* i2c_cr1_; // pointer to I2C_CR1 (control register 1) + uint32_t* i2c_dr_; // pointer to I2C_DR (data register) + uint32_t* i2c_sr1_; // pointer to I2C_SR1 (status register 1) + uint32_t* i2c_sr2_; // pointer to I2C_SR2 (status register 2) + I2C i2c_; // Object of I2C + + // For check contents of register + bool Check(uint32_t* rg, uint16_t value) + { return value == ((*rg) & value); } + + void TxDR(uint8_t data) { *i2c_dr_ = data; } + void SetCR1(uint16_t data) { *i2c_cr1_ |= data; } + }; +} +#endif // ACM1602NI_HPP
--- a/AQM0802A.cpp Sun Nov 30 06:10:19 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -//------------------------------------------------------- -// Class for LCD, AQM0802A -// -// 2014/11/30, Copyright (c) 2014 MIKAMI, Naoki -//------------------------------------------------------- - -#include "AQM0802A.hpp" - -namespace Mikami -{ - // Constructor - Aqm0802A::Aqm0802A(PinName sda, PinName scl, uint32_t clock, - bool cursor, bool blink) - : i2c_(sda, scl) - { - if (clock != 100000) i2c_.frequency(clock); - - wait_ms(40); - WriteCmd(0x39); // To extended command - WriteCmd(0x14); // Internal OSC frequency - WriteCmd(0x70 | 0x00); // Contrast set - WriteCmd(0x54 | 0x02); // Power/ICON/Contrast control - WriteCmd(0x6C); // Follower control - wait_ms(200); - - WriteCmd(0x38); // data length:8-bit, 2-line, 5×8 dots - WriteCmd(0x0C | (cursor << 1) | blink); - Clear(); // Clear display - } - - // All clear - void Aqm0802A::Clear() - { - WriteCmd(0x01); - wait_ms(50); - } - - // Write string - void Aqm0802A::WriteString(const char str[]) - { - for (int n=0; n<8; n++) - if (str[n] == 0) break; - else WriteChar(str[n]); - } - - // Write string from specified position - void Aqm0802A::WriteStringXY(const char str[], - uint8_t x, uint8_t y) - { - SetXY(x, y); - WriteString(str); - } - - // Set contrast - void Aqm0802A::SetContrast(uint8_t c) - { - WriteCmd(0x39); - WriteCmd(0x70 | (c & 0x0f)); // Lower 4 bits - WriteCmd(0x5C | ((c >> 4) & 0x03)); // Higher 2 bits - WriteCmd(0x38); - } - - //--------------------------------------------------- - // Following functions: private - - // Send command and data - void Aqm0802A::LcdTx(uint8_t cmdData, uint8_t data) - { - char tx[2]; - tx[0] = cmdData; - tx[1] = data; - i2c_.write(LCD_ADDRESS_, tx, 2); - } -} - -
--- a/AQM0802A.hpp Sun Nov 30 06:10:19 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -//------------------------------------------------------- -// Class for LCD, AQM0802A (Header) -// -// Default pin assignments -// D14 SDA ---- to pin4 of LCD module -// D15 SCL ---- to pin3 of LCD module -// -// Assignment of I2C ports -// SDA SCL -// I2C1 PB_7 or PB_9(D14) PB_6(D10) or PB_8(D15) -// I2C2 PB_3(D3) PB_10(D6) -// I2C3 PB_4(D5) or PC_9 PA_8(D7) -// -// 2014/11/30, Copyright (c) 2014 MIKAMI, Naoki -//------------------------------------------------------- - -#ifndef AQM0802A_HPP -#define AQM0802A_HPP - -#include "mbed.h" - -namespace Mikami -{ - class Aqm0802A - { - public: - // Constructor - Aqm0802A(PinName sda = D14, // SDA - PinName scl = D15, // SCL - uint32_t clock = 100000, // clock: 100 kHz - bool cursor = false, // cursor: off - bool blink = false); // blink: off - - // All clear - void Clear(); - // Send command - void WriteCmd(uint8_t cmd) { LcdTx(0x00, cmd); } - // Write character (Not 0x80 but 0x40) - void WriteChar(char data) { LcdTx(0x40, data); } - // Specify display position, x: 0 - 7, y: 0, 1 - void SetXY(uint8_t x = 0, uint8_t y = 0) - { WriteCmd(x + y*0x40 | 0x80);} - // Write string - void WriteString(const char str[]); - // Write string from specified position - void WriteStringXY(const char str[], uint8_t x, uint8_t); - // Clear of specified line - void ClearLine(uint8_t line) - { WriteStringXY(" ", 0, line); } - void SetContrast(uint8_t c); - - private: - // Slave address of AQM0802A - // left-justified 7-bit address - static const uint8_t LCD_ADDRESS_ = 0x7C; - - I2C i2c_; // Object of I2C - - void LcdTx(uint8_t cmdData, uint8_t data); - - // Forbid to use copy constructor - Aqm0802A(const Aqm0802A&); - // Forbid to use substitution operator - Aqm0802A& operator=(const Aqm0802A&); - }; -} -#endif // AQM0802A_HPP