濟南網(wǎng)站設(shè)計建設(shè)公司百度營銷推廣登錄平臺
一、IIC協(xié)議
1、IIC協(xié)議概述
1.1、概述:IIC全稱Inter-Integrated Circuit (集成電路總線) 是由PHILIPS公司在80年代開發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。IIC屬于半雙 工同步通信方式
1.2、特點:簡單性和有效性。 由于接口直接在組件之上,因此IIC總線占用的空間非常小,減少了電路板的空間和芯片管腳的數(shù)量,降 低了互聯(lián)成本??偩€的長度可高達25英尺,并且能夠以10Kbps的最大傳輸速率支持40個組件
多主控(multimastering) 其中任何能夠進行發(fā)送和接收的設(shè)備都可以成為主總線。一個主控能夠控制信號的傳輸和時鐘頻率。當 然,在任何時間點上只能有一個主控。
1.3、構(gòu)成:IIC串行總線一般有兩根信號線,一根是雙向的數(shù)據(jù)線SDA,另一根是時鐘線SCL,其時鐘信號是由主控 器件產(chǎn)生。所有接到IIC總線設(shè)備上的串行數(shù)據(jù)SDA都接到總線的SDA上,各設(shè)備的時鐘線SCL接到總線 的SCL上。對于并聯(lián)在一條總線上的每個IC都有唯一的地址。
?
2、時序分析
IIC總線在傳輸數(shù)據(jù)的過程中一共有三種類型信號,分別為:開始信號、結(jié)束信號和應(yīng)答信號。
起始信號
?
void IIC_Start()
{scl = 0;sda = 1;scl = 1;_nop_();sda = 0;_nop_();
}
終止信號
?
void IIC_Stop()
{sda = 0;scl = 1;_nop_();sda = 1;_nop_();
}
應(yīng)答信號
發(fā)送器每發(fā)送一個字節(jié)(8個bit),就在時鐘脈沖9期間釋放數(shù)據(jù)線,由接收器反饋一個應(yīng)答信號。 應(yīng)答信號為低電平時,規(guī)定為有效應(yīng)答位(ACK,簡稱應(yīng)答位),表示接收器已經(jīng)成功地接收了該字 節(jié); 應(yīng)答信號為高電平時,規(guī)定為非應(yīng)答位(NACK),一般表示接收器接收該字節(jié)沒有成功
?
char IIC_ACK()
{char flag;sda = 1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl = 1;_nop_();flag = sda;_nop_();scl = 0;_nop_();return flag;
}
數(shù)據(jù)發(fā)送
?
void IIC_Send_Byte(char dataSend)
{int i;for(i = 0;i<8;i++){scl = 0;//scl拉低,讓sda做好數(shù)據(jù)準備sda = dataSend & 0x80;//1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl = 1;//scl拉高開始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;
}
}
二、oled屏
1、OLED寫命令
寫命令/數(shù)據(jù)的代碼邏輯思路
1. start()
2. 寫入 b0111 1000 0x78
3. ACK
4. cotrol byte: (0)(0)000000 寫入命令 (0)(1)000000寫入數(shù)據(jù)
5. ACK
6. 寫入指令/數(shù)據(jù)
7. ACK
8. STOP
void Oled_Write_Cmd(char dataCmd)
{
// 1. start()IIC_Start();
// 2. 寫入從機地址 b0111 1000 0x78IIC_Send_Byte(0x78);
// 3. ACKIIC_ACK();
// 4. cotrol byte: (0)(0)000000 寫入命令 (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);
// 5. ACKIIC_ACK();
//6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);
//7. ACKIIC_ACK();
//8. STOPIIC_Stop();
}
void Oled_Write_Data(char dataData)
{
// 1. start()IIC_Start();
// 2. 寫入從機地址 b0111 1000 0x78IIC_Send_Byte(0x78);
// 3. ACKIIC_ACK();
// 4. cotrol byte: (0)(0)000000 寫入命令 (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);
// 5. ACKIIC_ACK();
///6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataData);
//7. ACKIIC_ACK();
//8. STOPIIC_Stop();
}
2、OLED的尋址模式
如何顯示一個點?
有三種尋址模式,分別位頁地址模式,水平地址模式和垂直地址模式,可以通過一下表格進行配置 內(nèi)存管理
?
?頁地址模式
?水平地址模式
?垂直地址模式
?
列地址選擇
?如果寫入0x08(b00001000)會顯示什么呢 ?一個字節(jié)負責一個Page的一列顯示
?三、代碼實現(xiàn)
#include "reg52.h"
#include "intrins.h"sbit scl=P0^1;
sbit sda=P0^3;void IIC_start()
{scl=0;//防止雪花sda=1;scl=1;_nop_();sda=0;_nop_();}
void IIC_stop()
{scl=0;sda=0;scl=1;_nop_();sda=1;_nop_();}char IIC_ACK()
{char flag;sda=1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl=1;_nop_();flag=sda;_nop_();scl=0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i=0;i<8;i++){scl=0;//scl拉低做好數(shù)據(jù)準備sda=dataSend & 0x80; //1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl=1;//scl拉高開始傳數(shù)據(jù)_nop_();scl=0;//發(fā)送完畢拉低_nop_();dataSend= dataSend << 1;}
}void Oled_Write_Data(char dataData)
{//1.startIIC_start();//2.寫入從機地址 0x78IIC_Send_Byte(0x78);//3.ACKIIC_ACK();//4.control byte: 0000 0000 寫入命令 0100 0000 寫入數(shù)據(jù)IIC_Send_Byte(0x40);//5.ACKIIC_ACK();//6.寫入指令或數(shù)據(jù)IIC_Send_Byte(dataData);//7.ACKIIC_ACK();//8.STOPIIC_stop();
}void Oled_Write_Cmd(char dataCmd)
{//1.startIIC_start();//2.寫入從機地址 0x78IIC_Send_Byte(0x78);//3.ACKIIC_ACK();//4.control byte: 0000 0000 寫入命令 0100 0000 寫入數(shù)據(jù)IIC_Send_Byte(0x00);//5.ACKIIC_ACK();//6.寫入指令或數(shù)據(jù)IIC_Send_Byte(dataCmd);//7.ACKIIC_ACK();//8.STOPIIC_stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128 Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel
}void Oled_Clear() //清屏函數(shù)
{int i;int j;for(i=0;i<8;i++){Oled_Write_Cmd(0xB0+ i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j=0;j<128;j++){Oled_Write_Data(0); }}}void Oled_Show_Image(unsigned char *image)//顯示一張圖
{unsigned int i;unsigned int j;for(i=0;i<8;i++){Oled_Write_Cmd(0xB0+ i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j=128*i;j<128 * (i+1);j++){Oled_Write_Data(image[j]);}}}void main()
{//1.OLED初始化Oled_Init();//2.選擇一個位置//2.1確認頁尋址模式Oled_Write_Cmd(0x20);Oled_Write_Cmd(0x02);Oled_Clear();//清屏函數(shù)//顯示一條線Oled_Write_Data(0x08);Oled_Write_Data(0x08);Oled_Write_Data(0x08);Oled_Write_Data(0x08);Oled_Write_Data(0x08);Oled_Write_Data(0x08);Oled_Write_Data(0x08);while(1);//不讓程序退出
}