Other Parts Discussed in Thread: MSP430G2553
I say at the beginning, that i'm the beginner :)
I'm trying to write a simple code to control Adfruit Oled 128x64 I2C display. I have problems from the bigining.
My code was based on those examples:
There is olso example for SPI, but it's to complicated fo me to make it wor for I2C.
MSP430 Oled SSd1306 128x64 SPI
And This is begining of my code:
#include <msp430G2553.h>
#include "stdint.h"
#include "ascii_char.h"
#define OLED_CONTROL_BYTE_CMD_SINGLE 0x80
#define OLED_CONTROL_BYTE_CMD_STREAM 0x00
#define OLED_CONTROL_BYTE_DATA_STREAM 0x40
// Fundamental commands (pg.28)
#define OLED_CMD_SET_CONTRAST 0x81 // follow with 0x7F
#define OLED_CMD_DISPLAY_RAM 0xA4
#define OLED_CMD_DISPLAY_ALLON 0xA5
#define OLED_CMD_DISPLAY_NORMAL 0xA6
#define OLED_CMD_DISPLAY_INVERTED 0xA7
#define OLED_CMD_DISPLAY_OFF 0xAE
#define OLED_CMD_DISPLAY_ON 0xAF
// Addressing Command Table (pg.30)
#define OLED_CMD_SET_MEMORY_ADDR_MODE 0x20 // follow with 0x00 = HORZ mode = Behave like a KS108 graphic LCD
#define OLED_CMD_SET_COLUMN_RANGE 0x21 // can be used only in HORZ/VERT mode - follow with 0x00 + 0x7F = COL127
#define OLED_CMD_SET_PAGE_RANGE 0x22 // can be used only in HORZ/VERT mode - follow with 0x00 + 0x07 = PAGE7
// Hardware Config (pg.31)
#define OLED_CMD_SET_DISPLAY_START_LINE 0x40
#define OLED_CMD_SET_SEGMENT_REMAP 0xA1
#define OLED_CMD_SET_MUX_RATIO 0xA8 // follow with 0x3F = 64 MUX
#define OLED_CMD_SET_COM_SCAN_MODE 0xC8
#define OLED_CMD_SET_DISPLAY_OFFSET 0xD3 // follow with 0x00
#define OLED_CMD_SET_COM_PIN_MAP 0xDA // follow with 0x12
// Timing and Driving Scheme (pg.32)
#define OLED_CMD_SET_DISPLAY_CLK_DIV 0xD5 // follow with 0x80
#define OLED_CMD_SET_PRECHARGE 0xD9 // follow with 0x22
#define OLED_CMD_SET_VCOMH_DESELCT 0xDB // follow with 0x30
// Charge Pump (pg.62)
#define OLED_CMD_SET_CHARGE_PUMP 0x8D // follow with 0x14
// NOP
#define OLED_CMD_NOP 0xE3
unsigned char *PTXData;
unsigned char TXByteCtr;
uint16_t i;
uint8_t j,c,s,b;
//const unsigned char init_cmd_array[] = { 0x00,0xAE,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0xD5,0x80,0x8D,0x14,0xD9,0x22,0xDB,0x30,0x20,0x00,0xAF};
const unsigned char init_cmd_array[] = {
OLED_CONTROL_BYTE_CMD_STREAM,
// Follow instructions on pg.64 of the dataSheet for software configuration of the SSD1306
// Turn the Display OFF
OLED_CMD_DISPLAY_OFF,
// Set mux ration tp select max number of rows - 64
OLED_CMD_SET_MUX_RATIO,
0x3F,
// Set the display offset to 0
OLED_CMD_SET_DISPLAY_OFFSET,
0x00,
// Display start line to 0
OLED_CMD_SET_DISPLAY_START_LINE,
// Mirror the x-axis. In case you set it up such that the pins are north.
// Wire.write(0xA0); - in case pins are south - default
OLED_CMD_SET_SEGMENT_REMAP,
// Mirror the y-axis. In case you set it up such that the pins are north.
// Wire.write(0xC0); - in case pins are south - default
OLED_CMD_SET_COM_SCAN_MODE,
// Default - alternate COM pin map
OLED_CMD_SET_COM_PIN_MAP,
0x12,
// set contrast
OLED_CMD_SET_CONTRAST,
0x7F,
// Set display to enable rendering from GDDRAM (Graphic Display Data RAM)
OLED_CMD_DISPLAY_RAM,
// Normal mode!
OLED_CMD_DISPLAY_NORMAL,
// Default oscillator clock
OLED_CMD_SET_DISPLAY_CLK_DIV,
0x80,
// Enable the charge pump
OLED_CMD_SET_CHARGE_PUMP,
0x14,
// Set precharge cycles to high cap type
OLED_CMD_SET_PRECHARGE,
0x22,
// Set the V_COMH deselect volatage to max
OLED_CMD_SET_VCOMH_DESELCT,
0x30,
// Horizonatal addressing mode - same as the KS108 GLCD
OLED_CMD_SET_MEMORY_ADDR_MODE,
0x00,
// Turn the Display ON
OLED_CMD_DISPLAY_ON
};
const unsigned char WriteInit[] = { 0x00, 0x21, 0x00, 0x7F, 0x22, 0x00, 0x07 };
//const unsigned char TX[] = {0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00,0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00};
const unsigned char TX[] = {0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81};
const unsigned char TEST[]= {"This is test "};
unsigned char buffer[100];
unsigned int value;
int strlen(const unsigned char * str)
{
const unsigned char *len;
for (len = str; *len; ++len);
return(len - str);
}
int WriteString(const unsigned char* character) {
unsigned int size = strlen(character);
for (s = 0; s < size; s++) {
for (c = 0; c < 5; c++) {
buffer[b] = ascii_table[(unsigned int) *character][c];
b++;
}
*character++;
if (b == size) {
b = 0;
character = 0;
}
}
return size;
}
void WriteOLED(const unsigned char* data, unsigned char size) {
PTXData = (unsigned char*)data;
TXByteCtr = size;
while (UCB0CTL1 & UCTXSTP);
UCB0CTL1 |= UCTR + UCTXSTT;
}
void OLEDInit() {
WriteOLED(init_cmd_array, sizeof(init_cmd_array));
__delay_cycles(160000);
}
int main(void) {
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1=CALBC1_16MHZ;
DCOCTL=CALDCO_16MHZ;
P1DIR |= BIT0;
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2 |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12;
UCB0BR1 = 0;
UCB0I2CSA = 0x3C; // Slave Address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0TXIE; // Enable TX interrupt
__enable_interrupt();
OLEDInit();
value = (WriteString(TEST)*5);
while (1) {
WriteOLED(WriteInit, sizeof(WriteInit));
for (i = 0; i < 1024; i++) {
WriteOLED((unsigned char*)OLED_CONTROL_BYTE_DATA_STREAM,1);
for (j = 0; j < 16; j++) { //j=1 for text
WriteOLED((unsigned char*)0x81,1);
WriteOLED((unsigned char*)0x02,1);
WriteOLED(TX, sizeof(TX)); //Test array
//WriteOLED(buffer, value); //Text
i++;
}
i--;
}
__delay_cycles(160000);
}
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void) {
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTXData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
}
P1OUT ^= BIT0;
}
"ascii_char.h" is from the third exaple.
This is how it looks like:


So in the first place I want to ask You, why I have to set:
BCSCTL1=CALBC1_16MHZ; DCOCTL=CALDCO_16MHZ;
and
UCB0BR0 = 12;
to make this work.
Which is different than in the first example, to make this work, may someone explain me this?
My second question is...
I have to use
__enable_interrupt();
becouse it also doesn't work with:
__bis_SR_register(CPUOFF + GIE);
and
__bic_SR_register_on_exit(CPUOFF);
Could You explain me that too?
And my last question is...
For example if I want to send some big array to Oled, for exaple with 1024 bytes, the same like
here...
How should I do this? Any ideas? This is MSP430G2553 microcontroller, so I can't put so big array to it memory I guess.
I will appreciate any help and explanations. Greetings from Poland.
