STM32F103C8のMbedでの時計,DS1307で時刻表示OLED,OLED096UNO-A


stm32g031,stm32l010用に最軽量化したもの

x時間合わせは、別
x大幅に説明を省略

1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

忙しい人よう
https://os.mbed.com/users/caa45040/code/i2c_oled_ds1307_103_1/


```c++


#include "mbed.h"
#include "SSD1306.h"

#define ADDR_OLED       (0x3c<<1) //  address
//#define ADDR_OLED     (0x3d<<1) //  address
#define ADDR        (0xD0)   //  address

//I2C i2c(I2C_SDA, I2C_SCL);
I2C i2c(PB_7, PB_6); // STM32F103C8

// Host PC Communication channels
//Serial pc(USBTX, USBRX); // tx, rx
Serial pc(PA_9, PA_10); // tx, rx 103

// Instantiate OLED
SSD1306 oled(i2c, ADDR_OLED);

int ii; //ループカウンター
int jj; //ループカウンター
int cursor1; //文字カウンター

char    data_read[8];   //i2cバッファー

char ch_hex_a_b[4];
char *ch_hex_a(int l_num)
{
    ch_hex_a_b[0] = '0' + (l_num >> 4);
    ch_hex_a_b[1] = '0' + (l_num & 0xf);
    ch_hex_a_b[2] = '.';
    ch_hex_a_b[3] = 0;
    return(ch_hex_a_b);
}

void i2c_oled_w(char *s)
{
    ii=0;
    while(1){
        if(s[ii] == 0) break;
        //                y   x
        oled.writeBigChar(0, cursor1*16,s[ii]);
        cursor1=cursor1 + 1;
        ii=ii+1;
    } //for
} //i2c_oled_w

int main() {       
    pc.baud(9600);    
    //oled.writeString(0, 0, "Hello World !");  
        
    char n1_8[] = "12345678";
    
    ii=0;
    for(jj=0;jj<8;jj++){
        //                y   x
        oled.writeBigChar(0, ii*16,n1_8[jj]);
        ii = ii + 1;
    } //for
    pc.printf("Printed something\r");    
    wait_ms(500);

    //for(ii=0;ii<8;ii++){
    //    oled.writeString(ii, 0, "Hello World !"); 
    //}
    //wait_ms(1000);

    while(1){
 
        //液晶のクリア
        cursor1 = 0;      
        
        //時間の読み込み
        i2c.write(ADDR, "\000", 1);
        i2c.read(ADDR | 1, data_read, 7);

        //画面に表示
        i2c_oled_w(ch_hex_a(data_read[2]));
        i2c_oled_w(ch_hex_a(data_read[1]));
        ch_hex_a(data_read[0]);ch_hex_a_b[2]=0;
        i2c_oled_w(ch_hex_a_b);

        wait_ms(1000);  
        
    } //while
}



```

時間合わせ


```c++


#include "mbed.h"
#include <stdio.h>
 
//Serial pc(USBTX, USBRX); // tx, rx
//Serial pc(SERIAL_TX, SERIAL_RX);

#define ADDR        (0xD0)  //  address
#define ADDR_LCD    (0x7C)  //  address

//I2C i2c(I2C_SDA, I2C_SCL); //767
//I2C i2c(dp5, dp27); //1114
//I2C i2c(PA_10, PA_9); //010
I2C i2c(PB_7, PB_6); // STM32F103C8

char data_read[8];  //i2cバッファー

#define HH  12
#define MM  34

int main() {
    
///*INIT start *********  

    data_read[0]=0;
    data_read[1]=0;
    data_read[2]= ( MM /10)*16+( MM %10);
    data_read[3]= ( HH /10)*16+( HH %10);
    data_read[4]=3;    
    data_read[5]=1;
    data_read[6]=1;
    data_read[7]=0x20;
    
    i2c.write(ADDR, data_read, 8);

//*/  //INIT end *********

    while(1){} //無限ループ

} // main



```

![103_mbed_oled_ds1307_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4d57b4ec-05a9-3b64-f079-0a2ca42534b4.jpeg)

![103_mbed_oled_ds1307_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a58d91fe-9506-fedf-1dc1-d71eae3abb89.jpeg)

![i2c_oled_ds1307_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4866fa1b-d85c-9138-5330-0a470087a386.jpeg)



いろいろテスト


```c++





#include "mbed.h"
#include "SSD1308.h"

#include "font_8x8.h"
#include "font_16x24.h"

#if defined(TARGET_LPC1768)
#define I2C_OPTIMIZE   1
#else
#define I2C_OPTIMIZE   0
#endif

void fff(char *str1)
{
    printf(str1);//debug
}



/**
 *@brief Constructor
 *@param I2C *i2c reference to i2c
 *@param uint8_t deviceAddress slaveaddress
 */
SSD1308::SSD1308(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c) {
  
  _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
  _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read  
  
  initialize(); 
}//SSD1308

//イニシャライズ
void SSD1308::initialize()
{

    fff("initialize\r\n");//debug

    setHorizontalAddressingMode(); //メモリーアクセスモード

    clearDisplay();

    setInverted(false); //反転

    setDisplayOn();
}//initialize

//クリアディスプレー
void SSD1308::clearDisplay()
{

    fff("clearDisplay\r\n");//debug

    //setDisplayOff();
    setPageAddress(0, MAX_PAGE);  // all pages
    setColumnAddress(0, MAX_COL); // all columns

    for (uint8_t page = 0; page < PAGES; page++) {
        for (uint8_t col = 0; col < COLUMNS; col++) {
            _sendData(0x00);
        }
    }

    //setDisplayOn();
}//clearDisplay

//
void SSD1308::fillDisplay(uint8_t pattern,
                          uint8_t start_page, uint8_t end_page,
                          uint8_t start_col, uint8_t end_col)
{

    int count = (end_page - start_page + 1) * (end_col - start_col + 1);

    //setDisplayOff();
    setPageAddress(start_page, end_page);  // set page window
    setColumnAddress(start_col, end_col);  // set column window

    for (int i=0; i<count; i++) {
        _sendData(pattern); // Write Data
    }

    //setDisplayOn();
}//

//ライトビットマップ
void SSD1308::writeBitmap(uint8_t* data,
                          uint8_t start_page, uint8_t end_page,
                          uint8_t start_col, uint8_t end_col)
{

    fff("  writeBitmap\r\n");//debug

    int count = (end_page - start_page + 1) * (end_col - start_col + 1);

    //setDisplayOff();
    setPageAddress(start_page, end_page);  // set page window
    setColumnAddress(start_col, end_col);  // set column window

    for (int i=0; i<count; i++) {
        _sendData(data[i]); // Write Data
    }

    //setDisplayOn();
}//writeBitmap


#define PRG_MAX_SCALE     50
#define PRG_LEFT_EDGE   0xFF
#define PRG_RIGHT_EDGE  0xFF
#define PRG_ACTIVE      0xFF
//#define PRG_ACTIVE      0xBD
#define PRG_NOT_ACTIVE  0x81

//
void SSD1308::writeProgressBar(uint8_t page, uint8_t col, int percentage)
{
    uint8_t scale_value;

    if (percentage <= 0) {
        scale_value = 0;
    } else if (percentage >= 100) {
        scale_value = PRG_MAX_SCALE - 1;
    } else {
        scale_value = (percentage * PRG_MAX_SCALE) / 100;
    }

    //setDisplayOff();
    setPageAddress(page, page);
    setColumnAddress(col, MAX_COL);

    _sendData(PRG_LEFT_EDGE);

    for (uint8_t col = 0; col < scale_value; col++) {
        _sendData(PRG_ACTIVE);
    }

    _sendData(PRG_ACTIVE);

    for (uint8_t col = (scale_value+1); col < PRG_MAX_SCALE; col++) {
        _sendData(PRG_NOT_ACTIVE);
    }

    _sendData(PRG_RIGHT_EDGE);

    //setDisplayOn();
}//writeProgressBar

//ライトレベルバー
void SSD1308::writeLevelBar(uint8_t page, uint8_t col, int percentage)
{
    uint8_t scale_value;

    if (percentage <= 0) {
        scale_value = 0;
    } else if (percentage >= 100) {
        scale_value = PRG_MAX_SCALE - 1;
    } else {
        scale_value = (percentage * PRG_MAX_SCALE) / 100;
    }

    //setDisplayOff();
    setPageAddress(page, page);
    setColumnAddress(col, MAX_COL);

    _sendData(PRG_LEFT_EDGE);

    for (uint8_t col = 0; col < scale_value; col++) {
        _sendData(PRG_NOT_ACTIVE);  // Write Data
    }

    _sendData(PRG_ACTIVE);  // Write Data at active meterlevel

    for (uint8_t col = scale_value+1; col < PRG_MAX_SCALE; col++) {
        _sendData(PRG_NOT_ACTIVE);
    }

    _sendData(PRG_RIGHT_EDGE);

    //setDisplayOn();
}//writeLevelBar

//ライトキャラ
void SSD1308::writeChar(char chr)
{

    const uint8_t char_index = chr - 0x20;

    for (uint8_t i = 0; i < 8; i++) {
        if (_inverted) {
            _sendData( ~font_8x8[char_index][i] );
        } else {
            _sendData( font_8x8[char_index][i] );
        }
    }

}//writeChar

//ライトストリング
void SSD1308::writeString(uint8_t row, uint8_t col, const char * text)
{
    uint16_t index = 0;
    uint16_t len = strlen(text);

    setPageAddress(row, MAX_PAGE);
    const uint8_t col_addr = FONT8x8_WIDTH*col;
    setColumnAddress(col_addr, MAX_COL);

    while ((col+index) < CHARS && (index < len)) {
        // write first line, starting at given position
        writeChar(text[index++]);
    }

    // write remaining lines
    // write until the end of memory
    // then wrap around again from the top.
    if (index + 1 < len) {
        setPageAddress(row + 1, MAX_PAGE);
        setColumnAddress(0, MAX_COL);
        bool wrapEntireScreen = false;
        while (index + 1 < len) {
            writeChar(text[index++]);
            // if we've written the last character space on the screen,
            // reset the page and column address so that it wraps around from the top again
            if (!wrapEntireScreen && (row*CHARS + col + index) > 127) {
                setPageAddress(0, MAX_PAGE);
                setColumnAddress(0, MAX_COL);
                wrapEntireScreen = true;
            }
        }
    }
}//

//ライトビッグキャラ
void SSD1308::writeBigChar(uint8_t row, uint8_t col, char chr)
{

    fff("writeBigChar\r\n");//debug

    writeBitmap((uint8_t*) font_16x24[int(chr) - FONT16x24_START],
                row, (row + FONT16x24_BYTES - 1),
                col, (col + FONT16x24_WIDTH - 1));
}//writeBigChar

//センドコマンド コマンドx1
void SSD1308::_sendCommand(uint8_t command)
{
    char databytes[2] = {    COMMAND_MODE,    command             };
    _i2c->write(_writeOpcode,databytes, 2); 
    //_i2c.write(_writeOpcode, databytes, 2);    // Write command
}//

//センドコマンド コマンドx1 パラメーターx1
void SSD1308::_sendCommand(uint8_t command, uint8_t param1)
{
    char databytes[4] = {    COMMAND_MODE,    command,    COMMAND_MODE,    param1              };
    _i2c->write(_writeOpcode, databytes, 4);
    //_i2c.write(_writeOpcode, databytes, 4);    // Write command

}//

//センドコマンド コマンドx1 パラメーターx2
void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2)
{
    char databytes[6] = {    COMMAND_MODE,    command,    COMMAND_MODE,    param1,    COMMAND_MODE,    param2              };
    _i2c->write(_writeOpcode, databytes, 6);
    //_i2c.write(_writeOpcode, databytes, 6);    // Write command

}//

//センドコマンド コマンドx1 パラメーターx5
void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2,
                           uint8_t param3, uint8_t param4,
                           uint8_t param5)
{
    char databytes[12] = {    COMMAND_MODE,    command,    COMMAND_MODE,    param1,    COMMAND_MODE,    param2,
    COMMAND_MODE,    param3,    COMMAND_MODE,    param4,    COMMAND_MODE,    param5               };
    _i2c->write(_writeOpcode, databytes, 12);
    //_i2c.write(_writeOpcode, databytes, 12);    // Write command
}//

//センドコマンド コマンドx1 パラメーターx6
void SSD1308::_sendCommand(uint8_t command, uint8_t param1, uint8_t param2,
                           uint8_t param3, uint8_t param4,
                           uint8_t param5, uint8_t param6)
{
    char databytes[14] = {    COMMAND_MODE,    command,    COMMAND_MODE,    param1,    COMMAND_MODE,    param2,
    COMMAND_MODE,    param3,    COMMAND_MODE,    param4,    COMMAND_MODE,    param5,    COMMAND_MODE,    param6              };
    _i2c->write(_writeOpcode, databytes, 14);
    //_i2c.write(_writeOpcode, databytes, 14);    // Write command

}//

//センドデータ コマンドx1
void SSD1308::_sendData(uint8_t data)
{
    char databytes[2] = {    DATA_MODE,    data };
    _i2c->write(_writeOpcode, databytes, 2);
    //_i2c.write(_writeOpcode, databytes, 2);    // Write Data
}//

//センドデータ コマンドx1 データ
void SSD1308::_sendData(uint8_t len, uint8_t* data)
{
    for (int i=0; i<len ; i++) {
        _sendData(data[i]);  // Write Data
    }
}//_sendData

//セット
void SSD1308::setHorizontalAddressingMode()
{

    fff("setHorizontalAddressingMode\r\n");//debug

    setMemoryAddressingMode(HORIZONTAL_ADDRESSING_MODE);
}//setHorizontalAddressingMode

//
void SSD1308::setVerticalAddressingMode()
{
    setMemoryAddressingMode(VERTICAL_ADDRESSING_MODE);
}//setVerticalAddressingMode

//セットページ
void SSD1308::setPageAddressingMode()
{
    setMemoryAddressingMode(PAGE_ADDRESSING_MODE);
}//setPageAddressingMode

//セットメモリーアドレシングモード
void SSD1308::setMemoryAddressingMode(uint8_t mode)
{
    _sendCommand(SET_MEMORY_ADDRESSING_MODE, mode);
}//setMemoryAddressingMode

//セットページアドレス
void SSD1308::setPageAddress(uint8_t start, uint8_t end)
{
    _sendCommand(SET_PAGE_ADDRESS, start, end);
}//setPageAddress

//セット
void SSD1308::setColumnAddress(uint8_t start, uint8_t end)
{
    _sendCommand(SET_COLUMN_ADDRESS, start, end);
}//setColumnAddress

//セットディスプレースタートライン
void SSD1308::setDisplayStartLine(uint8_t line)
{
    line = line & MAX_ROW;

    _sendCommand(SET_DISPLAY_START_LINE | line);
}//setDisplayStartLine

//セットカラムスタート for ページアクセシングモード
void SSD1308::setColumnStartForPageAddressingMode(uint8_t column)
{
    column = column & MAX_COL;

    _sendCommand(SET_LOWER_COLUMN  | ( column     & 0x0F));  // lower nibble
    _sendCommand(SET_HIGHER_COLUMN | ((column>>4) & 0x0F));  // higher nibble
}//setColumnStartForPageAddressingMode

//セットカラムページ for ページアクセシングモード
void SSD1308::setPageStartForPageAddressingMode(uint8_t page)
{
    page = page & MAX_PAGE;

    _sendCommand(SET_PAGE_START_ADDRESS | page);
}//setPageStartForPageAddressingMode

//セットコントラストコントロール
void SSD1308::setContrastControl(uint8_t contrast)
{
    _sendCommand(SET_CONTRAST, contrast);
}//setContrastControl

//セットディスプレーオン
void SSD1308::setDisplayOn()
{

    fff("setDisplayOn\r\n");//debug

    _sendCommand(SET_DISPLAY_POWER_ON);
}//setDisplayOn

//セットディスプレーオフ
void SSD1308::setDisplayOff()
{
    _sendCommand(SET_DISPLAY_POWER_OFF);
}//setDisplayOff

//セットディスプレーパワー
void SSD1308::setDisplayPower(bool on)
{
    if (on) {
        setDisplayOn();
    } else {
        setDisplayOff();
    }
}//setDisplayPower

//セットディスプレーノーマル
void SSD1308::setDisplayNormal()
{
    _sendCommand(SET_NORMAL_DISPLAY);
}//setDisplayNormal

//セットディスプレーインバース
void SSD1308::setDisplayInverse()
{
    _sendCommand(SET_INVERSE_DISPLAY);
}//setDisplayInverse

//セットディスプレーブリンク
void SSD1308::setDisplayBlink(bool on)
{
    if (on) {
        _sendCommand(SET_FADE_BLINK, (BLINK_ENABLE | FADE_INTERVAL_128_FRAMES));
    } else {
        _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
    }
}//setDisplayBlink

//セットディスプレー fade
void SSD1308::setDisplayFade(bool on)
{
    if (on) {
        _sendCommand(SET_FADE_BLINK, (FADE_OUT_ENABLE | FADE_INTERVAL_128_FRAMES));
    } else {
        _sendCommand(SET_FADE_BLINK, FADE_BLINK_DISABLE);
    }
}//setDisplayFade

//セットディスプレー Flip
void SSD1308::setDisplayFlip(bool left, bool down)
{
    if (left) {
        // column address   0 is mapped to SEG0 (Reset)
        _sendCommand(SET_SEGMENT_REMAP_0);
    } else {
        // column address 127 is mapped to SEG0
        _sendCommand(SET_SEGMENT_REMAP_127);
    }

    if (down) {
        // Reset mode
        _sendCommand(SET_COMMON_REMAP_0);
    } else {
        // Flip Up/Down (Need to rewrite display before H effect shows)
        _sendCommand(SET_COMMON_REMAP_63);
    }

}//setDisplayFlip

//セットインターナル
void SSD1308::setInternalIref()
{
    _sendCommand(SET_IREF_SELECTION, INTERNAL_IREF);
}//setInternalIref

//セット
void SSD1308::setExternalIref()
{
    _sendCommand(SET_IREF_SELECTION, EXTERNAL_IREF);
}//setExternalIref

//セットエンタイアーディスプレーオン
void SSD1308::setEntireDisplayOn()
{
    _sendCommand(SET_ENTIRE_DISPLAY_ON);
}//setEntireDisplayOn

//セットエンタイアーディスプレーRAM
void SSD1308::setEntireDisplayRAM()
{
    _sendCommand(SET_DISPLAY_GDDRAM);
}//setEntireDisplayRAM

//セットエンタイアーディスプレー
void SSD1308::setEntireDisplay(bool on)
{
    if (on) {
        setEntireDisplayOn();  // All Pixels on
    } else {
        setEntireDisplayRAM(); // Pixels are RAM content
    }
}//setEntireDisplay

//セット
void SSD1308::setContinuousHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page, uint8_t interval)
{
    if (left) {
        _sendCommand(SET_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF);  // Scroll Left
    } else {
        _sendCommand(SET_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, 0x00, 0xFF); // Scroll Right
    }

}//setContinuousHorizontalScroll

//セット
void SSD1308::setContinuousVerticalAndHorizontalScroll(bool left, uint8_t start_page, uint8_t end_page,
        uint8_t offset, uint8_t interval)
{
    if (left) {
        _sendCommand(SET_VERT_LEFT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset);  // Scroll Left
    } else {
        _sendCommand(SET_VERT_RIGHT_HOR_SCROLL, 0x00, start_page, interval, end_page, offset); // Scroll Right
    }

}//setContinuousVerticalAndHorizontalScroll

//セット
void SSD1308::setVerticalScrollArea(uint8_t topRowsFixed, uint8_t scrollRows)
{
    if ((topRowsFixed + scrollRows) > ROWS) {
        scrollRows = ROWS - topRowsFixed;
    }

    _sendCommand(SET_VERTICAL_SCROLL_AREA, topRowsFixed, scrollRows);
}//setVerticalScrollArea

//セットディスプレースクロール
void SSD1308::setDisplayScroll(bool on)
{
    if (on) {
        _sendCommand(SET_ACTIVATE_SCROLL);   // Scroll on
    } else {
        _sendCommand(SET_DEACTIVATE_SCROLL); // Scroll off
    }
}//setDisplayScroll

//
void SSD1308::_init()
{
    _sendCommand(SET_DISPLAY_POWER_OFF);      // 0xAE

    // column address   0 is mapped to SEG0 (Reset)
    // row address   0 is mapped to COM0 (Reset)
    _sendCommand(SET_SEGMENT_REMAP_0);        // 0xA0 (Reset)
    _sendCommand(SET_COMMON_REMAP_0);         // 0xC0 (Reset)

    setDisplayStartLine(0);                   // 0x40 (Reset)

    _sendCommand(SET_COMMON_CONF, COMMON_BASE | COMMON_ALTERNATIVE | COMMON_LEFTRIGHT_NORMAL); // 0xDA, 0x12 (Reset)

    // Pagemode or Horizontal mode
//  setPageAddressingMode();                  // 0x20, 0x02 (Reset)
//  setColumnStartForPageAddressingMode(0);   // 0x00, 0x10 (Reset = Column 0)
//  setPageStartForPageAddressingMode(PAGE_0);// 0xBO       (Reset = Page 0)
    setHorizontalAddressingMode();            // 0x20, 0x00 (Non-Reset)
    setColumnAddress(0, MAX_COL);             // 0x21, 0x00, 0x37 (Reset)
    setPageAddress(0, MAX_PAGE);              // 0x22, 0x00, 0x07 (Reset)

    setExternalIref();                        // 0xAD, 0x10 (Reset)

    _sendCommand(SET_DISPLAY_CLOCK, 0x70);    // 0xD5, 0x70 (Reset = 0x80)
    _sendCommand(SET_PRECHARGE_TIME, 0x21);   // 0xD9, 0x21 (Reset = 0x22)
    _sendCommand(SET_VCOMH_DESELECT_LEVEL, 0x30); // 0xDB, 0x30 (Reset = 0x20)
    _sendCommand(SET_MULTIPLEX_RATIO, 0x3F);  // 0xA8, 0x3F (Reset)
    _sendCommand(SET_DISPLAY_OFFSET, 0x00);   // 0xD3, 0x00 (Reset)

    _sendCommand(SET_CONTRAST, 0x7F);         // 0x81, 0x7F (Reset)

    _sendCommand(SET_NORMAL_DISPLAY);         // 0xA6 (Reset)

    setEntireDisplayRAM();                    // 0xA4 (Reset)
    setDisplayScroll(false);

    clearDisplay();

    _sendCommand(SET_DISPLAY_POWER_ON);       // 0xAF
}//_init





```