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();
}
文章写的不好, 如有问题希望大家多多指教