使用驅動芯片SSD1306的OLED時, 我使用的是I2C通信
在看網上一些代碼時, 發現基本都是每發送一個字節命令/數據, 都會發送信號, 從機地址, 發送完后就立馬發送終止信號, 整個流程像這樣:
起始信號-發送從機地址-控制字節-數據字節-終止信號
發送一個命令/數據相關代碼
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if(mode){Send_Byte(0x40);}
else{Send_Byte(0x00);}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
但是如果初始化要發送很多命令, 或者像需要寫入很多數據時, 就會每次發送完一個命令/數據后, 然后就發送終止信號. 這里以初始化為例.
初始化相關代碼:
void OLED_Init(void)
{
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0xAF,OLED_CMD);
}
這樣大數據的傳輸就相當於大部分無用時間都耗在了發送開始, 發送從機地址和發送結束信號中. 然而我在SSD1306的Datasheet中看到了是可以連續發送數據的
只要將控制字節的Co位從0改成1即可, 就能連續發送
若是發送命令, 控制字節是0x00, 改成0x80;
若是發送數據, 控制字節是0x40, 改成0xC0;
每次發送一個控制字節, 一個數據字節, 再接着發送一個控制字節, 一個數據字節..
附上我自己寫的代碼
發送單個字節
ErrorStatus Send_SingleData(uint8_t Data)
{
SendByte(Data); //發送個控制字節
if( NOACK == WaitAck() ) //從設備不應答
{
I2C_OLED_USART1("從設備沒有應答");
I2C_Stop();
return ERROR;
}
return SUCCESS;
}
發送一個控制字節和一個數據字節
ErrorStatus Send_TwoData(SENDTYPE Type, uint8_t Data)
{
if( ERROR == Send_SingleData(Type) )
return ERROR;
if( ERROR == Send_SingleData(Data) )
return ERROR;
return SUCCESS;
}
初始化相關代碼, 其中ContCOMMAND是0x80;
void I2C_CmdInit(void)
{
I2C_Start();
Send_SingleData(I2C_SLAVE_ADDRESS8);
Send_TwoData(ContCOMMAND,0xAE);// turn off oled panel
Send_TwoData(ContCOMMAND,0x00);// set low column address
Send_TwoData(ContCOMMAND,0x10);// set high column address
Send_TwoData(ContCOMMAND,0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
Send_TwoData(ContCOMMAND,0x81);//--set contrast control register
Send_TwoData(ContCOMMAND,0xCF);// Set SEG Output Current Brightness
Send_TwoData(ContCOMMAND,0xA1);// Set SEG/Column Mapping
Send_TwoData(ContCOMMAND,0xC8);// Set COM/Row Scan Direction
Send_TwoData(ContCOMMAND,0xA6);// set normal display
Send_TwoData(ContCOMMAND,0xA8);// set multiplex ratio(1 to 64)
Send_TwoData(ContCOMMAND,0x3f);// 1/64 duty
Send_TwoData(ContCOMMAND,0xD3);// set display offset Shift Mapping RAM Counter (0x00~0x3F)
Send_TwoData(ContCOMMAND,0x00);// not offset
Send_TwoData(ContCOMMAND,0xd5);// set display clock divide ratio/oscillator frequency
Send_TwoData(ContCOMMAND,0x80);// set divide ratio, Set Clock as 100 Frames/Sec
Send_TwoData(ContCOMMAND,0xD9);// set pre-charge period
Send_TwoData(ContCOMMAND,0xF1);// Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
Send_TwoData(ContCOMMAND,0xDA);// set com pins hardware configuration
Send_TwoData(ContCOMMAND,0x12);
Send_TwoData(ContCOMMAND,0xDB);// set vcomh
Send_TwoData(ContCOMMAND,0x40);// Set VCOM Deselect Level
Send_TwoData(ContCOMMAND,0x20);// Set Page Addressing Mode (0x00/0x01/0x02)
Send_TwoData(ContCOMMAND,0x02);
Send_TwoData(ContCOMMAND,0x8D);// set Charge Pump enable/disable
Send_TwoData(ContCOMMAND,0x14);// set(0x10) disable
Send_TwoData(ContCOMMAND,0xA4);// Disable Entire Display On (0xa4/0xa5)
Send_TwoData(ContCOMMAND,0xA6);// Disable Inverse Display On (0xa6/a7)
Send_TwoData(ContCOMMAND,0xAF);
I2C_Stop();
}
文章寫的不好, 如有問題希望大家多多指教