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

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Mon Dec 01 03:47:45 2014 +0000
Parent:
2:edf345c86b3b
Commit message:
4

Changed in this revision

ACM1602NI.cpp Show annotated file Show diff for this revision Revisions of this file
ACM1602NI.hpp Show annotated file Show diff for this revision Revisions of this file
AQM0802A.cpp Show diff for this revision Revisions of this file
AQM0802A.hpp Show diff for this revision Revisions of this file
diff -r edf345c86b3b -r b2a573e31cc9 ACM1602NI.cpp
--- /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;
+    }
+}
diff -r edf345c86b3b -r b2a573e31cc9 ACM1602NI.hpp
--- /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
diff -r edf345c86b3b -r b2a573e31cc9 AQM0802A.cpp
--- 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);
-    }
-}
-
-
diff -r edf345c86b3b -r b2a573e31cc9 AQM0802A.hpp
--- 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