// OLED VOLTMETER. // By moty22.co.uk // PIC12F675 #include <htc.h> // default library #include "oled_font.c" #pragma config WDTE=OFF, MCLRE=OFF, BOREN=OFF, FOSC=INTRCIO, CP=OFF, CPD=OFF //,INTRCIO #define _XTAL_FREQ 4000000 #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0))) #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0))) #define SCL GP4 //pin3 #define SDA GP5 //pin2 //prototypes void command( unsigned char comm); void oled_init(); void clrScreen(); void sendData(unsigned char dataB); void startBit(void); void stopBit(void); void clock(void); void drawChar2(char fig, unsigned char y, unsigned char x); unsigned char addr=0x78; //0b0111 1000 void main(void){ unsigned char d[4]; unsigned int count; // PIC I/O init CMCON = 0b111; //comparator off TRISIO = 0b00001111; //SCL, SDA, input ANSEL = 0b01010100; // 101=Fosc/16, 0100=AN2 GP2 ADCON0 = 0b10001001; //1=right justified, 0,0,0, 10=AN2, 0, 1 =ADC on SCL=1; SDA=1; __delay_ms(500); oled_init(); clrScreen(); // clear screen drawChar2(10, 1, 7); //V drawChar2(12, 1, 2); //. while(1) { GO_DONE = 1; //start ADC while(GO_DONE){}; count=((ADRESH << 8) + ADRESL)*5; // (0 - 1023) * 5 = 0 - 5115 d[0]=(count/1000) %10; //digit on left d[1]=(count/100) %10; d[2]=(count/10) %10; d[3]=count %10; // digit on right drawChar2(d[0], 1, 1); drawChar2(d[1], 1, 3); drawChar2(d[2], 1, 4); drawChar2(d[3], 1, 5); __delay_ms(500); } } //size 2 chars void drawChar2(char fig, unsigned char y, unsigned char x) { unsigned char i, line, btm, top; // command(0x20); // vert mode command(0x01); command(0x21); //col addr command(13 * x); //col start command(13 * x + 9); //col end command(0x22); //0x22 command(y); // Page start command(y+1); // Page end startBit(); sendData(addr); // address sendData(0x40); for (i = 0; i < 5; i++){ line=font[5*(fig)+i]; // font [5 x 5 + i] = 0x27, 0x45, 0x45, 0x45, 0x39 btm=0; top=0; // 128x32 OLED has 4 pages (0-3) starting in column 0 and ending in column 127 // top = top page (page1 y) of 5 columns wide and 8 rows deep // btm = bottom page (page2 y+1) of 5 columns wide and 8 rows deep // when 1 byte is written the pointer moves to the next column automatically // the 4 bits on the left determine the top page column // the 4 bits on the right determine the bottom page column // 0x93 means top page from top downwards white,white,white,black and bottom page white,black,black,white if(line & 8) {top +=192;} // if(line & 4) {top +=48;} // if(line & 2) {top +=12;} // if(line & 1) {top +=3;} // if(line & 128) {btm +=192;} // if(line & 64) {btm +=48;} // if(line & 32) {btm +=12;} // if(line & 16) {btm +=3;} // /* original code // expend char if(line & 64) {btm +=192;} // line & 0100 bottom + 192 if(line & 32) {btm +=48;} // line & 0010 bottom + 48 -> 48 if(line & 16) {btm +=12;} // line & 0001 bottom + 12 if(line & 8) {btm +=3;} // line & 1000 bottom + 3 if(line & 4) {top +=192;} // line & 0100 top + 192 -> 252 if(line & 2) {top +=48;} // line & 0010 top + 48 if(line & 1) {top +=12;} // line & 0001 top + 12 */ sendData(top); //top page (page 1) sendData(btm); // page below top (page 2) sendData(top); // top page, but next column sendData(btm); // bottom page, but next column // this means 1 byte for 2 columns in 2 pages (16 bits) } stopBit(); command(0x20); // horizontal mode command(0x00); } void clrScreen() //fill screen with 0 { unsigned char y, i; for ( y = 0; y < 8; y++ ) { command(0x21); //col addr command(0); //col start command(127); //col end command(0x22); //0x22 command(y); // Page start command(y+1); // Page end startBit(); sendData(addr); // address sendData(0x40); for (i = 0; i < 128; i++){ sendData(0x00); } stopBit(); } } //Software I2C void sendData(unsigned char dataB) { for(unsigned char b=0;b<8;b++){ SDA=(dataB >> (7-b)) % 2; clock(); } TRISIO5=1; //SDA input clock(); __delay_us(5); TRISIO5=0; //SDA output } void clock(void) { __delay_us(1); SCL=1; __delay_us(5); SCL=0; __delay_us(1); } void startBit(void) { SDA=0; __delay_us(5); SCL=0; } void stopBit(void) { SCL=1; __delay_us(5); SDA=1; } void command( unsigned char comm){ startBit(); sendData(addr); // address sendData(0x00); sendData(comm); // command code stopBit(); } void oled_init() { command(0xAE); // DISPLAYOFF command(0x8D); // CHARGEPUMP * command(0x14); //0x14-pump on command(0x20); // MEMORYMODE command(0x0); //0x0=horizontal, 0x01=vertical, 0x02=page command(0xA1); //SEGREMAP * A0/A1=top/bottom command(0xC8); //COMSCANDEC * C0/C8=left/right command(0xDA); // SETCOMPINS * command(0x22); //0x22=4rows, 0x12=8rows command(0x81); // SETCONTRAST command(0xFF); //0x8F //next settings are set by default // command(0xD5); //SETDISPLAYCLOCKDIV // command(0x80); // command(0xA8); // SETMULTIPLEX // command(0x3F); //0x1F // command(0xD3); // SETDISPLAYOFFSET // command(0x0); // command(0x40); // SETSTARTLINE // command(0xD9); // SETPRECHARGE // command(0xF1); // command(0xDB); // SETVCOMDETECT // command(0x40); // command(0xA4); // DISPLAYALLON_RESUME // command(0xA6); // NORMALDISPLAY command(0xAF); //DISPLAYON } // ----oled_font.c----------------------- static const unsigned char font[] = { 0x7E,0xC1,0x81,0x83,0x7E, 0x82,0x83,0xFF,0x80,0x80, 0xC2,0xA1,0x91,0x89,0x46, 0x42,0x81,0x99,0x99,0x7E, 0x18,0x14,0x92,0xFF,0x90, 0xC7,0x89,0x89,0x99,0x70, 0xEE,0x91,0x91,0x91,0x70, 0x01,0xC1,0x31,0x19,0x06, 0x66,0x99,0x99,0x99,0x66, 0x0E,0x91,0x91,0x91,0x7E, 0x0C,0x30,0xC0,0x30,0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,// (space) 0x00,0xC0,0xC0,0xC0,0x00 };