LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-03-06

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

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

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

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



#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
}



時間合わせ



#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

103_mbed_oled_ds1307_2.jpg

i2c_oled_ds1307_1.jpg

いろいろテスト






#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





0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0