簡單理解下什麼是IIC
I2C(Inter-Integrated Circuit BUS) 集成電路總線,該總線由NXP(原PHILIPS)公司設計,多用於主控制器和從器件間的主從通訊,在小數據量場合使用,傳輸距離短,任意時刻只能有一個主機等特性。
總線信號 :ide
SDA :串行數據線函數
SCL :串行時鐘字體
總線空閒狀態 :ui
SDA :高電平設計
SCL :高電平code
起始位:SCL爲高電平期間 SDA出現降低沿
終止位:SCL爲高電平期間 SDA出現上升沿
數據傳輸 :SDA的數據在SCL高電平期間被寫入從機。因此SDA的數據變化要發生在SCL低電平期間。
先簡單寫出IIC.h頭文件orm
#ifndef _IIC_H #define _IIC_H #include "msp430f5529.h" //IIC通訊接口引腳輸出宏定義 #define SCL_HIGH P6OUT|=BIT3 //定義引腳6.3爲高電平時的輸出 #define SCL_LOW P6OUT&=~BIT3//定義引腳6.3爲低電平時的輸出 #define SDA_HIGH P6OUT|=BIT4//定義引腳6.4爲高電平時的輸出 #define SDA_LOW P6OUT&=~BIT4//定義引腳6.4爲低電平時的輸出 #define XLevelL 0x00//低位地址 #define XLevelH 0x10//高位地址 #define XLevel ((XLevelH&0x0F)*16+XLevelL) #define Max_Column 128//最大屏幕像素寬度 #define Max_Row 64 //最大屏幕像素寬度 #define Brightness 0xCF //IIC起始地址 #define X_WIDTH 128//屏幕像素寬度 #define Y_WIDTH 64 //屏幕像素高度 void IIC_delayus(unsigned int i); void IIC_ioinit(void);//初始化IIC void IIC_start(void);//開始IIC通訊 void IIC_stop(void);//結束IIC通訊 void IIC_writebyte(unsigned char IIC_byte);//寫字節 void IIC_writecmd(unsigned char IIC_command);//寫命令 void IIC_writedata(unsigned char IIC_data);//寫數據 void LCD_Set_Pos(unsigned char x, unsigned char y);//設置顯示位置 void LCD_CLS(void);//清屏 void LCD_Init(void);//OLED屏初始化 void LCD_ShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char Char_Size);//顯示字符 void LCD_ShowString(unsigned char x,unsigned char y,unsigned char *chr,unsigned char Char_Size);//顯示字符串 void LCD_ShowNum(unsigned char x,unsigned char y,unsigned long num,unsigned char len,unsigned char size2);//顯示數字 unsigned long oled_pow(unsigned char m,unsigned char n);//字符求冪函數 #endif //_IIC_H
#include "IIC.h" #include "font.h" //延時函數延時=4*i void IIC_delayus(unsigned int i) { unsigned int j,k; for(k=0;k<i;k++) for(j=0;j<4;i++); } //IIC初始化函數 void IIC_ioinit() { P6DIR|=BIT1|BIT2|BIT3|BIT4; //配置IIC IO口爲輸出方向 P6REN|=BIT3|BIT4; //配置IIC IO口使能上拉電阻 P6OUT&=~BIT1;//6.1 拉高 P6OUT|=BIT2;//6.2 拉低 } //開始一個IIC通訊 void IIC_start() { //產生信號上升沿 SCL_HIGH;//SCL拉高 SDA_HIGH;//SDA拉高 //接下來產生SDA信號降低沿,注意,這裏SDA必定比SCL先拉低 //IIC_delayus(2); SDA_LOW;//SDA拉低 //IIC_delayus(2); SCL_LOW;//SCL拉低 //主機開始讀寫信號產生完畢 } //中止IIC通訊 void IIC_stop() { SCL_LOW; SDA_LOW; //IIC_delayus(2); //接下來產生SDA信號上升沿,注意,這裏SCL必定比SDA先拉高 SCL_HIGH; SDA_HIGH; //IIC_delayus(2); } //IIC發送一個byte void IIC_writebyte(unsigned char IIC_byte) { unsigned char i; //一個字節8bit所以,循環從0開始到7共8次寫數據 for(i=0;i<8;i++) { if(IIC_byte&0x80) //若是寫滿8字節且不爲0 SDA_HIGH;//拉高SDA信號 else//沒有寫滿8字節 SDA_LOW;//寫入0 SCL_HIGH;//拉高SCL結束一bit的寫 SCL_LOW;//拉低SCL使得SDA可寫 IIC_byte<<=1; //IIC_byte左移一位,故名思意了 //假設IIC_byte數據爲字符c 那麼它的二進制就是01100011寫入寄存器就是 //第一遍循環11000110 //第二遍循環10001100 //第三遍循環00011000 //第四遍循環00110000 //第五遍循環01100000 //第六遍循環11000000 //第七遍循環10000000 //第八遍循環00000000 全爲0拉高SDA } SDA_HIGH;//恢復拉高SDA SCL_HIGH;//恢復拉高SCL SCL_LOW;//拉低SCL等待SDA電平變更 } void IIC_writecmd(unsigned char IIC_command) { IIC_start(); IIC_writebyte(0x78); //Slave address,SA0=0 從機寄存器地址 IIC_writebyte(0x00); //發送指令寫指令 IIC_writebyte(IIC_command);//寫入指令 IIC_stop();//結束IIC通訊 } void IIC_writedata(unsigned char IIC_data) { IIC_start(); IIC_writebyte(0x78); //IIC寫從機起始地址 IIC_writebyte(0x40); //write data寫數據 IIC_writebyte(IIC_data);//寫入字符數據 IIC_stop(); } /**************************LCD 設置座標*******************************/ void LCD_Set_Pos(unsigned char x, unsigned char y) { //OLED寄存器指令集查看OLED芯片手冊 IIC_writecmd(0xb0+y); IIC_writecmd(((x&0xf0)>>4)|0x10); IIC_writecmd((x&0x0f)|0x01); } /***************************LCD復位************************************/ void LCD_CLS(void) { unsigned char y,x; for(y=0;y<8;y++) { IIC_writecmd(0xb0+y); IIC_writecmd(0x01); IIC_writecmd(0x10); for(x=0;x<X_WIDTH;x++) IIC_writedata(0); } } /***************************LCD初始化************************************/ void LCD_Init(void) { IIC_ioinit(); IIC_writecmd(0xAE); //display off IIC_writecmd(0x20); //Set Memory Addressing Mode IIC_writecmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid IIC_writecmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7 IIC_writecmd(0xc8); //Set COM Output Scan Direction IIC_writecmd(0x00);//---set low column address IIC_writecmd(0x10);//---set high column address IIC_writecmd(0x40);//--set start line address IIC_writecmd(0x81);//--set contrast control register IIC_writecmd(0x7f); IIC_writecmd(0xa1);//--set segment re-map 0 to 127 IIC_writecmd(0xa6);//--set normal display IIC_writecmd(0xa8);//--set multiplex ratio(1 to 64) IIC_writecmd(0x3F);// IIC_writecmd(0xa4);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content IIC_writecmd(0xd3);//-set display offset IIC_writecmd(0x00);//-not offset IIC_writecmd(0xd5);//--set display clock divide ratio/oscillator frequency IIC_writecmd(0xf0);//--set divide ratio IIC_writecmd(0xd9);//--set pre-charge period IIC_writecmd(0x22); // IIC_writecmd(0xda);//--set com pins hardware configuration IIC_writecmd(0x12); IIC_writecmd(0xdb);//--set vcomh IIC_writecmd(0x20);//0x20,0.77xVcc IIC_writecmd(0x8d);//--set DC-DC enable IIC_writecmd(0x14);// IIC_writecmd(0xaf);//--turn on oled panel LCD_CLS(); LCD_Set_Pos(0,0); } //在指定位置顯示一個字符,包括部分字符 //x:0~127 //y:0~63 //mode:0,反白顯示;1,正常顯示 //size:選擇字體 16/12 void LCD_ShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char Char_Size) { unsigned char c=0,i=0; c=chr-' ';//獲得偏移後的值 if(x>Max_Column-1)//若是,字符座標大於行最大像素值寫到下一行開始位置 { x=0; y=y+2; } if(Char_Size ==16)//若是字符恰好等於16字符 { LCD_Set_Pos(x,y); for(i=0;i<8;i++) IIC_writedata(F8X16[c*16+i]); LCD_Set_Pos(x,y+1); for(i=0;i<8;i++) IIC_writedata(F8X16[c*16+i+8]); } else //不然寫到下一行 { LCD_Set_Pos(x,y); for(i=0;i<6;i++) IIC_writedata(F6x8[c][i]); } } //顯示一個字符號串 void LCD_ShowString(unsigned char x,unsigned char y,unsigned char *chr,unsigned char Char_Size) { unsigned char j=0; while (chr[j]!='\0')//遍歷字符串,x+8至關於每一個字符間隔8個座標 循環調用顯示字符函數,直到字符串爲空 { LCD_ShowChar(x,y,chr[j],Char_Size); x+=8; if(x>128) { x=0; y+=2; } j++; } } //m^n函數 unsigned long oled_pow(unsigned char m,unsigned char n) { unsigned long result=1; while(n--)result*=m; return result; } //顯示一個數字將數字取模獲取每一位的數字,以字符的形式顯示 //當輸入數字爲9876時座標爲0,0時 //取得每一位數 //第一遍循環 9876%10=987 餘6 6+'0'='6' 座標 x=0 y=0 //第二遍循環 987%10=98 餘7 7+'0'='7‘ 座標 x=0+8=8 y=0 //第三遍循環 98%10=9 餘6 6+'0'='7' 座標 x=8+8=16 y=0 //第四遍循環 9%10=0 餘9 9+'0'='9' 座標 x=16+8=24 y=0 //其餘以此類推 void LCD_ShowNum(unsigned char x,unsigned char y,unsigned long num,unsigned char len,unsigned char size2) { unsigned char t,temp; //unsigned char enshow=0; for(t=0;t<len;t++) { temp=(num/oled_pow(10,len-t-1))%10; LCD_ShowChar(x+(size2/2)*t,y,temp+'0',size2); } }