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

ACM1602NI.cpp

Committer:
MikamiUitOpen
Date:
2014-12-01
Revision:
3:b2a573e31cc9

File content as of revision 3:b2a573e31cc9:

//------------------------------------------------------
//  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;
    }
}