简单理解下什么是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); } }