1. 程式人生 > >瘋狂微控制器--用C++寫STM32程式-OLED

瘋狂微控制器--用C++寫STM32程式-OLED

第一次見到OLED就是在MP3播放器上,那時只有高階大氣上檔次的機器才用OLED,所以後來對使用OLED的裝置總有一種高貴的感覺.
今天就來玩一玩OLED

型號:PG9639TLBE,
驅動IC:SSD1306
驅動方式:模擬SPI方式,
OLED介面引腳:SCLK,SDIN,CS_N,CMD
SCLK:序列時針訊號
SDIN:序列資料訊號
CS_N:片選
CMD:命令/資料選擇


型號:QG-2864KLBLG22
驅動IC:SH1106
驅動方式:模擬SPI方式,
OLED介面引腳:SCLK,SDIN,CS_N,CMD
SCLK:序列時針訊號
SDIN:序列資料訊號
CS_N:片選
CMD:命令/資料選擇
 


接著建立了一個OLED類
 

//OLED.H
//BY wisepragma
//homepage:http://blog.csdn.net/wisepragma
#pragma once
#include "main.h"
#include "math.h"
#include "font_dot.h"			 
#include "string.h"
//////////////////////////////////////////////////////
///////////////////////////////////////////////////
// 型號:QG-2864KLBLG22
// 驅動IC:SH1106
// 驅動方式:模擬SPI方式,
// OLED介面引腳:SCLK,SDIN,CS_N,CMD
// SCLK:序列時針訊號
// SDIN:序列資料訊號
// CS_N:片選
// CMD:命令/資料選擇
enum  
{
        MAX_PAGE=8,   //7+8*4 ROWS 範圍:0~MAX_PAGE-1
        MAX_COLUMN=128,//96,,//, //解析度:橫向96點  範圍:0~MAX_COLUMN-1   128
        MAX_ROW=64,//39,//,//解析度:縱向39點 範圍:0~MAX_ROW-1   64
        COLUMN_OFFSET_ADDRINC=2,
        CHAR_WIDTH=8,
        CHAR_HEIGHT=16, 
        DEFAULT_BRIGHTNESS=0x14,
        MAX_DELAY_POWERUP=30000
}OLED_CONFIG; 
// // //////////////////////////////////////////
// // 型號:PG9639TLBE,
// // 驅動IC:SSD1306
// // 驅動方式:模擬SPI方式,
// // OLED介面引腳:SCLK,SDIN,CS_N,CMD
// // SCLK:序列時針訊號
// // SDIN:序列資料訊號
// // CS_N:片選
// // CMD:命令/資料選擇
//   enum  
//   {
//  //OLED PG9639TLBE
//  //PAGE0:D1~D7填入,PAGE1~PAGE4:D0~D7;填入方向從上往下
//  //解析度為:96x39 即Xpixel:96 columns Ypixel:5pages=7rows+8*(4page) rows=7+8*4=39 rows
//   MAX_PAGE=5,   //7+8*4 ROWS 範圍:0~MAX_PAGE-1
//   MAX_COLUMN= 96, //, //解析度:橫向96點  範圍:0~MAX_COLUMN-1  96
//   MAX_ROW= 39, //解析度:縱向39點 範圍:0~MAX_ROW-1   39
//    COLUMN_OFFSET_ADDRINC=32,
//   CHAR_WIDTH=8,
//   CHAR_HEIGHT=16, 
//   DEFAULT_BRIGHTNESS=0x14,
//   MAX_DELAY_POWERUP=30000//使用者自己調節,加入上電延時保證可靠顯示
//  }OLED_CONFIG; 
////////////////////////////////////////////////////  
class OLED
{
private:
        enum	 		 
        {
                Charge_Pump_Setting=0x8D,//0x8D,settingbyte [0x10(disable charge pump),0x14(enable charge pump)]
                Set_Contrast_Control=0x81,	//00~0xff
                Entire_Display_On=0xA4,//0xA4 follows RAM,0xA5 ignores RAM
                Entire_Display_Off=0xA5,
                Set_Normal_Display=0xA6,
                Set_Inverse_Display=0xA7,
                Set_Display_On=0xAF,
                Set_Display_Off=0xAE,
                Right_Horizontal_Scroll=0x26,	 //0x26,0x00(DummyByte),StartPage(0~7),interval(0~7),EndPage(0~7),0x00(DummyByte),0xFF(DummyByte)
                Left_Horizontal_Scroll=0x27,	//0x27,0x00(DummyByte),StartPage(0~7),interval(0~7),EndPage(0~7),0x00(DummyByte),0xFF(DummyByte)
                Vertical_And_Right_Horizontal_Scroll=0x29,//0x29,0x00(DummyByte),StartPage(0~7),interval(0~7),EndPage(0~7),VerticalScrollOffset(1~63)
                Vertical_And_Left_Horizontal_Scroll=0x2A, //0x2A,0x00(DummyByte),StartPage(0~7),interval(0~7),EndPage(0~7),VerticalScrollOffset(1~63)
                Deactivate_Scroll=0x2E,//for 0x26,0x27,0x29,0x2A ,RAM NEED TO BE rewritten 
                Activate_Scroll=0x2F,//for 0x26,0x27,0x29,0x2A 
                Set_Vertical_Scroll_Area=0xA3,//p30*0xA3,NoOfRows,VerticalScrollNo
                Set_Memory_Address_Mode=0x20,//0x20,ModeSelect(0, Horizontal Addressing Mode ;1, Vertical Addressing Mode; 2,Page Addressing Mode (default)
                Set_Column_Address=0x21,//0x21,startColumn(0~127),endColumn(0~127) //This command is only for  horizontal or vertical addressing mode.    
                Set_Page_Address=0x22,//0x22,startPage(0~7),endPage(0~7)	    //This command is only for  horizontal or vertical addressing mode. 
                Set_Segment_Remap_ColumnAddress0_Mappedto_SEG0=0xA0,	//default
                Set_Segment_Remap_ColumnAddress0_Mappedto_SEGmax=0xA1,
                Set_Multiplex_Ratio=0xA8,//0xA8,MUXratio(16~64)
                Set_COM_Output_Scan_DirUp=0xC0,		 //default
                Set_COM_Output_Scan_DirDown=0xC8,
                Set_Display_Vertical_Offset=0xD3,//0xD3,Vertical Shift(0~63)
                Set_COMPins_Hardware_Config=0xDA,//p31*config(0x32,0x02,0x12,0x22)
                Set_Display_Clock=0xD5,//p32*0xD5,osc[7:4]|ratio[3:0]
                Set_PreCharge_Period=0xD9,//0xD9,Phase1[3:0]|Phase2[7:4]
                Set_Vcomh_DeselectLevel=0xDB,//0xDB,level[0x00,0x20,0x30]
                NOP=0xE3,
        }OLED_COMMAND; //置頂,否則GRAM[MAX_PAGE][MAX_COLUMN]未定義
        STM32PIN CMD;
        STM32PIN CS_N;
        STM32PIN SCLK;
        STM32PIN SDIN;
        uint8_t GRAM[MAX_PAGE][MAX_COLUMN];
        bool 	m_bSegmentRemapAsAddrInc_fixed;
        bool  m_bflipHorizontal,m_bflipVertical;
        uint8_t m_brightness; 
        uint8_t m_StartColumnAddress;
        //
public: 
        OLED( STM32PIN &p_sclk,STM32PIN &p_sdin,STM32PIN &p_cs,STM32PIN &p_cmd ,uint8_t brightness=DEFAULT_BRIGHTNESS/*0x00(dark)~0xff(light)*/,uint8_t maxpage=8,uint8_t maxcolumn=128 )
        {
                SCLK=p_sclk;
                SDIN=p_sdin;
                CS_N=p_cs;
                CMD=p_cmd; 
                SCLK.reset(GPIO_Mode_Out_PP);
                SDIN.reset(GPIO_Mode_Out_PP);
                CS_N.reset(GPIO_Mode_Out_PP);
                CMD.reset(GPIO_Mode_Out_PP);
                m_brightness=brightness;
                m_bflipHorizontal=false;
                m_bflipVertical=false;
                PowerUp(); 
        }
        ///////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////
        void PowerUp(void)
        {
                for(int i=0;i<MAX_DELAY_POWERUP;i++);	//延時保證可靠顯示		 
                SwitchDisplayOn(false);	 				//0xAE 關閉顯示 		
                //SetMemoryAddressMode(2);			//0x20(0x02預設),地址自增模式,頁模式下PAGE會自動歸0,SH1106 not support,ModeSelect://0, Horizontal Addressing Mode ;//1, Vertical Addressing Mode; //2,Page Addressing Mode (default)
                //SetPageAddressRange(0);
                //SetColumnAddressRange(0,127);
                SetDisplayVerticalOffset(0);	  //0xD3(00)縱向起點行
                SetDisplayStartLine(0);		 			//0x40(0),行偏移
                SetDisplayStartColumn(COLUMN_OFFSET_ADDRINC);//列偏移,sh1106:2 ssd1306:32( addr & 0x0f);/*set lower column address*/(0x10| (addr>>4) & 0x0f);/*set higher column address*/
                FlipHorizontal(false);  	 			//0xA0 or 0xA1	水平翻轉顯示 /*set segment remap*///	startColumn+=32; //magic number,i don't know why//SegmentRemapAsAddrInc(false); 時要加這句
                FlipVertical(false);						//0xC8 or 0xC0( //default)   垂直翻轉顯示 	/*Com scan direction*/	
                //180度轉向顯示FlipVertical(true);			FlipHorizontal(true); 
                //SWSetHV(true,true);軟體翻轉
                EnableChargePump(true);  				//0x8D(0x14),啟用內部電壓泵 Enable Embedded DC/DC Converter 
                SetMultiplexRatio(MAX_ROW-1); 	//0xA8(64d=0x3F)引數近似要顯示的行數 QG-2864KLBLG22(SH1106)-- set multiplex ratio: 1/64 duty//PG9639TLBE(SSD1306)   0xA8(0x27=39D)	 
                SetClockDivideRatio(0x80); 			//0xD5(0x80) Set Clock as 100 Frames/Sec
                SetCOMPinsHardwareConfig(0x12);	//0xDA(0x12)//?p31*config(0x32,0x02,0x12,0x22)//SH1106:0XDA,0X02隔行掃描
                SetBrightness(m_brightness);		//0x81(0xAF)亮度即Contrast Control,Brightness:0x00(dark)~0xff(light)
                SetPreChargePeriod(0x25);			//0xD9(0x25)//?p32*Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
                SetVcomhDeselectLevel(0x20);	//0xDB(0x20)//00h  ~ 0.65 x Vcc  //20h  ~ 0.77 x Vcc (RESET) //30h  ~ 0.83 x Vcc
                SwitchEntireDisplayOn(true);  	//0xA4 or 0xA5 ,false全亮顯示
                SwitchInverseDisplay(false);  	//0xA6 or 0xA7 反相顯示
                SwitchDisplayOn(true);  				//0xAF	開啟顯示 	
                clear(true/*flush*/);//清屏
        }
        void PowerDown(void)
        {
                sleep();
                for(int i=0;i<300000;i++);		//20ms延時 
        }
        void sleep(void)  //在sleep狀態下還是能寫入東西的
        {
                SwitchDisplayOn(false);	 		//AE
                EnableChargePump(false);  		//8D(10) Enable Embedded DC/DC Converter 
        }
        void wake(void)
        {
                EnableChargePump(true);  		//8D(14) Enable Embedded DC/DC Converter 
                SwitchDisplayOn(true);  		//AF
        }
        // **************configuation functions**********************************=
        void SetMemoryAddressMode(uint8_t mode=0x02)	
        {  
                //ModeSelect SH1106不支援
                //0, Horizontal Addressing Mode ;	//寫入資料,column 自增到末尾(MAX_COLUMN-1),[column回0,page自增,到末尾(MAX_PAGE-1)回0	  ]
                //1, Vertical Addressing Mode; 	   // 寫入資料,page自增,到末尾(MAX_PAGE-1)[page回0,column 自增到末尾(MAX_COLUMN-1),回0 ]
                //2,Page Addressing Mode (default)	  //page不變,寫入資料,column自增,到末尾(MAX_PAGE-1)後回0
                WR1BCmd( Set_Memory_Address_Mode );
                WR1BCmd( mode );  	  
        }
        void FlipHorizontal(bool bOn=true)
        {
                m_bSegmentRemapAsAddrInc_fixed=bOn;	 
                WR1BCmd( bOn? Set_Segment_Remap_ColumnAddress0_Mappedto_SEG0:Set_Segment_Remap_ColumnAddress0_Mappedto_SEGmax);
        }
        void FlipVertical(bool bOn=true)
        {
                WR1BCmd( bOn? 	Set_COM_Output_Scan_DirUp:  Set_COM_Output_Scan_DirDown);
        }  	
        void SetStartPage(uint8_t page=0)	 //頁模式下,設定起始頁
        {
                WR1BCmd( 0xB0 | (page&0x0F) );
        }		
        void SetDisplayStartLine(uint8_t ixLine=0)
        {
                WR1BCmd(0x40 | ixLine); //ixLine:0~63
        }	
        void SetDisplayStartColumn(uint8_t ColumnAddress=0)//SH1106,X軸偏移-2,ssd1306 x軸偏移-32
        {		
                m_StartColumnAddress=(0<ColumnAddress) && ( ColumnAddress< MAX_COLUMN)?ColumnAddress:0;
        }
        void SetStartColumn(uint8_t ColumnAddress=0)	//頁模式下,設定起始列
        {
                //SH1106,X軸偏移-2,ssd1306 x軸偏移-32
                ColumnAddress+=m_bSegmentRemapAsAddrInc_fixed?0:m_StartColumnAddress;
                if( ColumnAddress >= MAX_COLUMN ) return;
                WR1BCmd(0x0f & 	ColumnAddress );				//Set Lower Column (00H - 0FH) 
                WR1BCmd(0x0f & (ColumnAddress>>4) |	0x10 );	//Set Higher Column  (10H - 1FH) 	
        }
        uint8_t GetBrightness(void)
        {
                return 	 m_brightness;
        }
        void light(int8_t dlight)
        {
                m_brightness+=dlight;
                SetBrightness(m_brightness);
        }
        void SetBrightness(uint8_t light=0x10) //亮度 Brightness:0x00(dark)~0xff(light)	  
        {
                m_brightness=light;
                WR1BCmd( Set_Contrast_Control );
                WR1BCmd( light );
        }
        //___________________________________________________________________________________________
        void EnableChargePump( bool bEnable=true)
        { 
                //0x8D,settingbyte [0x10(disable charge pump,default),0x14(enable charge pump)]
                WR1BCmd( Charge_Pump_Setting );	//someone use(0xad);/*set charge pump enable*/ 
                WR1BCmd( bEnable? 0x14: 0x10);
        }  
        void SetVppLevel(uint8_t level)//這個也可以調節亮度SH1106
        {
                WR1BCmd( 0x30|(level&0x03) );/*0X30---0X33 set VPP 9V*/
        }
        void SwitchEntireDisplayOn(bool bOn=false)
        {
                WR1BCmd( bOn ? Entire_Display_On:Entire_Display_Off );
        }
        void SwitchInverseDisplay(bool bOn=false)
        {
                WR1BCmd( bOn ? Set_Inverse_Display:Set_Normal_Display );
        }  	
        void SetMultiplexRatio(uint8_t MUXratio=0x3F)
        {
                WR1BCmd(Set_Multiplex_Ratio);
                WR1BCmd( MUXratio );
        } 	
        void SwitchDisplayOn(bool bOn=false)
        {
                WR1BCmd( bOn ? Set_Display_On:Set_Display_Off );
        }
        void SetDisplayVerticalOffset(uint8_t offset)
        {
                WR1BCmd(Set_Display_Vertical_Offset);
                WR1BCmd( offset );
        }
        //2 FUNC FOR Set_Display_Clock
        void SetClockDivideRatio(uint8_t osc,uint8_t ratio)
        {
                WR1BCmd(Set_Display_Clock);
                WR1BCmd ( ( osc & 0xf0 )|(ratio & 0x0f) );
        }
        void SetClockDivideRatio(uint8_t oscratio)
        {
                WR1BCmd(Set_Display_Clock);
                WR1BCmd( oscratio );
        }  	
        void SetPreChargePeriod(uint8_t phase=0x25)
        {
                WR1BCmd(Set_PreCharge_Period); 
                WR1BCmd(phase);
        } 
        void SetCOMPinsHardwareConfig (uint8_t config)//sh1106只支援0xda,0x02或0XDA,0X12
        {
                WR1BCmd( Set_COMPins_Hardware_Config );
                WR1BCmd( config );
        }		
        void SetVcomhDeselectLevel(uint8_t  level=0x12)
        {  
                WR1BCmd(Set_Vcomh_DeselectLevel); 
                WR1BCmd(level);
        } 	
        //++++++++++++++useless functions+++++++++++++++++++++++++++++++++++
        void Nop(void)
        {
                WR1BCmd(NOP);
        }
        void ActivateScroll(void)
        {
                WR1BCmd( Activate_Scroll );
        }
        void DeactivateScroll(void)
        {
                WR1BCmd( Deactivate_Scroll );
        }
        void SetColumnAddressRange(uint8_t startColumn,uint8_t endColumn) //橫/豎模式下使用,設定列範圍 column:0~127
        {	 
                WR1BCmd(Set_Column_Address);
                WR1BCmd(  startColumn );	//default:0
                WR1BCmd(  endColumn  );		//default:127		
        }
        void SetPageAddressRange(uint8_t startPage=0,uint8_t endPage=MAX_PAGE-1)	 //橫/豎模式下使用,設定頁範圍 Page:0~7
        {	////This command is only for  horizontal or vertical addressing mode.  
                WR1BCmd(Set_Page_Address);
                WR1BCmd(startPage);	  //default:0
                WR1BCmd(endPage);	  //default:7
        }
        void VerticalRightScroll(uint8_t StartPage,uint8_t EndPage,uint8_t Speed,uint8_t VerticalScrollOffset) 	//斜著,不知作什麼用
        {	  	
                //VerticalScrollOffset(0~63),若取0就等於RightScroll()
                DeactivateScroll();
                WR1BCmd( Vertical_And_Right_Horizontal_Scroll );
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( StartPage );//page(0~7)  y軸方向從上向下分八頁,分別為page0..page7,
                WR1BCmd( Speed );//interval(0~7)
                WR1BCmd( EndPage ); //page(0~7)
                WR1BCmd( VerticalScrollOffset );
                ActivateScroll();
        }
        void VerticalLeftScroll(uint8_t StartPage,uint8_t EndPage,uint8_t Speed,uint8_t VerticalScrollOffset) //斜著,不知作什麼用
        {	
                //VerticalScrollOffset(0~63),若取0就等於LeftScroll()
                DeactivateScroll();
                WR1BCmd( Vertical_And_Left_Horizontal_Scroll );
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( StartPage );//page(0~7)  y軸方向從上向下分八頁,分別為page0..page7,
                WR1BCmd( Speed );//interval(0~7)
                WR1BCmd( EndPage ); //page(0~7)
                WR1BCmd( VerticalScrollOffset );
                ActivateScroll();
        }
        void RightScroll(uint8_t StartPage,uint8_t EndPage,uint8_t Speed )	//page(0~7)   speed(0~7)
        {		
                DeactivateScroll();
                WR1BCmd( Right_Horizontal_Scroll );
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( StartPage );//page(0~7)  y軸方向從上向下分八頁,分別為page0..page7,
                WR1BCmd( Speed );//interval(0~7)
                WR1BCmd( EndPage ); //page(0~7)
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( 0xFF );
                ActivateScroll();
        }
        void LeftScroll(uint8_t StartPage,uint8_t EndPage,uint8_t Speed )
        {
                DeactivateScroll();
                WR1BCmd( Left_Horizontal_Scroll );
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( StartPage );
                WR1BCmd( Speed );//interval(0~7)
                WR1BCmd( EndPage );
                WR1BCmd( 0x00 );//DummyByte
                WR1BCmd( 0xFF );
                ActivateScroll();
        }	
        /// **************useful functions**********************************=
        void fill(uint8_t dat=0xff,bool bFlushAtOnce=true)
        {
                memset(GRAM,dat,sizeof(GRAM));
                if( bFlushAtOnce ) flush();	
        }	   
        void clear(bool bFlushAtOnce=true)
        {
                memset(GRAM,0,sizeof(GRAM));
                if( bFlushAtOnce ) flush();	
        }
        void dot(uint8_t page,uint8_t column,uint8_t byDot)  //不經GRAM直接寫OLED		  
        {	   
                //page:0~4,column:0~95
                //SetDisplayStartLine(0);
                SetStartPage(page);        
                SetStartColumn(column);
                WR1BData(byDot);
        }
        //
        //	void direct_putascii(uint8_t basePage,uint8_t baseColumn,char ch) //不經GRAM直接寫OLED		 
        //	{					    
        //		signed char  iAlpha=ch-0x20;	  //ascii字模從0x20開始
        //		if(	iAlpha<0 || iAlpha>Total_Ascii8x16dot_Font)
        //		{
        //			return;//0~0x19非ASCII符不處理
        //		}
        //	    //按位元組寫入column自增的方式,先畫字模的第一行,再畫第二行 ,(字模是縱向掃描的)
        //		SetStartPage(basePage);		   
        //		SetStartColumn(baseColumn); 	
        //		for(uint8_t i=0;i<=14;i+=2)
        //		{
        //			 WR1BData( Ascii8x16dot[iAlpha][i]);
        //		}
        //		SetStartPage(basePage+1);
        //		SetStartColumn(baseColumn); 
        //		for(uint8_t i=1;i<=15;i+=2)
        //		{
        //			 WR1BData( Ascii8x16dot[iAlpha][i]);
        //		}
        //	}
        //	
        //	void direct_putstr(uint8_t basePage,uint8_t baseColumn, const  char  *str)	  不經GRAM直接寫OLED 
        //	{
        //		int len=strlen(str);
        //		for(int i=0;i<len;i++)	
        //		{				   
        //	
        //			if(baseColumn>MAX_COLUMN-CHAR_WIDTH)
        //			{	
        //				basePage+=2;
        //				baseColumn=0;
        //			}
        //			if(basePage>4)break; 
        //			putascii(basePage,baseColumn,str[i]);
        //			baseColumn+=CHAR_WIDTH;		   
        //		}
        //	}
        void putstr(uint8_t ix,uint8_t iy, const  char  *str,bool bSingleLine=false,bool bFlushAtOnce=false,bool bDot=true )
        {
                int len=strlen(str);
                for(int i=0;i<len;i++)	
                {				   
                        if(ix>MAX_COLUMN-CHAR_WIDTH)
                        {	
                                if(bSingleLine) break;
                                iy+=CHAR_HEIGHT;
                                ix=0;
                        }
                        if(iy>MAX_ROW)break; 
                        putchar(ix,iy,str[i],bDot);
                        ix+=CHAR_WIDTH;		   
                }
                if( bFlushAtOnce ) flush();	
        }
        void lineSrolling(uint8_t y,const char *str,int &istr,int delay=0,bool bLeftScroll=true,bool bFlushAtOnce=false )
        {
                const int MaxStr=strlen(str);
                const int ToatalCharsIn1line= MAX_COLUMN / CHAR_WIDTH;
                char linestr[ToatalCharsIn1line];
                //從str中第istr個字開始取ToatalCharsIn1line個字元裝入linestr
                if( istr>=MaxStr ) istr=0;
                if( istr<0 ) istr=MaxStr-1;		   	
                int ishow=istr;
                for(uint8_t n=0;n<ToatalCharsIn1line;n++)
                {
                        linestr[n]=str[ishow];
                        ishow++;	
                        if(ishow>=MaxStr) ishow=0;
                        if(ishow<0) ishow=MaxStr-1;
                }										
                if(bLeftScroll)
                {
                        istr++;	
                } else 
                {
                        istr--;
                }
                putstr(0,y,linestr,true);
                for(int i=0;i<delay;i++);  
                if( bFlushAtOnce ) flush();	
        }
        ///---------------------------------------------------------
        uint8_t InvertByte(uint8_t dat)//位元組倒置
        {
                return ((dat<<7)&0x80 | 
                        (dat<<5)&0x40 | 
                        (dat<<3)&0x20 | 
                        (dat<<1)&0x10 | 
                        (dat>>1)&0x08 | 
                        (dat>>3)&0x04 | 
                        (dat>>5)&0x02 | 
                        (dat>>7)&0x01 );
        }
        void SWFlipVertical()//GRAM上翻轉上下
        {
                uint8_t tmp;
                for(uint8_t page=0;page<(MAX_PAGE+1)/2;page++)
                {
                        for(uint8_t column=0;column<MAX_COLUMN;column++)
                        { 
                                tmp=InvertByte( GRAM[page][column] );
                                GRAM[page][column]= InvertByte( GRAM[MAX_PAGE-page-1][column] );//下標溢位程式亂跑
                                GRAM[MAX_PAGE-page-1][column]=tmp;
                        }
                }
        }
        void SWFlipHorizontal()//GRAM上翻轉左右
        {
                uint8_t tmp;
                for(uint8_t page=0;page<MAX_PAGE;page++)
                {
                        for(uint8_t column=0;column<=(MAX_COLUMN-1)/2;column++)
                        { 
                                tmp= GRAM[page][column] ;
                                GRAM[page][column]=GRAM[page][MAX_COLUMN-column-1];//下標溢位程式亂跑
                                GRAM[page][MAX_COLUMN-column-1]=tmp;
                        }
                }
        }
        void SWSetHV(bool h,bool v)
        {
                m_bflipHorizontal=h;
                m_bflipVertical=v;
        }
        void flush(void)		//此版本為line mode,sh1106不支援page 改為line mode
        { 
                if(m_bflipHorizontal) SWFlipHorizontal();
                if(m_bflipVertical) SWFlipVertical();			 
                for(uint8_t page=0;page<MAX_PAGE;page++)
                {		
                        SetStartPage(page);//SetPageAddress(page); 
                        SetStartColumn(0);//SetColumnAddress(0);
                        for(uint8_t column=0;column<MAX_COLUMN;column++)
                        {
                                WR1BData(GRAM[page][column]);
                        }
                }	
        }
        void putchar(uint8_t x,uint8_t y,char ch,bool bDot=true)//為加快速度,本函式只刷入GRAM (96,39)
        {
                signed char  iAlpha=ch-0x20;   //ascii字模從0x20開始
                if( iAlpha<0 || iAlpha>Total_Ascii8x16dot_Font)
                {
                        return;//非ASCII符不處理
                }  
                uint8_t imod=0;
                for(uint8_t width=0;width<8;width++)
                {
                        for(int8_t height=0;height<16/8;height++)
                        {
                                for(uint8_t dy=0;dy<=7;dy++)
                                { 
                                        bool dot= (1<<dy) &  Ascii8x16dot[iAlpha][imod] ;
                                        SetPixel(x+width,y+height*8+dy, bDot?dot:!dot  );
                                }
                                imod++; //放的後面從0開始,而非從1開始
                        }
                } 
        }
        void drawicon(uint8_t x,uint8_t y,int ixIcon,bool bFlushAtOnce=false ,bool bDot=true)//bDot=true,有點為亮;bDot=false,有點為暗
        {	  
                if(ixIcon>Total_icon24x24 || ixIcon<0)return;
                uint8_t imod=0;				   //以ICON的長寬為索引,而非以模的元素下標
                for(uint8_t width=0;width<24;width++)
                {
                        for(int8_t height=0;height<24/8;height++)
                        {
                                for(uint8_t dy=0;dy<=7;dy++)
                                { 
                                        bool dot= (1<<dy) &  icon24x24[ixIcon][imod] ;
                                        SetPixel(x+width,y+height*8+dy, bDot?dot:!dot  );
                                        //	 com.printf("x,y=%d,%d,%d\n",x+width,y+height*8+dy, bDot?dot:!dot);
                                }
                                // com.printf("%d,",imod );
                                imod++; //放的後面從0開始,而非從1開始
                        }
                } 
                if(bFlushAtOnce)	flush();
        }
        void rectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2,bool bFlushAtOnce=false ,/*SeriesPort &com,*/bool bDot=true )/*x,0~95;y,0~38*/
        {
                line(x1,y1,x2,y1,false,bDot);
                line(x2,y1,x2,y2,false,bDot);
                line(x2,y2,x1,y2,false,bDot);
                line(x1,y2,x1,y1,false,bDot);
                if(bFlushAtOnce)	flush();
        }
        void circle(uint8_t x0,uint8_t y0,uint8_t r,bool bFlushAtOnce=false,bool bDot=true  )
        {
                for(float beta=0;beta<6.2831853;beta+=0.05)
                {
                        SetPixel(x0+r*cos(beta),y0+r*sin(beta),bDot);
                }
                if(bFlushAtOnce)	flush();
        }
        void line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2,bool bFlushAtOnce=false ,/*SeriesPort &com,*/bool bDot=true )/*x,0~95;y,0~38*/
        {	 //  不能用於畫斜線		
                uint8_t x=x1, y=y1;	
                while(true)
                {		
                        if( x>=MAX_COLUMN|| y>=MAX_ROW  )break;	   
                        SetPixel(x,y,bDot);
                        if( x==x2 && y==y2 ) break;//為了在相等時還能列印那一點
                        if( x<x2 )x++; 		
                        if( x>x2 )x--;	
                        if( y<y2 )y++; 
                        if( y>y2 )y--; 	
                } 	
                if(bFlushAtOnce)	flush();
        }   
        ////********************************************************///////
        void ResetPixel(uint8_t ix,uint8_t iy)//ix,ix中的i代表索引
        {
                SetPixel(ix,iy,false);
        }	  
        void SetPixel(uint8_t ix/*0~95*/,uint8_t iy/*0~38*/,bool bDot=true)//ix,ix中的i代表索引
        {  
                //為加快顯示速度,本函式只刷入GRAM
                //函式說明:在GRAM(x,y)打點,不影響其他點,不重新整理flush();情況下不顯示			
                //  PG9639TLBE,  解析度: ix:0~95  iy:0~38	
                //	QG-2864KLBLG22, 解析度: ix:0~127  iy:0~63	
                //	PG-9639有效點陣分佈如下圖(QG-2864類似,略)
                //////  y //////////////////////////////////////////////////////////////////////////////
                // 	D1	0	x:0................PAGE0....................95	    
                //	D2	1 
                //	D3	2
                //	D4	3
                //	D5	4
                //	D6 	5
                //	D7	6
                // 
                //	D0	7	x:0................PAGE1....................95	
                //	D1	8
                //	D2 	9
                //	D3	10
                //	D4	11
                //	D5	12
                //	D6	13
                //	D7	14
                // 
                //	D0	15	x:0................PAGE2....................95	
                //	D1 	16
                //	D2	17
                //	D3 	18
                //	D4	19
                //	D5	20
                //	D6	21
                //	D7	22
                // 
                //	D0	23	x:0................PAGE3....................95	
                //	D1	24
                //	D2	25
                //	D3	26
                //	D4	27
                //	D5	28
                //	D6	29
                //	D7	30
                // 
                //	D0	31	x:0................PAGE4....................95	
                //	D1	32
                //	D2	33
                //	D3	34
                //	D4	35
                //	D5	36
                //	D6	37
                //	D7	38 [D7不顯示]	 
                ///////////////////////////////////////////////////////////////////////////////////////// 	 
                if( iy>MAX_ROW || ix>MAX_COLUMN  )	return;
                uint8_t page=iy/8;
                uint8_t bitDn=iy%8;
                if(bDot)
                {
                        GRAM[page][ix]|=(1<<bitDn);	
                }else
                {
                        GRAM[page][ix]&=~(1<<bitDn);
                } 
        }
        //************low level function***************************	
        void ChipSelected(void)
        {
                CS_N.low();
        }
        void ChipUnselected(void)
        {
                CS_N.high();
        }
        inline void CmdInput(void)
        {
                CMD.low();
        }
        inline void DataInput(void)
        {
                CMD.high();
        }
        void uDelay(uint8_t t)
        {	
                while(t--);
        }
        void WR1BData(uint8_t dat)
        {		   
                WRByte(dat);
        } 
        void WR1BCmd(uint8_t cmd)
        {
                WRByte(cmd,true);	 
        }    
        void WRByte(uint8_t dat,bool bIsCmd=false)	//寫完一位元組,column會自增
        {
                ChipSelected(); 
                if(bIsCmd) 
                {
                        CmdInput();
                }else  	  
                {
                        DataInput();
                }
                for(uint8_t i=0x80;i>0;i>>=1) //OLED從位元組的高位D7輸入,至到D0 -- SPI模擬
                {
                        SCLK.low();	 
                        SDIN.set(i&dat); 		
                        uDelay(15);
                        SCLK.high();		
                        uDelay(15);	 	 	 	     
                }
                //uDelay(50);
                ChipUnselected(); 
        }				 
        /////////////////////TEST FUNCTION///////////////////////////////////////////
        void test() 
        {	
                for(uint8_t page=0;page<MAX_PAGE;page+=1)
                {			
                        for(uint8_t column=0;column<MAX_COLUMN;column++)
                        {
                                dot(page,column,0x41);
                                for(uint32_t tt=0;tt<100000;tt++);
                        }
                }
        }
        void test0() 
        {	
                for(uint8_t page=0;page<MAX_PAGE;page+=1)
                {			
                        uint8_t bydot=0xff;//,i=0;
                        for(uint8_t column=0;column<MAX_COLUMN;column++)
                        {
                                dot(page,column,bydot--);
                                for(uint32_t tt=0;tt<100000;tt++);
                        }
                }
        }
        void test4() 
        {	
                for(uint8_t page=0;page<MAX_PAGE;page+=1)
                {			
                        uint8_t bydot=0xff; 
                        for(uint8_t column=0;column<MAX_COLUMN;column++)
                        {						 
                                GRAM[page][column]=bydot--;	flush();	for(uint32_t tt=0;tt<10000;tt++);
                        }
                }
        }	
        void test3() 
        {	
                for(uint8_t iy=0;iy<MAX_ROW;iy+=1)
                {			
                        for(uint8_t ix=0;ix<MAX_COLUMN;ix++)
                        {
                                SetPixel(ix,iy,false);
                        }
                }
        }
        void test2() 
        {	
                uint8_t bydot=0x0;//,i=0;
                SetStartPage(0);        
                SetStartColumn(0);
                for(uint32_t z=0;z<MAX_PAGE*MAX_COLUMN;z++) 
                {
                        WR1BData(bydot);
                        ++bydot;
                        for(uint32_t tt=0;tt<10000;tt++);
                }
        }
        // 	void test()//花格
        // 	 {	uint8_t bydot=0xfe,i=0;
        // 			for(uint8_t page=0;page<MAX_PAGE;page++)
        // 			for(uint8_t column=0;column<MAX_COLUMN;column++)
        // 			{
        //  				//dot(page,column,bydot++);
        // 				//dot(page,column,0x01);
        // 				i++;
        // 				if(i>7)i=0;
        // 				dot(page,column,bydot<<i);
        //  
        // 			}
        //  	 }
        // 	void test()//細雨
        // 	 {	uint8_t bydot=1,i=0;
        // 			for(uint8_t page=0;page<MAX_PAGE;page++)
        // 			for(uint8_t column=0;column<MAX_COLUMN;column++)
        // 			{
        //  				//dot(page,column,bydot++);
        // 				//dot(page,column,0x01);
        // 				i++;
        // 				if(i>7)i=0;
        // 				dot(page,column,bydot<<i);
        //  
        // 			}
        //  	 }
};

字元和圖示字模定義如下
//OLED.H
//BY wisepragma
//homepage:http://blog.csdn.net/wisepragma
#pragma once
// !"#$%&'()*+,-./0123456789:;<=>[email protected][\]^_`abcdefghijklmnopqrstuvwxyz{|}~

 const uint8_t Ascii8x16dot[][16]=	//加const 定義在程式碼空間 CHAR_WIDTH*CHAR_HEIGHT=8*16    
  //不加const  Ascii8x16dot                                    0x2000005c   Data        1520  main.o(.data)
  // 加const   Ascii8x16dot                                    0x08001d08   Data        1520  main.o(.constdata)
 
 //字型取模順序12,34四個半位元組,顯示填充順序為13,24
 // 13
 // 24

{ //@BatangChe
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x33,0x00,0x00,0x00,0x00,0x00,0x00,/*"!",1*/
0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x00,0x00,/*""",2*/
0x00,0x04,0x20,0x7C,0xE0,0x07,0x3E,0x04,0x20,0x7C,0xE0,0x07,0x3E,0x04,0x20,0x00,/*"#",3*/
0x00,0x00,0x30,0x08,0x48,0x30,0x84,0x20,0xFE,0x7F,0x84,0x20,0x0C,0x11,0x10,0x0E,/*"$",4*/
0x00,0x00,0x30,0x20,0x48,0x18,0x24,0x06,0x98,0x19,0x68,0x24,0x18,0x12,0x04,0x0C,/*"%",5*/
0x00,0x00,0x00,0x1E,0xB8,0x21,0xC4,0x20,0x24,0x23,0x98,0x1C,0x80,0x27,0x80,0x10,/*"&",6*/
0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"'",7*/
0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x18,0x18,0x04,0x20,0x02,0x40,0x00,0x00,/*"(",8*/
0x00,0x00,0x02,0x40,0x04,0x20,0x18,0x18,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,/*")",9*/
0x00,0x00,0x00,0x00,0x20,0x02,0x40,0x01,0xF0,0x07,0x40,0x01,0x20,0x02,0x00,0x00,/*"*",10*/
0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xF8,0x0F,0x80,0x00,0x80,0x00,0x80,0x00,/*"+",11*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,/*",",12*/
0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,/*"-",13*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,/*".",14*/
0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0xC0,0x00,0x30,0x00,0x0C,0x00,0x00,0x00,/*"/",15*/
0x00,0x00,0xF0,0x0F,0x08,0x10,0x04,0x20,0x04,0x20,0x04,0x20,0x08,0x10,0xF0,0x0F,/*"0",16*/
0x00,0x00,0x00,0x00,0x08,0x20,0x08,0x20,0xFC,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,/*"1",17*/
0x00,0x00,0x30,0x38,0x08,0x24,0x04,0x22,0x04,0x21,0x84,0x20,0x48,0x30,0x30,0x08,/*"2",18*/
0x00,0x00,0x10,0x08,0x08,0x10,0x84,0x20,0x84,0x20,0x84,0x20,0x48,0x11,0x30,0x0E,/*"3",19*/
0x00,0x00,0x00,0x04,0x00,0x07,0xC0,0x04,0x30,0x04,0x08,0x24,0xFC,0x3F,0x00,0x24,/*"4",20*/
0x00,0x00,0xFC,0x19,0x84,0x20,0x44,0x20,0x44,0x20,0x44,0x20,0x84,0x10,0x00,0x0F,/*"5",21*/
0x00,0x00,0xF0,0x0F,0x88,0x10,0x44,0x20,0x44,0x20,0x44,0x20,0x84,0x10,0x18,0x0F,/*"6",22*/
0x00,0x00,0x10,0x00,0x0C,0x00,0x04,0x00,0x04,0x3C,0x84,0x03,0x64,0x00,0x1C,0x00,/*"7",23*/
0x00,0x00,0x30,0x0E,0x48,0x11,0x84,0x20,0x84,0x20,0x84,0x20,0x48,0x11,0x30,0x0E,/*"8",24*/
0x00,0x00,0xF0,0x08,0x08,0x11,0x04,0x22,0x04,0x22,0x04,0x22,0x08,0x11,0xF0,0x0F,/*"9",25*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,/*":",26*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,/*";",27*/
0x00,0x00,0x80,0x00,0x40,0x01,0x40,0x01,0x20,0x02,0x20,0x02,0x10,0x04,0x10,0x04,/*"<",28*/
0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,/*"=",29*/
0x00,0x00,0x10,0x04,0x10,0x04,0x20,0x02,0x20,0x02,0x40,0x01,0x40,0x01,0x80,0x00,/*">",30*/
0x00,0x00,0x18,0x00,0x04,0x00,0x02,0x00,0x02,0x37,0x82,0x00,0x44,0x00,0x38,0x00,/*"?",31*/
0x00,0x00,0xF0,0x1F,0x08,0x20,0xC4,0x47,0x24,0x48,0xE4,0x47,0x08,0x48,0xF0,0x2F,/*"@",32*/
0x00,0x00,0x00,0x20,0x00,0x3F,0xE0,0x24,0x1C,0x04,0xE0,0x24,0x00,0x3F,0x00,0x20,/*"A",33*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x84,0x20,0x84,0x20,0x84,0x20,0x84,0x20,0x78,0x1F,/*"B",34*/
0x00,0x00,0xF0,0x0F,0x08,0x10,0x04,0x20,0x04,0x20,0x04,0x20,0x0C,0x10,0x10,0x0C,/*"C",35*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x04,0x20,0x04,0x20,0x04,0x20,0x08,0x10,0xF0,0x0F,/*"D",36*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x84,0x20,0x84,0x20,0x84,0x20,0xCC,0x31,0x10,0x08,/*"E",37*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x84,0x20,0x84,0x20,0x84,0x00,0xCC,0x01,0x10,0x00,/*"F",38*/
0x00,0x00,0xF0,0x0F,0x08,0x10,0x04,0x20,0x04,0x20,0x08,0x11,0x0C,0x3F,0x10,0x01,/*"G",39*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x84,0x20,0x80,0x00,0x84,0x20,0xFC,0x3F,0x04,0x20,/*"H",40*/
0x00,0x00,0x00,0x00,0x04,0x20,0x04,0x20,0xFC,0x3F,0x04,0x20,0x04,0x20,0x00,0x00,/*"I",41*/
0x00,0x00,0x00,0x18,0x00,0x20,0x04,0x20,0x04,0x20,0xFC,0x1F,0x04,0x00,0x04,0x00,/*"J",42*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x84,0x20,0x40,0x01,0x34,0x26,0x0C,0x38,0x04,0x20,/*"K",43*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x04,0x20,0x00,0x20,0x00,0x20,0x00,0x30,0x00,0x08,/*"L",44*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x70,0x20,0x80,0x03,0x70,0x20,0xFC,0x3F,0x04,0x20,/*"M",45*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x70,0x20,0x80,0x01,0x04,0x0E,0xFC,0x3F,0x04,0x00,/*"N",46*/
0x00,0x00,0xF0,0x0F,0x08,0x10,0x04,0x20,0x04,0x20,0x04,0x20,0x08,0x10,0xF0,0x0F,/*"O",47*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x04,0x21,0x04,0x01,0x04,0x01,0x88,0x00,0x70,0x00,/*"P",48*/
0x00,0x00,0xF0,0x0F,0x08,0x10,0x04,0x28,0x04,0x28,0x04,0x28,0x08,0x30,0xF0,0x4F,/*"Q",49*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x04,0x21,0x04,0x01,0x88,0x02,0x70,0x3C,0x00,0x20,/*"R",50*/
0x00,0x00,0x30,0x08,0x48,0x30,0x84,0x20,0x84,0x20,0x04,0x21,0x0C,0x11,0x10,0x0E,/*"S",51*/
0x00,0x00,0x10,0x00,0x0C,0x00,0x04,0x20,0xFC,0x3F,0x04,0x20,0x0C,0x00,0x10,0x00,/*"T",52*/
0x00,0x00,0x04,0x00,0xFC,0x1F,0x04,0x20,0x00,0x20,0x04,0x20,0xFC,0x1F,0x04,0x00,/*"U",53*/
0x00,0x00,0x04,0x00,0x7C,0x00,0x84,0x07,0x00,0x38,0x84,0x07,0x7C,0x00,0x04,0x00,/*"V",54*/
0x00,0x00,0x04,0x00,0xFC,0x03,0x04,0x3C,0xF0,0x03,0x04,0x3C,0xFC,0x03,0x04,0x00,/*"W",55*/
0x00,0x00,0x04,0x20,0x1C,0x38,0x64,0x26,0x80,0x01,0x64,0x26,0x1C,0x38,0x04,0x20,/*"X",56*/
0x00,0x00,0x04,0x00,0x1C,0x00,0xE4,0x20,0x00,0x3F,0xE4,0x20,0x1C,0x00,0x04,0x00,/*"Y",57*/
0x00,0x00,0x10,0x38,0x0C,0x24,0x04,0x23,0x84,0x20,0x64,0x20,0x1C,0x30,0x04,0x08,/*"Z",58*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x02,0x40,0x02,0x40,0x00,0x00,/*"[",59*/
0x0C,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,/*"\"fixed,60*/
0x00,0x00,0x00,0x00,0x02,0x40,0x02,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,/*"]",61*/
0x00,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x00,0x00,/*"^",62*/
0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,/*"_",63*/
0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"`",64*/
0x00,0x00,0x80,0x1C,0x40,0x22,0x40,0x22,0x40,0x22,0x40,0x12,0x80,0x3F,0x00,0x20,/*"a",65*/
0x00,0x00,0x04,0x00,0xFC,0x3F,0x80,0x10,0x40,0x20,0x40,0x20,0x80,0x10,0x00,0x0F,/*"b",66*/
0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x20,0x40,0x20,0x40,0x20,0x80,0x10,0x00,0x00,/*"c",67*/
0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x20,0x40,0x20,0x84,0x10,0xFC,0x3F,0x00,0x20,/*"d",68*/
0x00,0x00,0x80,0x1F,0x40,0x22,0x40,0x22,0x40,0x22,0x40,0x22,0x80,0x13,0x00,0x00,/*"e",69*/
0x00,0x00,0x40,0x00,0x40,0x20,0xF8,0x3F,0x44,0x20,0x44,0x00,0x08,0x00,0x00,0x00,/*"f",70*/
0x00,0x00,0x00,0x34,0x80,0x4B,0x40,0x4A,0x40,0x4A,0x40,0x4A,0x80,0x49,0x40,0x30,/*"g",71*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x80,0x20,0x40,0x00,0x40,0x20,0x80,0x3F,0x00,0x20,/*"h",72*/
0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0xCC,0x3F,0x00,0x20,0x00,0x00,0x00,0x00,/*"i",73*/
0x00,0x00,0x00,0x20,0x00,0x40,0x40,0x40,0xCC,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,/*"j",74*/
0x00,0x00,0x04,0x20,0xFC,0x3F,0x00,0x22,0x40,0x05,0xC0,0x28,0x40,0x30,0x00,0x20,/*"k",75*/
0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,0xFC,0x3F,0x00,0x20,0x00,0x00,0x00,0x00,/*"l",76*/
0x80,0x20,0xC0,0x3F,0x80,0x20,0x40,0x00,0x80,0x3F,0x40,0x00,0x40,0x20,0x80,0x3F,/*"m",77*/
0x00,0x00,0x80,0x20,0xC0,0x3F,0x80,0x20,0x40,0x00,0x40,0x20,0x80,0x3F,0x00,0x20,/*"n",78*/
0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x20,0x40,0x20,0x40,0x20,0x80,0x10,0x00,0x0F,/*"o",79*/
0x00,0x00,0x40,0x40,0xC0,0x7F,0x80,0x48,0x40,0x10,0x40,0x10,0x80,0x08,0x00,0x07,/*"p",80*/
0x00,0x00,0x00,0x07,0x80,0x08,0x40,0x10,0x40,0x10,0x80,0x48,0xC0,0x7F,0x40,0x40,/*"q",81*/
0x00,0x00,0x00,0x00,0x40,0x20,0xC0,0x3F,0x80,0x20,0x40,0x00,0x40,0x00,0x00,0x00,/*"r",82*/
0x00,0x00,0x80,0x09,0x40,0x32,0x40,0x22,0x40,0x24,0xC0,0x24,0x00,0x19,0x00,0x00,/*"s",83*/
0x00,0x00,0x40,0x00,0x40,0x00,0xF8,0x1F,0x40,0x20,0x40,0x20,0x00,0x10,0x00,0x00,/*"t",84*/
0x00,0x00,0x40,0x00,0xC0,0x1F,0x00,0x20,0x00,0x20,0x00,0x20,0x40,0x10,0xC0,0x3F,/*"u",85*/
0x00,0x00,0x40,0x00,0xC0,0x01,0x40,0x0E,0x00,0x30,0x40,0x0E,0xC0,0x01,0x40,0x00,/*"v",86*/
0x00,0x00,0x40,0x00,0xC0,0x07,0x40,0x38,0x00,0x06,0x40,0x38,0xC0,0x07,0x40,0x00,/*"w",87*/
0x00,0x00,0x40,0x20,0xC0,0x30,0x40,0x29,0x00,0x06,0x40,0x29,0xC0,0x30,0x40,0x20,/*"x",88*/
0x00,0x00,0x40,0x60,0xC0,0x41,0x40,0x26,0x00,0x18,0x40,0x06,0xC0,0x01,0x40,0x00,/*"y",89*/
0x00,0x00,0x00,0x31,0xC0,0x28,0x40,0x24,0x40,0x22,0x40,0x21,0xC0,0x30,0x40,0x08,/*"z",90*/
0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x7C,0x3F,0x02,0x40,0x02,0x40,0x00,0x00,/*"{",91*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,/*"|",92*/
0x00,0x00,0x02,0x40,0x02,0x40,0x7C,0x3F,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,/*"}",93*/
0x00,0x00,0x00,0x01,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x01,0x00,0x01,0x80,0x00,/*"~",94*/
};

const uint8_t icon24x24[][3*24]=
{
//clear(0),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//bluetooth_black(1),
0x00,0x7E,0x00,0xC0,0xFF,0x03,0xE0,0xFF,0x0F,0xF8,0xFF,0x1F,0xD8,0xFF,0x1B,0xBC,0xFF,0x3D,0x7E,0xFF,0x7E,0xFE,0x7E,0x7F,
0xFF,0xBD,0xFF,0xFF,0xDB,0xFF,0x01,0x00,0x80,0xFD,0xE7,0xBF,0xFB,0xDB,0x9F,0xF6,0xBD,0x6F,0xEE,0x7E,0x77,0x5C,0xFF,0x3A,
0xB8,0xFF,0x1D,0xF8,0xFF,0x1F,0xE0,0xFF,0x07,0xC0,0xFF,0x03,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//bluetooth white(2),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x20,0x00,0x04,0x40,0x00,0x02,0x80,0x00,0x01,0x00,0x81,0x00,
0x00,0x42,0x00,0x00,0x24,0x00,0xFF,0xFF,0xFF,0x02,0x18,0x40,0x04,0x24,0x20,0x08,0x42,0x10,0x10,0x81,0x08,0xA0,0x00,0x05,
0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//brightness(3),
0x00,0x10,0x00,0x04,0x10,0x20,0x08,0x10,0x10,0x10,0x00,0x08,0x20,0x3C,0x04,0x00,0xC3,0x00,0x80,0x00,0x01,0x40,0x00,0x02,
0x40,0x00,0x02,0x20,0x00,0x04,0x20,0x00,0x04,0x2F,0x00,0xF4,0x20,0x00,0x04,0x20,0x00,0x04,0x40,0x00,0x02,0x40,0x00,0x02,
0x80,0x00,0x01,0x00,0xC3,0x00,0x10,0x3C,0x04,0x08,0x00,0x08,0x04,0x10,0x10,0x02,0x10,0x20,0x00,0x10,0x00,0x00,0x00,0x00, 
//hand(4),
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x09,0x00,0x00,0x31,0x00,0x00,0xC2,0x00,0x00,0x02,0x03,0x00,0x04,0x0C,0xFE,0x1F,0xF8,
0x01,0x00,0x80,0x01,0x00,0x80,0xFE,0x03,0x80,0x30,0x00,0x80,0x10,0x00,0x80,0xE0,0x07,0x80,0x60,0x00,0x80,0x20,0x00,0x80,
0xC0,0x0F,0xF0,0x80,0x01,0x1C,0x80,0x01,0x03,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//loudspeaker(5),
0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0x0F,0xF0,0xFF,0x0F,0xF0,0xFF,0x0F,0xF0,0xFF,0x0F,0xF0,0xFF,0x0F,0xF0,0xFF,0x0F,
0xF0,0xFF,0x0F,0x10,0x00,0x08,0x08,0x00,0x10,0x04,0x00,0x20,0x02,0x00,0x40,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//music(6),
0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x7C,0xE0,0xFF,0x3F,0x20,0x00,0x00,0x10,0x00,0x00,
0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x0E,0x04,0x00,0x1F,
0x04,0x00,0x1F,0x04,0x00,0x1F,0xFC,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
//paper(7),
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x7F,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,
0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0x02,0x00,0x40,0xFE,0x03,0x40,0x04,0x02,0x40,
0x08,0x02,0x40,0x10,0x02,0x40,0x20,0x02,0x40,0x40,0x02,0x40,0x80,0x02,0x40,0x00,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,
//tree(8),
0x00,0x00,0x00,0x00,0x80,0x03,0x30,0x40,0x06,0x48,0x5E,0x04,0xCC,0x61,0x46,0xE2,0xC0,0x43,0x62,0x86,0x40,0x24,0x8F,0x60,
0x9C,0xB8,0x78,0xD0,0xA4,0x7C,0x90,0xFC,0x7E,0x90,0x41,0x7F,0x20,0x21,0x67,0x20,0x9E,0x63,0xC0,0xC0,0x61,0x80,0xFF,0x60,
0xD8,0x48,0x60,0x34,0xE4,0x40,0x54,0x34,0x41,0xD8,0x6C,0x41,0x84,0x98,0x41,0x64,0xF4,0x00,0x18,0x78,0x00,0x00,0x00,0x00,
//USB(9),
0x00,0x1C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00,0x00,0x08,0x00,0x00,0x0E,0x00,0x00,0x0B,0x00,0x80,0x38,0x00,
0x80,0x68,0x00,0x40,0x88,0x00,0x60,0x08,0x01,0xF0,0x08,0x02,0xF0,0x08,0x02,0x60,0x88,0x07,0x00,0x88,0x07,0x00,0x88,0x07,
0x00,0x88,0x07,0x00,0x08,0x00,0x00,0x08,0x00,0x80,0x88,0x00,0x00,0x49,0x00,0x00,0x2A,0x00,0x00,0x1C,0x00,0x00,0x08,0x00, 
//wlan(10),
0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x03,0x00,0x80,0x18,0x00,0x40,0x06,0x00,0x20,0x31,0x00,0xA0,0x08,0x00,0x50,0x04,0x00,
0x50,0x12,0x00,0x50,0xCA,0x01,0x28,0xE5,0x03,0x28,0xF5,0x07,0x28,0xF5,0x07,0x28,0xE5,0x03,0x50,0xCA,0x01,0x50,0x12,0x00,
0x50,0x04,0x00,0xA0,0x08,0x00,0x20,0x31,0x00,0x40,0x06,0x00,0x80,0x18,0x00,0x00,0x03,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,  
//setting(11),
0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x24,0x00,0x10,0xFF,0x08,0xE8,0xFF,0x17,0xC4,0xFF,0x23,0xE8,0xE7,0x17,0xF0,0x81,0x0F,
0xF0,0x00,0x0F,0x78,0x00,0x1E,0x3E,0x00,0x7E,0x3A,0x00,0x5C,0x3A,0x00,0x5C,0x3E,0x00,0x7E,0x78,0x00,0x1E,0xF0,0x00,0x0F,
0xF0,0x81,0x0F,0xE8,0xE7,0x17,0xC4,0xFF,0x23,0xE8,0xFF,0x17,0x10,0xFF,0x08,0x00,0x24,0x00,0x00,0x3C,0x00,0x00,0x00,0x00, 
//setting2(12),
0x00,0x00,0x00,0x80,0x3C,0x01,0x20,0xA5,0x04,0x50,0x7E,0x0A,0x88,0xFF,0x11,0xD0,0xFF,0x0B,0xF0,0xC3,0x4F,0xF4,0x81,0x2F,
0xF8,0x00,0x1F,0x78,0x00,0x1E,0x7E,0x00,0x7E,0x3A,0x00,0x5C,0x3A,0x00,0x5C,0x7E,0x00,0x7E,0x78,0x00,0x1E,0xF8,0x00,0x1F,
0xF8,0x81,0x2F,0xF4,0xE7,0x4F,0xD0,0xFF,0x0B,0x88,0xFF,0x11,0x50,0xFE,0x0A,0x20,0xA5,0x04,0x80,0x3C,0x01,0x00,0x00,0x00, 
//setting3(13),
0x00,0x00,0x00,0x80,0x3C,0x01,0x20,0xA5,0x04,0x50,0x7E,0x0A,0x88,0xFF,0x11,0xD0,0xFF,0x0B,0xF0,0xC3,0x4F,0xF4,0x81,0x2F,
0xF8,0x00,0x1F,0x78,0x00,0x1E,0x7E,0x00,0x7E,0x3A,0x00,0x5C,0x3A,0x00,0x5C,0x7E,0x00,0x7E,0x78,0x00,0x1E,0xF8,0x00,0x1F,
0xF8,0x81,0x2F,0xF4,0xE7,0x4F,0xD0,0xFF,0x0B,0x88,0xFF,0x11,0x50,0xFE,0x0A,0x20,0xA5,0x04,0x80,0x3C,0x01,0x00,0x00,0x00, 
//setting4(14),
0x00,0x18,0x00,0x80,0x18,0x01,0xC0,0xBD,0x03,0x90,0xC3,0x09,0x78,0x00,0x1E,0x30,0x00,0x0C,0x54,0x00,0x2A,0x8E,0x00,0x71,
0x0C,0x81,0x30,0x08,0x42,0x10,0x04,0x3C,0x20,0x0F,0x24,0xE0,0x0F,0x24,0xE0,0x04,0x3C,0x20,0x08,0x42,0x10,0x0C,0x81,0x30,
0x8E,0x00,0x71,0x54,0x00,0x2A,0x30,0x00,0x0C,0x78,0x00,0x1E,0x90,0xC3,0x09,0xC0,0xBD,0x03,0x80,0x18,0x01,0x00,0x18,0x00,
//setting5(15),	  x0.bmp(0)	 
0x00,0x18,0x00,0x80,0x18,0x01,0xC0,0xBD,0x03,0x90,0xCB,0x09,0x78,0x10,0x1E,0x30,0x08,0x0C,0x14,0x10,0x28,0x0E,0x08,0x70,
0x0C,0x10,0x30,0x08,0x08,0x10,0x04,0x3C,0x20,0x5F,0xA5,0xEA,0xAF,0x66,0xF5,0x04,0x3C,0x20,0x08,0x08,0x10,0x0C,0x10,0x30,
0x0E,0x08,0x70,0x14,0x10,0x28,0x30,0x08,0x0C,0x78,0x10,0x1E,0x90,0xCB,0x09,0xC0,0xBD,0x03,0x80,0x18,0x01,0x00,0x18,0x00,
//電池0(16),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x00,0x40,
0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,0x06,0x00,0x40,
0x06,0x00,0x40,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(17),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x00,0x58,
0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,0x06,0x00,0x58,
0x06,0x00,0x58,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(18),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x00,0x5B,
0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,
0x06,0x00,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(19),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x00,0x5B,
0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,0x06,0x00,0x5B,
0x06,0x00,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(20),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x60,0x5B,
0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,0x06,0x60,0x5B,
0x06,0x60,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(21),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x06,0x6C,0x5B,
0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,0x06,0x6C,0x5B,
0x06,0x6C,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(22),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0x86,0x6D,0x5B,
0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,0x86,0x6D,0x5B,
0x86,0x6D,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//電池0(23),
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x04,0x00,0x40,0xB6,0x6D,0x5B,
0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,0xB6,0x6D,0x5B,
0xB6,0x6D,0x5B,0x04,0x00,0x40,0xFC,0xFF,0x7F,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
  											   
const int Total_icon24x24=sizeof(icon24x24)/sizeof(icon24x24[0]);//[ERROR]	sizeof(icon24x24)/sizeof(icon24x24[0][3*24]);
const int Total_Ascii8x16dot_Font=sizeof(Ascii8x16dot)/sizeof(Ascii8x16dot[0]);	 //[ERROR]sizeof(Ascii8x16dot)/sizeof(Ascii8x16dot[0][16]);	

使用PG9639TLBE的OLED_CONFIG,測試程式碼
 	enum	 
 	{
	//OLED PG9639TLBE
	//PAGE0:D1~D7填入,PAGE1~PAGE4:D0~D7;填入方向從上往下
	//解析度為:96x39 即Xpixel:96 columns Ypixel:5pages=7rows+8*(4page) rows=7+8*4=39 rows
		MAX_PAGE=5,	  //7+8*4 ROWS 範圍:0~MAX_PAGE-1
		MAX_COLUMN= 96, //, //解析度:橫向96點  範圍:0~MAX_COLUMN-1  96
		MAX_ROW= 39, //解析度:縱向39點 範圍:0~MAX_ROW-1   39
 		COLUMN_OFFSET_ADDRINC=32,
		CHAR_WIDTH=8,
		CHAR_HEIGHT=16,	
		DEFAULT_BRIGHTNESS=0x14,
		MAX_DELAY_POWERUP=30000//使用者自己調節,加入上電延時保證可靠顯示
	}OLED_CONFIG;	

//MAIN.CPP
#include "stm32f10x.h"
#include "stm32pin.h"
#include "oled.h"

void  test_oled(OLED &oledx)
{
		oledx.drawicon(0,0,4,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(24,0,6,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(48,0,14,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(72,0,8,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.putstr(0,24, "wisepragma:)",true/*bSingleLine*/,true/*bFlushAtOnce*/,false/*bDot*/ );
}


int main()
{
		STM32PIN sclk(PC,8);
		STM32PIN sdin(PA,8);
		STM32PIN ncs(PE,6);
		STM32PIN cmd(PC,9); 
		OLED oled(sclk,sdin,ncs,cmd,0);
 
		test_oled(oled);
		while(true);
}





使用QG-2864KLBLG22的測試程式碼

enum 
{
        MAX_PAGE=8, 
        MAX_COLUMN=128, 
        MAX_ROW=64, 
        COLUMN_OFFSET_ADDRINC=2,
        CHAR_WIDTH=8,
        CHAR_HEIGHT=16,
        DEFAULT_BRIGHTNESS=0x14,
        MAX_DELAY_POWERUP=30000
}OLED_CONFIG;

//MAIN.CPP
//BY wisepragma
//homepage:http://blog.csdn.net/wisepragma
#include "stm32f10x.h"
#include "stm32pin.h"
#include "oled.h"

void  test_oled(OLED &oledx)
{
		oledx.drawicon(0,0,4,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(24,0,6,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(48,0,14,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.drawicon(72,0,8,false/*bFlushAtOnce*/,true/*bDot*/);  
		oledx.putstr(0,24, "wisepragma:)",true/*bSingleLine*/,true/*bFlushAtOnce*/,false/*bDot*/ );
}

	//區域性定義下面text堆疊不夠黑屏
	const  char text[]="[START][In the east there is a shark which is larger than all other fish. It changes into a bird whose winds are like clouds filling the sky. When this bird moves across the land, it brings a message from Corporate Headquarters. This message it drops into the midst of the program- mers, like a seagull making its mark upon the beach. Then the bird mounts on the wind and, with the blue sky at its back, returns home. The novice programmer stares in wonder at the bird, for he understands it not. The average programmer dreads the coming of the bird, for he fears its message. The master programmer continues to work at his terminal, for he does not know that the bird has come and gone.When you have learned to snatch the error code from the trap frame, it will be time for you to leave.[The highest sounds are the hardest to hear. Going forward is a way to retreat.Greater talent shows itself late in life. Even a perfect program still has bugs.Grand Master Turing once dreamed that he was a machine. When he awoke he exclaimed: \"I don't know whether I am Turing dreaming that I am a machine, or a machine dreaming that I am Turing!\"][END]";
	const  char homepage[]="HOME PAGE:  ^_^   http://blog.csdn.net/wisepragma  ";
 
	void OLED_IconTextRolling_loop(OLED &oledx)
	{
		int  cnt=0;//滾動索引 
		int iScroll[3]={0};//滾動索引 
		int icon[5]={1,14,8,16,4};//滾動索引 
		bool bop=false;
		oledx.fill();
	 	while(true) 
		 {	

				if(iScroll[0]%50==0)bop=!bop; 					 
				oledx .drawicon(0,0,icon[0],false/*bFlushAtOnce*/,bop/*bDot*/);	  					
				oledx .drawicon(24,0,icon[1],false/*bFlushAtOnce*/,bop/*bDot*/);	   
				oledx .drawicon(48,0,icon[2],false/*bFlushAtOnce*/,bop/*bDot*/);		  		
				oledx .drawicon(72,0,icon[3],false/*bFlushAtOnce*/,bop/*bDot*/);   					  
				oledx .drawicon(100,0,icon[4],false/*bFlushAtOnce*/,!bop/*bDot*/);   					  
				icon[3]++;if(icon[3]>23)icon[3]=16; 
				icon[1]++;if(icon[1]>15)icon[1]=14;
				cnt++;
				if(cnt>30)
				{ 
					cnt=0;
					icon[0]++;
					if(icon[0]>10)icon[0]=1;
				}
				icon[2]=(icon[2]==8)?0:8;
				oledx.lineSrolling(26,homepage,iScroll[0],0/*delay*/,false/*bLeftScroll*/,false/*bFlushAtOnce*/);		
				oledx.lineSrolling(45,text,iScroll[1],0/*delay*/,true/*bLeftScroll*/,true/*bFlushAtOnce*/);		
				for(uint32_t t=0;t<1000000;t++);
		}
	}

int main()
{
		STM32PIN sclk(PC,8);
		STM32PIN sdin(PA,8);
		STM32PIN ncs(PE,6);
		STM32PIN cmd(PC,9); 
		OLED oled(sclk,sdin,ncs,cmd,0);
		OLED_IconTextRolling_loop(oled);
		//test_oled(oled);
		//while(true);
}


使用模擬時序的好處就是,可以使用任意的GPIO引腳驅動OLED

完整工程檔案


相關推薦

瘋狂微控制器--C++STM32程式-OLED

第一次見到OLED就是在MP3播放器上,那時只有高階大氣上檔次的機器才用OLED,所以後來對使用OLED的裝置總有一種高貴的感覺. 今天就來玩一玩OLED 型號:PG9639TLBE, 驅動IC:SSD1306 驅動方式:模擬SPI方式, OLED介面引腳:SCLK,SDI

瘋狂微控制器--C++STM32程式-STM32PIN

現微控制器已經白菜價了,可用的資源也不斷豐富起來.有一天我突發奇想,用C++寫微控制器不是更方便.(相信很多人有類似的想法,不過在網上找到的參考資料也太少了) 話說很多編譯器本身是支援C++,大部分人認為C++效率C低,我想說的是當年Android剛出來的時候,也受到了很多

C++開發STM32程式

今天這篇文章有點複雜,大家要注意一點看啦! 我們知道KEIL是支援C++的,網上一搜索也能找到一些使用C++的方法,無非是在Keil裡的options->C/C++->Misc Controls裡新增—cpp,如果要支援c++11,還需要指定—cpp11。事實上

C++ STM32 程式設計 005 c++編寫STM32程式的準備

        由於我們使用的是 ARM 的工具鏈 是gcc的,所以,我們大可以用c++來編寫程式,無論是 c++99 或c++11 還是 c++14,都是可以的。另外在 HAL 庫中,幾乎每個 .h標頭檔案都有這種巨集 #ifdef __cplusplu

C++MTP程式遇到的知識

1、C++ string類的方法 string 函式列表 函式名   描述 begin     得到指向字串開頭的Iterator end 得到指向字串結尾的Iterator rbegin 得到指向反向字串開頭的Iterator rend 得到指向反向字串結尾的Itera

C一個UDP傳送和接收程式

1、UDP網路程式設計主要流程 UDP協議的程式設計框架,客戶端和伺服器之間的差別在於伺服器必須使用bind()函式來繫結偵聽的本地UDP埠,而客戶端則可以不進行繫結,直接傳送到伺服器地址的某個埠地址。框圖如圖1.3所示 UDP協議的伺服器端流程 伺服器流程主要分為下述6個部分,即建立套

輸入一行字元分別統計出其中英文字母、空格、數字和其他字元的個數。(c++語言編寫程式)【的第1篇部落格,很高興

#include<stdio.h> int main() { char ch; //定義ch為字元型變數 int a=0,b=0,c=0,d=0; //定義a,b,c,d為整型變數並賦初值 while(scanf("%c",&ch),ch!=’\n’) //輸入字元直到c

【Linux程式設計師福音】在Visual Studio上C++Linux

如今我們正在開發一個新的外掛,一個能夠讓開發者在(以下簡稱 VS ) 上建構能夠在 Linux 上執行 C++ 程式的套件。開發者可以藉由這個外掛將 C++ 程式移轉到 Linux 伺服器、PC 以及移動裝置上,也同時可以藉由這個外掛將這些機器連結至你的 VS 上。 V

QT中呼叫之前已c++好的程式

核心程式已經用c++寫好了,現在在用QT編一個使用者介面,想在這個介面中呼叫這個程式,並且把結果在介面中顯示出來。 程式是用c++寫的,最後出來一個debug資料夾,裡面有一個.exe檔案,這就是要呼叫的程式,是封裝好的。有個要注意的地方是,這個exe檔案 在執行的時候要從

C++使用libcurl做HttpClient(業務觀摩,C++封裝過程式代碼,post和get的數據,最好url編碼,否則+會變成空格)good

com 如果 msvc 是否 out tle source rac 無需 當使用C++做HTTP客戶端時,目前通用的做法就是使用libcurl。其官方網站的地址是http://curl.haxx.se/,該網站主要提供了Curl和libcurl。Curl是命令行

C++的帶模板雙向鏈表

main 報錯 src for out rst 所有 else ddl 1 #ifndef _BLIST_H_ 2 #define _BLIST_H_ 3 4 #include <iostream> 5 6 using n

php調C#的dll包

ext src logs cnblogs class tex .com 技術 png php調用C#寫的dll包

C++程序相比於C到底有哪些不同

mfc tun com docs jsm http w3m mib dbr 1啃腦7暮0殺a斡還http://weibo.com/u/6373334892 腋6趴胖s斷堵c苑寥6gwhttp://shufang.docin.com/jwo55353 7懈5qyof6醇b

sql server中調c#的dll裏的方法

lib null all varchar 什麽什麽 server 調用dll func 雲服務 最近有一項目: 一超市管理系統單機版,運行在WIN2003+SQL2005上,每天超市關門都都會關電腦,現客戶要新加功能,每天關門下班後回家可以上網查看超市管理系統的數據

易語言調C++的DLL

mage clas XP 編程入門 cpp ret 模塊 lsp 錯誤 直接調用會彈出堆棧錯誤的信息,原因是VS默認是__cdcel方式,而易語言是__stdcall,所以調用約定不一致導致堆棧錯誤。 解決方案很簡單,易語言聲明DLL函數時“在庫中對應命令名”函數名前加一個

通過COM組件方式實現java調C#的DLL文件 轉

time rar .exe 字符串 sys 還需 第一個 運行 system 最近一段時間單位在做一個Web項目,工程師用JAVA語言,需要公用人員信息,統一用戶名和密碼,原有的平臺中是用C#語言開發的,在網上查找解決方法,通過JAVA調用C#的DLL文件實現。網上

快速掌握python並行程式

目錄 一、大資料時代的現狀 二、面對挑戰的方法 2.1 平行計算 2.2 改用GPU處理計算密集型程式 3.3 分散式計算 三、用python寫並行程式 3.1 程序與執行緒 3.2 全域性直譯器鎖GIL: 3.3

C#個NBiot串列埠小工具

背景 做嵌入式這行剛剛開始入門基本就是流水燈跟串列埠這些了,一直用別人的工具(在此感謝那些前輩寫的很好用的工具),雖然很好,但是缺少一些定製化的開發。比如最近我在做NBiot的專案,在除錯NB模組的時候就需要手動複製貼上MsgID號碼,十分繁瑣,有時候還會因為超時,不得不從頭來走一遍

C#了個鍵盤記錄器

為了把自己充實起來,閒來沒事,寫了個鍵盤記錄器,主要功能如下:   1.獲取使用者的按鍵資訊,將記錄的資訊以文字的形式儲存起來; 2.讀取檔案內容,已郵件方式傳送到指定郵箱; 3.實現了定時傳送; 4.為了能夠隨系統啟動,所以把程式寫到了服務裡。  

C#一個簡單的進度介面

介面設計如下: 實現類: public partial class FormProgressInfo : Form { public FormProgressInfo(int nMinimum = 0, int nMaximum = 100) { InitializeCom