/* OLED_SSD1306 via I2C * * This program communicate with the OLED_SSD1306 via I2C. * It writes "ABC" on the display and fills the rest of the * display with a checker board pattern. * * I2C1SCL P6.5 * I2C1SDA P6.4 * * Built and tested with MSP432P401R Rev. C, Keil MDK-ARM v5.24a and MSP432P4xx_DFP v3.1.0 */ #include "msp.h" #define SLAVE_ADDR 0x3C // 0111 100. #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define SCREEN_PAGE_NUM (SCREEN_HEIGHT / 8) void delayMs(int n); void I2C1_init(void); int I2C1_byteWrite(int slaveAddr, unsigned char memAddr, unsigned char data); void SSD1306_init(void); void SSD1306_data(char data); void SSD1306_command(char command); char imagebuf[SCREEN_PAGE_NUM][SCREEN_WIDTH]; const static char font_table[][6] = { /* sample font table */ {0x7e, 0x11, 0x11, 0x11, 0x7e, 0}, /* A */ {0x7f, 0x49, 0x49, 0x49, 0x36, 0}, /* B */ {0x3e, 0x41, 0x41, 0x41, 0x22, 0}}; /* C */ int main(void) { int i, j, k; I2C1_init(); SSD1306_init(); SSD1306_command(0x22); /* set page */ SSD1306_command(0x00); /* starting page */ SSD1306_command(0x00); /* end page */ SSD1306_command(0x21); /* set column */ SSD1306_command(0); /* starting column */ SSD1306_command(SCREEN_WIDTH-1); /* end column */ /* write ABC at the beginning of first line */ for (j = 0; j < 3; j++) for (i = 0; i < 6; i++) SSD1306_data(font_table[j][i]); /* clear the rest of the line */ for (i = 0; i < SCREEN_WIDTH-3*6; i++) SSD1306_data(0); for (i = 1; i < SCREEN_PAGE_NUM; i++) { SSD1306_command(0x22); /* set page */ SSD1306_command(i); /* starting page */ SSD1306_command(i); /* end page */ SSD1306_command(0x21); /* set column */ SSD1306_command(0); /* starting column */ SSD1306_command(SCREEN_WIDTH-1); /* end column */ /* make checker board pattern */ for (j = 0; j < SCREEN_WIDTH/8; j++) { for (k = 0; k < 4; k++) SSD1306_data(0xF0); for (k = 0; k < 4; k++) SSD1306_data(0x0F); } } for (;;) { /* infinite loop */ } } /* system clock at 3 MHz, MSP432P401R Rev. C, Start-up v2.2.1 */ void delayMs(int n) { int i, j; for (j = 0; j < n; j++) for (i = 750; i > 0; i--); /* Delay */ } /* configure UCB1 as I2C */ void I2C1_init(void) { extern uint32_t SystemCoreClock; EUSCI_B1->CTLW0 |= 1; /* disable UCB1 during config */ EUSCI_B1->CTLW0 = 0x0F81; /* 7-bit slave addr, master, I2C, synch mode, use SMCLK */ EUSCI_B1->BRW = 30; /* set clock prescaler for 100kHz */ P6->SEL0 |= 0x30; /* P6.5, P6.4 for UCB1 */ P6->SEL1 &= ~0x30; EUSCI_B1->CTLW0 &= ~1; /* enable UCB1 after config */ } /* Write a single byte at memAddr * write: S-(slaveAddr+w)-ACK-memAddr-ACK-data-ACK-P */ int I2C1_byteWrite(int slaveAddr, unsigned char memAddr, unsigned char data) { EUSCI_B1->I2CSA = slaveAddr; /* setup slave address */ EUSCI_B1->CTLW0 |= 0x0010; /* enable transmitter */ EUSCI_B1->CTLW0 |= 0x0002; /* generate START and send slave address */ while((EUSCI_B1->CTLW0 & 2)); /* wait until slave address is sent */ EUSCI_B1->TXBUF = memAddr; /* send memory address to slave */ while(!(EUSCI_B1->IFG & 2)); /* wait till it's ready to transmit */ EUSCI_B1->TXBUF = data; /* send data to slave */ while(!(EUSCI_B1->IFG & 2)); /* wait till last transmit is done */ EUSCI_B1->CTLW0 |= 0x0004; /* send STOP */ while(EUSCI_B1->CTLW0 & 4) ; /* wait until STOP is sent */ return 0; } const static char init_seq[] = { 0xae, // turn off oled panel 0x00, // set low column address 0x10, // set high column address 0x40, // set start line address 0x20, 0x02, // page addressing mode 0xc8, // top-down segment (4th quadrant) 0x81, // set contrast control register 0xcf, 0xa1, // set segment re-map 95 to 0 0xa6, // set normal display 0xa8, // set multiplex ratio(1 to 64) 0x3f, // 1/64 duty 0xd3, // set display offset 0x00, // not offset 0xd5, // set display clock divide ratio/oscillator frequency 0x80, // set divide ratio 0xd9, // set pre-charge period 0xf1, 0xda, // set com pins hardware configuration 0x12, 0xdb, // set vcomh 0x40, 0x8d, // set Charge Pump enable/disable 0x14, // set(0x10) disable 0xaf // turn on oled panel }; void SSD1306_init(void) { int i; delayMs(100); for (i = 0; i < sizeof(init_seq); i++) SSD1306_command(init_seq[i]); } void SSD1306_data(char data) { I2C1_byteWrite(SLAVE_ADDR, 0xC0, data); } void SSD1306_command(char command) { I2C1_byteWrite(SLAVE_ADDR, 0x80, command); }