현 직장에서 SH1106을 사용하게 되었는데.
 
생성자를 보면, SID(슬레이브 ID)와 SCLK(시리얼 통신 클럭 핀), DC(데이터/컨트롤 핀), RST(리셋 핀), CS(칩 셀렉트 핀)을 설정하도록 되어 있다.
그래서, 해당 라이브러리에서 레지스터를 다이렉트로 연결해서 사용하도록 만들어 봤다.(굳이 이렇게 하지 않고, 해당 핀 번호 혹은 레지스트 연결하는 하위 함수를 아시는 분들은 매크로를 사용해서 수정하면 된다.)
이렇게 header파일를 수정했다.
추가한 함수를 정의한 내용.
 
 
 
 보드가 설정되었던게 Arduino 라이브러리에서 핀 번호로 할당되지 않는 핀이 적용된 상태이다.(Atmel 2560)
| 1 2 3 4 5 6 | class Adafruit_SH1106 : public Adafruit_GFX {  public:   Adafruit_SH1106(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);   Adafruit_SH1106(int8_t DC, int8_t RST, int8_t CS);   Adafruit_SH1106(int8_t RST); } | cs | 
생성자를 보면, SID(슬레이브 ID)와 SCLK(시리얼 통신 클럭 핀), DC(데이터/컨트롤 핀), RST(리셋 핀), CS(칩 셀렉트 핀)을 설정하도록 되어 있다.
 그리고, 이 설정된 핀의 번호를 보고 해당 레지스터의 위치를 찾아서 수정하도록 되어 있는 상태인데.
 이것이 불만족스러웠다.(특히, 지금 Atmel 2560의 데이터를 전부 다 사용하도록 만든 보드를 사용하는 회사 보드 입장에선 라이브러리가 불만인 상황...)
| 1 2 3 4 |     csport      = (PortReg*)portOutputRegister(digitalPinToPort(cs));     cspinmask   = digitalPinToBitMask(cs);     dcport      = (PortReg*)portOutputRegister(digitalPinToPort(dc));     dcpinmask   = digitalPinToBitMask(dc); | cs | 
그래서, 해당 라이브러리에서 레지스터를 다이렉트로 연결해서 사용하도록 만들어 봤다.(굳이 이렇게 하지 않고, 해당 핀 번호 혹은 레지스트 연결하는 하위 함수를 아시는 분들은 매크로를 사용해서 수정하면 된다.)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |   /*    @function : setCsPort    @arg : PortReg* port(레지스트의 동작을 설정하는 변수)    @arg : PortReg* portOpen(레지스트 초기화 하기 위한 변수)    @arg : csPin(값 설정)   */   void setCsPort(PortReg* port, PortReg* portOpen, uint8_t csPin);   /*    @function : setDcPort    @arg : PortReg* port(레지스트의 동작을 설정하는 변수)    @arg : PortReg* portOpen(레지스트 초기화 하기 위한 변수)    @arg : csPin(값 설정)   */   void setDcPort(PortReg* port, PortReg* portOpen, uint8_t dcPin);   /*    @function : setRestPort    @arg : PortReg* port(레지스트의 동작을 설정하는 변수)    @arg : PortReg* portOpen(레지스트 초기화 하기 위한 변수)    @arg : csPin(값 설정)   */   void setRestPort(PortReg* port, PortReg* portOpen, uint8_t restPin, bool rest = true);   /*    @function : init    @설명 :     begin()의 함수를 다시 재설정하기 위해서 동작 시키는 함수.   */   void init(uint8_t switchvcc = SH1106_SWITCHCAPVCC, uint8_t i2caddr = SH1106_I2C_ADDRESS); | cs | 
이렇게 header파일를 수정했다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | void Adafruit_SH1106::setCsPort(PortReg* port, PortReg* portOpen, uint8_t mask) {     csport = port;     *portOpen |= mask;     cspinmask = mask; } void Adafruit_SH1106::setDcPort(PortReg* port, PortReg* portOpen, uint8_t mask) {     dcport = port;     *portOpen |= mask;     dcpinmask = mask; } void Adafruit_SH1106::setRestPort(PortReg* port, PortReg* portOpen, uint8_t mask, bool rest) {     restport = port;     *portOpen |= mask;     restpinmask = mask;     if(rest)     {         *restport |= restpinmask;         delay(1);         *restport &= ~restpinmask;         delay(10);         *restport |= restpinmask;     } } void Adafruit_SH1106::init(uint8_t vccstate, uint8_t i2caddr) {     sid = 0;     hwSPI = true;     if (hwSPI){         SPI.begin ();         #ifdef __SAM3X8E__             SPI.setClockDivider (9); // 9.3 MHz         #else             SPI.setClockDivider (SPI_CLOCK_DIV2); // 8 MHz         #endif     }     #if defined SH1106_128_32     // Init sequence for 128x32 OLED module     SH1106_command(SH1106_DISPLAYOFF);                    // 0xAE     SH1106_command(SH1106_SETDISPLAYCLOCKDIV);            // 0xD5     SH1106_command(0x80);                                  // the suggested ratio 0x80     SH1106_command(SH1106_SETMULTIPLEX);                  // 0xA8     SH1106_command(0x1F);     SH1106_command(SH1106_SETDISPLAYOFFSET);              // 0xD3     SH1106_command(0x0);                                   // no offset     SH1106_command(SH1106_SETSTARTLINE | 0x0);            // line #0     SH1106_command(SH1106_CHARGEPUMP);                    // 0x8D     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x10); }     else     { SH1106_command(0x14); }     SH1106_command(SH1106_MEMORYMODE);                    // 0x20     SH1106_command(0x00);                                  // 0x0 act like ks0108     SH1106_command(SH1106_SEGREMAP | 0x1);     SH1106_command(SH1106_COMSCANDEC);     SH1106_command(SH1106_SETCOMPINS);                    // 0xDA     SH1106_command(0x02);     SH1106_command(SH1106_SETCONTRAST);                   // 0x81     SH1106_command(0x8F);     SH1106_command(SH1106_SETPRECHARGE);                  // 0xd9     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x22); }     else     { SH1106_command(0xF1); }     SH1106_command(SH1106_SETVCOMDETECT);                 // 0xDB     SH1106_command(0x40);     SH1106_command(SH1106_DISPLAYALLON_RESUME);           // 0xA4     SH1106_command(SH1106_NORMALDISPLAY);                 // 0xA6     #endif     #if defined SH1106_128_64     // Init sequence for 128x64 OLED module     SH1106_command(SH1106_DISPLAYOFF);                    // 0xAE     SH1106_command(SH1106_SETDISPLAYCLOCKDIV);            // 0xD5     SH1106_command(0x80);                                  // the suggested ratio 0x80     SH1106_command(SH1106_SETMULTIPLEX);                  // 0xA8     SH1106_command(0x3F);     SH1106_command(SH1106_SETDISPLAYOFFSET);              // 0xD3     SH1106_command(0x00);                                   // no offset     SH1106_command(SH1106_SETSTARTLINE | 0x0);            // line #0 0x40     SH1106_command(SH1106_CHARGEPUMP);                    // 0x8D     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x10); }     else     { SH1106_command(0x14); }     SH1106_command(SH1106_MEMORYMODE);                    // 0x20     SH1106_command(0x00);                                  // 0x0 act like ks0108     SH1106_command(SH1106_SEGREMAP | 0x1);     SH1106_command(SH1106_COMSCANDEC);     SH1106_command(SH1106_SETCOMPINS);                    // 0xDA     SH1106_command(0x12);     SH1106_command(SH1106_SETCONTRAST);                   // 0x81     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x9F); }     else     { SH1106_command(0xCF); }     SH1106_command(SH1106_SETPRECHARGE);                  // 0xd9     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x22); }     else     { SH1106_command(0xF1); }     SH1106_command(SH1106_SETVCOMDETECT);                 // 0xDB     SH1106_command(0x40);     SH1106_command(SH1106_DISPLAYALLON_RESUME);           // 0xA4     SH1106_command(SH1106_NORMALDISPLAY);                 // 0xA6     #endif     #if defined SH1106_96_16     // Init sequence for 96x16 OLED module     SH1106_command(SH1106_DISPLAYOFF);                    // 0xAE     SH1106_command(SH1106_SETDISPLAYCLOCKDIV);            // 0xD5     SH1106_command(0x80);                                  // the suggested ratio 0x80     SH1106_command(SH1106_SETMULTIPLEX);                  // 0xA8     SH1106_command(0x0F);     SH1106_command(SH1106_SETDISPLAYOFFSET);              // 0xD3     SH1106_command(0x00);                                   // no offset     SH1106_command(SH1106_SETSTARTLINE | 0x0);            // line #0     SH1106_command(SH1106_CHARGEPUMP);                    // 0x8D     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x10); }     else     { SH1106_command(0x14); }     SH1106_command(SH1106_MEMORYMODE);                    // 0x20     SH1106_command(0x00);                                  // 0x0 act like ks0108     SH1106_command(SH1106_SEGREMAP | 0x1);     SH1106_command(SH1106_COMSCANDEC);     SH1106_command(SH1106_SETCOMPINS);                    // 0xDA     SH1106_command(0x2);    //ada x12     SH1106_command(SH1106_SETCONTRAST);                   // 0x81     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x10); }     else     { SH1106_command(0xAF); }     SH1106_command(SH1106_SETPRECHARGE);                  // 0xd9     if (vccstate == SH1106_EXTERNALVCC)     { SH1106_command(0x22); }     else     { SH1106_command(0xF1); }     SH1106_command(SH1106_SETVCOMDETECT);                 // 0xDB     SH1106_command(0x40);     SH1106_command(SH1106_DISPLAYALLON_RESUME);           // 0xA4     SH1106_command(SH1106_NORMALDISPLAY);                 // 0xA6     #endif     SH1106_command(SH1106_DISPLAYON);//--turn on oled panel } | cs | 
추가한 함수를 정의한 내용.
이렇게 사용하여, 다음과 같은 방식으로 추가하면, 제대로 동작을 할 수 있다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <Adafruit_GFX.h> #include <Adafruit_SH1106_changes.h> #define OLED_RESET -1 //Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); Adafruit_SH1106 display(OLED_RESET); void setup()   {   // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)   display.begin(SH1106_SWITCHCAPVCC);   // init done   display.setCsPort(&PORTH, &DDRH, B00100000);   display.setDcPort(&PORTG, &DDRG, B00001000);   display.setRestPort(&PORTG, &DDRG, B00010000);   display.init(SH1106_SWITCHCAPVCC); } | cs | 
이렇게 Arduino 파일에 적용해서 사용할 수 있게 된다.
SPI에서 MOSI와 MISO는 자체적으로 고정된 핀을 사용하므로, CS핀과 Reset핀, DC핀 중에 숫자핀이 없다면, 사용하는 것이 좋다.
여담으로 오랜만에 티스토리에 포스팅하는데 에디터가 참, 안좋게 바뀐 것 같다.
특히, ColorScript의 클립보드 붙여넣기가 제대로 동작이 안되서 불편함이 이만저만이 아니다.
'Arduino' 카테고리의 다른 글
| Arduino에서 millis()와 delay()가 제대로 동작안되는 경우. (0) | 2020.07.04 | 
|---|---|
| [Arduino] Lora32u4의 LoRa 라이브러리. Begin()에서 초기화가 되지 않는다면? (0) | 2019.09.21 | 
| [Arduino]Adafruit_SH1106에 SPI 정보가 변했을 경우 복구하는 소스로 라이브러리 수정 (0) | 2019.05.07 | 










