I2C向SSD1306的OLED連續發送數據


使用驅動芯片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();
}

文章寫的不好, 如有問題希望大家多多指教


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM