STM32利用I2C驱动SSD1306代码

这篇博客详细介绍了如何使用I2C协议驱动SSD1306 OLED显示屏,包括I2C的开始、停止、发送数据和接收数据的函数实现,并给出了SSD1306的初始化命令和GDDRAM操作函数。此外,还展示了如何通过I2C进行连续读写操作,以及驱动OLED显示的各种功能,如设置对比度、全屏显示和清屏等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

之前购买了一款SSD1306驱动的0.96inchOLED显示屏幕,采用ESP8266使用u8g2库成功驱动。如今想自己摸索一下如何利用I2C驱动SSD1306.

I2C协议

I2C开始
SCL为高电平期间,SDA由高到低

void IIC_START()//IIC_SCL高电平时候 IIC_SDA拉低
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();
	
	IIC_SCL_H;IIC_SDA_L;IIC_DELAY();
	IIC_SCL_L;
}

I2C停止
SCL为高电平期间,SDA由低到高

void IIC_STOP()//IIC_SCL高电平时候 IIC_SDA升高
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_L;IIC_DELAY();
	
	IIC_SCL_H;IIC_SDA_H;IIC_DELAY();
	IIC_SCL_L;
}

I2C发送ACK

void IIC_ACK()//SCL为高电平时候 IIC_SDA为低电平
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_L;IIC_DELAY();

	IIC_SCL_H;IIC_DELAY();
	IIC_SCL_L;
}

I2C发送NACK

void IIC_NACK()
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();

	IIC_SCL_H;IIC_DELAY();
	IIC_SCL_L;
}

I2C等待ACK

uint8_t IIC_WAIT_ACK(void)
{
	uint8_t rpt=0;
	IIC_IN();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();

	IIC_SCL_H;
	while(GPIO_ReadInputDataBit(IIC_SDA,IIC_SDA_PIN)==Bit_SET)   //等待应答信号
	{
		rpt++;
		if(rpt>254){
			IIC_STOP();
			return 1;
		}
	}
	IIC_SCL_L;
	return 0;
}

I2C发送一个Byte

void IIC_SEND_BYTE(uint8_t byte)
{
	IIC_OUT();
	uint8_t i=0;
	for(i=0;i<8;i++){
		uint8_t bit=(byte>>(7-i)&0x01);
		IIC_SCL_L;
		if(bit){
			IIC_SDA_H;
		}else{
			IIC_SDA_L;
		}
		IIC_DELAY();		
		IIC_SCL_H;IIC_DELAY();
		IIC_SCL_L;
	}
}

I2C接受一个字节

uint8_t IIC_RECEIVE_BYTE(uint8_t ack)
{
	uint8_t temp,i;
	IIC_IN();
	for(i=0;i<8;i++)
	{
		IIC_SCL_L;IIC_DELAY();
		
		IIC_SCL_H;IIC_DELAY();
		temp<<=1;
		if(GPIO_ReadInputDataBit(IIC_SDA,IIC_SDA_PIN)==Bit_SET)temp|=0x01;
		IIC_SCL_L;	
	}					 
	if(!ack)
		 IIC_NACK();        //发送NACK
	else
		 IIC_ACK();         //发送ACK   
	return temp;
}

I2C连续读

//            R/W#   1/0
uint8_t IIC_READ(uint8_t addr,uint8_t reg,uint8_t* data,uint8_t len)
{
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|0);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	IIC_SEND_BYTE(reg);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|1);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	while(len){
		if(len==1)*data=IIC_RECEIVE_BYTE(0);
		else *data=IIC_RECEIVE_BYTE(1);
		len--;
		data++;	
	}
	IIC_STOP();
	return 0;
}

I2C连续写

uint8_t IIC_WRITE(uint8_t addr,uint8_t reg,uint8_t* data,uint8_t len)
{
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|0);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	
	IIC_SEND_BYTE(reg);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	while(len){
		IIC_SEND_BYTE(*data);
		if(IIC_WAIT_ACK()){
			IIC_STOP();	
			return 1;
		}	
		len--;
		data++;
	}
	IIC_STOP();
	return 0;
}

SSD1306驱动源代码

#include "ssd1306.h"

#define OLED_ADR 0X3C
#define SSD1306_DELAY_US 2
#define pixel_height 64
#define pixel_width  128


unsigned char GDDRAM[8][128]={0};//最小位是在最前行
const unsigned char  OLED_InitCmd[25]=
{
  /*0xae,0X00,0X10,0x40,0X81,0XCF,0xff,0xa1,0xa4,
  0xA6,0xc8,0xa8,0x3F,0xd5,0x80,0xd3,0x00,0XDA,0X12,
  0x8d,0x14,0xdb,0x40,0X20,0X02,0xd9,0xf1,0xAF*/
       0xAE,//关闭显示
       0xD5,//设置时钟分频因子,震荡频率
       0x80,  //[3:0],分频因子;[7:4],震荡频率

       0xA8,//设置驱动路数
       0X3F,//默认0X3F(1/64)
       0xD3,//设置显示偏移
       0X00,//默认为0
       0x40,//设置显示开始行 [5:0],行数.                              
       0x8D,//电荷泵设置
       0x14,//bit2,开启/关闭
	
       0x20,//设置内存地址模式
       0x00,//[1:0],00,水平地址模式   01,垂直地址模式   10,页地址模式;默认10;
	
       0xA1,//段重定义设置,bit0:0,0->0;1,0->127;  左右反转
	
			 0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 上下反转
	
       0xDA,//设置COM硬件引脚配置
       0x12,//[5:4]配置   
			 
       0x81,//对比度设置
       0xEF,//1~255;默认0X7F (亮度设置,越大越亮)
			 
       0xD9,//设置预充电周期
       0xf1,//[3:0],PHASE 1;[7:4],PHASE 2;
			 
       0xDB,//设置VCOMH 电压倍率
       0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
			 
       0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
			 
       0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示   
			 
       0xAF,//开启显示     
};
/*.........................................GDDRAM操作.......................................*/
static void OLED_GReset(void)//复位全部GDDRAM
{
	unsigned char i,j;
	for(i=0;i<128;i++){
		for(j=0;j<8;j++){
			GDDRAM[j][i]=0;
		}
	}
}
static void OLED_GSet(void) //置位全部GDDRAM
{
	unsigned char i,j;
	for(i=0;i<128;i++){
		for(j=0;j<8;j++){
			GDDRAM[j][i]=0xff;
		}
	}	
}
static void OLED_GSetP(unsigned char x,unsigned char y)//置位单个点
{
	if(x>pixel_width-1||y>pixel_height-1)return;
	GDDRAM[y/8][x]|=(0x01<<(y%8));
}
static void OLED_GResetP(unsigned char x,unsigned char y)//复位单个点
{
	if(x>pixel_width-1||y>pixel_height-1)return;
	GDDRAM[y/8][x]&=~(0x01<<(y%8));
}
static unsigned char OLED_GGetP(unsigned char x,unsigned char y)//获取某个点
{
	if(x>pixel_width-1||y>pixel_height-1)return 0;
	return (GDDRAM[y/8][x]>>(y%8))&0x01;
}
static void OLED_GSetByte(unsigned char data,unsigned char page,unsigned char column)
{
	if(page>7||column>127)return;
	GDDRAM[page][column]=data;
}
/*.......................................................................................*/
/*.........................................IIC操作.......................................*/
static void OLED_SendCmd(unsigned char cmd)
{
	IIC_Set_Delay_Us(SSD1306_DELAY_US);
	IIC_START();
	IIC_SEND_BYTE(OLED_ADR<<1|0);//WRITE
	IIC_WAIT_ACK();
	IIC_SEND_BYTE(0x00);//   DC位为0 表示是cmd
	IIC_WAIT_ACK();
	IIC_SEND_BYTE(cmd);
	IIC_WAIT_ACK();
	IIC_STOP();	
}
static void OLED_SendData(unsigned char data)
{
	IIC_Set_Delay_Us(SSD1306_DELAY_US);
	IIC_START();
	IIC_SEND_BYTE(OLED_ADR<<1|0);
	IIC_WAIT_ACK();
	IIC_SEND_BYTE(0x40);//   DC位为1 表示是data
	IIC_WAIT_ACK();
	IIC_SEND_BYTE(data);
	IIC_WAIT_ACK();
	IIC_STOP();	
}
static void OLED_SendCmdCo(const unsigned char * cmd,unsigned int len)
{
	IIC_Set_Delay_Us(SSD1306_DELAY_US);
	IIC_START();
	IIC_SEND_BYTE(OLED_ADR<<1|0);//WRITE
	IIC_WAIT_ACK();
	for(unsigned int i=0;i<len;i++){
		IIC_SEND_BYTE(0x80);//   DC位为0 表示是cmd
		IIC_WAIT_ACK();
		IIC_SEND_BYTE(cmd[i]);
		IIC_WAIT_ACK();
	}
	IIC_STOP();	
}
static void OLED_SendDataCo(const unsigned char * data,unsigned int len)
{
	IIC_Set_Delay_Us(SSD1306_DELAY_US);
	IIC_START();
	IIC_SEND_BYTE(OLED_ADR<<1|0);//WRITE
	IIC_WAIT_ACK();
	unsigned int i;
	for(i=0;i<len;i++)
	{   
		IIC_SEND_BYTE(0xC0);//DC位为1 表示是data
		IIC_WAIT_ACK();
		IIC_SEND_BYTE(data[i]);
		IIC_WAIT_ACK();
	}
	IIC_STOP();	
}
static void OLED_Set_MemAddrMode(uint8_t mode)//0x00 水平地址  0x01垂直地址  0x02页地址
{
	OLED_SendCmd(0x20);
	OLED_SendCmd(mode);
}

//页模式寻址
static void Column_Set_P(unsigned char column)//列地址0-127
{
	if(column>127)return;
	OLED_SendCmd(0x10|(column>>4));    //设置列地址高位
	OLED_SendCmd(0x00|(column&0x0f));   //设置列地址低位         	 
}
static void Page_Set_P(unsigned char page)//页地址
{
	OLED_SendCmd(0xB0+page);
}
//水平寻址 垂直寻址
static void Column_Set_HV(uint8_t Column_Begin,uint8_t Column_End)//0-127
{
	if(Column_End>127||Column_Begin>Column_End)return;
	OLED_SendCmd(0x21);
	OLED_SendCmd(Column_Begin); 
	OLED_SendCmd(Column_End); 
}
static void Page_Set_HV(uint8_t Page_Begin,uint8_t Page_End)//0-7
{
	if(Page_End>7||Page_Begin>Page_End)return;
	OLED_SendCmd(0x22);
	OLED_SendCmd(Page_Begin); 
	OLED_SendCmd(Page_End); 
}
/*....................................................................................*/
void OLED_Configuration(void)
{	
	OLED_SendCmdCo(OLED_InitCmd,25);
}
void OLED_SetContrast(unsigned char constrast)//1-255
{
	OLED_SendCmd(0x81);
	OLED_SendCmd(constrast);
}
void OLED_Full(void)
{
	OLED_GSet();
	OLED_Display();
}
void OLED_Clean(void)
{
	OLED_GReset();
	OLED_Display();
}
void OLED_OFF(void)
{
	OLED_SendCmd(0xAE);//关闭
}
void OLED_ON(void)
{
	OLED_SendCmd(0xAF);//开启
}
void OLED_FlipAll(uint8_t mode)
{
	if(mode){
		OLED_SendCmd(0xA6);//1亮0灭
	}else{	
		OLED_SendCmd(0xA7);//1灭0亮
	}
}

/*..............................GDDRAM绘制函数..............................................*/
void OLED_GFlipPart(unsigned char x,unsigned char y,unsigned char width,unsigned char height)
{	
	unsigned char i,j;
	for(i=x;i<x+width;i++){
		for(j=y;j<y+height;j++){
			if(OLED_GGetP(i,j)){OLED_GResetP(i,j);}else{OLED_GSetP(i,j);}
		}
	}
}
void OLED_GModifyPart(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char color)
{
	unsigned char i,j;
	for(i=x1;i<x2;i++)
	{
		for(j=y1;j<y2;j++)
		{
			if(color)OLED_GSetP(i,j);else OLED_GResetP(i,j);
		}
	}
}
void OLED_GDrawBitmap(unsigned char x,unsigned char y,const unsigned char*data,unsigned char width,unsigned char height)
{
/*阴码 逐列式 逆向*/
	unsigned char i,j,offset=0,index=0,fast_fill=0;
	const unsigned char *p=data;
	offset=y%8;
	if(offset==0)fast_fill=1;
	offset=0;
	for(i=x;i<x+width;i++){
		for(j=y;j<y+height;j++){
			if(fast_fill){
				OLED_GSetByte(*p,j/8,i);
				j+=8;
				p++;
			}else{
				if((*p>>offset)&0x01){
					OLED_GSetP(i,j);
				}else{
					OLED_GResetP(i,j);
				}
				offset++;
				if(offset%8==0){p++;offset=0;};
			}
		}
	}
}
void OLED_GDrawChar(unsigned char x,unsigned char y,const char data,unsigned char width,unsigned char height)
{
	/*阴码 逐列式 逆向*/
	unsigned char i,j,offset=0,index=0,fast_fill=0;
	const unsigned char *p;
	index=(int)data;
	if(index>126||index<32)return;//不在可绘制列表内
	p=&ascii[index-32][0];
	offset=y%8;
	if(offset==0)fast_fill=1;
	offset=0;
	for(i=x;i<x+width;i++){
		for(j=y;j<y+height;j++){
			if(fast_fill){
				OLED_GSetByte(*p,j/8,i);
				j+=8;
				p++;
			}else{
				if((*p>>offset)&0x01){
					OLED_GSetP(i,j);
				}else{
					OLED_GResetP(i,j);
				}
				offset++;
				if(offset%8==0){p++;offset=0;};
			}
		}
	}
}
void OLED_GDrawString(unsigned char x,unsigned char y,const char *data,unsigned char width,unsigned char height)
{
	unsigned char x_pos=x;
	while(*data!=0){
		if(*data=='\n'){y+=height;data++;x_pos=x;continue;}
		if(x_pos>pixel_width-1||y>pixel_height-1){data++;continue;}
		OLED_GDrawChar(x_pos,y,*data,width,height);
		x_pos+=width;
		data++;
	}
}
void OLED_GDrawL_V(unsigned char X_B,unsigned char Y_B,unsigned char height)
{
	unsigned char Y;
	for(Y=Y_B;Y<Y_B+height;Y++)
	{
		OLED_GSetP(X_B,Y);
	}
}
void OLED_GDrawL_R(unsigned char X_B,unsigned char Y_B,unsigned char width)
{
	unsigned char X;
	for(X=X_B;X<X_B+width;X++)
	{
		OLED_GSetP(X,Y_B);
	}
}
void OLED_GDrawHollowRect(unsigned char xpos,unsigned char ypos,unsigned char iwidth,unsigned char iheight)
{
	OLED_GDrawL_R(xpos,ypos,iwidth);
	OLED_GDrawL_R(xpos,ypos+iheight-1,iwidth);
	
	OLED_GDrawL_V(xpos,ypos,iheight);
	OLED_GDrawL_V(xpos+iwidth-1,ypos,iheight);
}
void OLED_GDrawSolidRect(unsigned char xpos,unsigned char ypos,unsigned char iwidth,unsigned char iheight)
{
	unsigned char i,j;
	for(i=xpos;i<xpos+iwidth;i++){
		for(j=ypos;j<ypos+iheight;j++){
			OLED_GSetP(i,j);
		}
	}
}
void OLED_GDrawNetRect(unsigned char xpos,unsigned char ypos,unsigned char iwidth,unsigned char iheight)
{
	unsigned char i,j;
	for(i=xpos;i<xpos+iwidth;i++){
		for(j=ypos;j<ypos+iheight;j++){
			if(i%2==0||j%2==0)OLED_GResetP(i,j);else OLED_GSetP(i,j);
		}
	}
}

void OLED_GDrawRectdotO(unsigned char xpos,unsigned char ypos,unsigned char iwidth,unsigned char iheight,unsigned char density)
{
		unsigned char i;
    for(i=xpos+2;i<xpos+iwidth-2;i+=density){
      OLED_GSetP(i, ypos+2);
    }
    for(i=xpos+2;i<xpos+iwidth-2;i+=density){
      OLED_GSetP(i, ypos+iheight-3);
    }
    for(i=ypos+2;i<ypos+iheight-2;i+=density){
      OLED_GSetP(xpos+2, i);
    }
    for(i=ypos+2;i<ypos+iheight-2;i+=density){
      OLED_GSetP(xpos+iwidth-3, i);
    }
    OLED_GDrawHollowRect(xpos,ypos,iwidth,iheight);   
}
void OLED_GDrawRectdotI(unsigned char xpos,unsigned char ypos,unsigned char iwidth,unsigned char iheight,unsigned char density)
{
		unsigned char i;
    for(i=xpos;i<xpos+iwidth;i+=density){
      OLED_GSetP(i, ypos);
    }
    for(i=xpos;i<xpos+iwidth;i+=density){
      OLED_GSetP(i, ypos+iheight-1);
    }
    for(i=ypos;i<ypos+iheight;i+=density){
      OLED_GSetP(xpos, i);
    }
    for(i=ypos;i<ypos+iheight;i+=density){
      OLED_GSetP(xpos+iwidth-1, i);
    }
    OLED_GDrawHollowRect(xpos+2,ypos+2,iwidth-4,iheight-4);
}
void OLED_Display(void)
{
	unsigned char page,column;
	OLED_Set_MemAddrMode(0);
	Column_Set_HV(0,127);
	Page_Set_HV(0,7);
	OLED_SendDataCo((const unsigned char *)GDDRAM,128*8);
}
/*.........................................................................................*/
void OLED_DrawFrame(unsigned char data[8][128])
{
	unsigned char i,j;
	OLED_Set_MemAddrMode(0);
	Column_Set_HV(0,127);
	Page_Set_HV(0,7);
	OLED_SendDataCo((const unsigned char *)data,128*8);
}

void OLED_DrawP(unsigned char x,unsigned char y,unsigned char color)
{
	if(x>127||y>63)return;
	OLED_Set_MemAddrMode(0x02);//页模式
	Page_Set_P(y/8);
	Column_Set_P(x);
	if(color)GDDRAM[y/8][x]|=(0x01<<(y%8));else GDDRAM[y/8][x]&=~(0x01<<(y%8));
	OLED_SendData(GDDRAM[y/8][x]);
}

I2C驱动源代码

#include "includes.h"
#define IIC_SDA  GPIOA
#define IIC_SCL  GPIOA

#define IIC_SDA_PIN GPIO_Pin_3
#define IIC_SCL_PIN GPIO_Pin_2

#define IIC_SDA_H GPIO_SetBits(IIC_SDA,IIC_SDA_PIN)
#define IIC_SDA_L GPIO_ResetBits(IIC_SDA,IIC_SDA_PIN)

#define IIC_SCL_H GPIO_SetBits(IIC_SCL,IIC_SCL_PIN)
#define IIC_SCL_L GPIO_ResetBits(IIC_SCL,IIC_SCL_PIN)

static uint8_t IIC_DELAY_US=1;
void IIC_Init(void)
{
	static uint8_t isInit=0;
	if(isInit==1)return;
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;//SDA
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(IIC_SDA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin=IIC_SCL_PIN;//SCL
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(IIC_SCL,&GPIO_InitStructure);
	IIC_STOP();
	IIC_DELAY_US=2;
	isInit=1;
}
void IIC_OUT(void)//SDA是输出方向
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //推挽输出模式
	GPIO_Init(IIC_SDA,&GPIO_InitStructure);
}
void IIC_IN(void)//SDA是输入方向
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;  //输入上拉模式
	GPIO_Init(IIC_SDA,&GPIO_InitStructure);
}
void IIC_DELAY(void)
{
	delay_us(IIC_DELAY_US);
}
void IIC_Set_Delay_Us(uint8_t us)
{
	IIC_DELAY_US=us;
}
void IIC_START()//IIC_SCL高电平时候 IIC_SDA拉低
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();
	
	IIC_SCL_H;IIC_SDA_L;IIC_DELAY();
	IIC_SCL_L;
}
void IIC_STOP()//IIC_SCL高电平时候 IIC_SDA升高
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_L;IIC_DELAY();
	
	IIC_SCL_H;IIC_SDA_H;IIC_DELAY();
	IIC_SCL_L;
}
void IIC_ACK()//SCL为高电平时候 IIC_SDA为低电平
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_L;IIC_DELAY();

	IIC_SCL_H;IIC_DELAY();
	IIC_SCL_L;
}
void IIC_NACK()
{
	IIC_OUT();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();

	IIC_SCL_H;IIC_DELAY();
	IIC_SCL_L;
}
uint8_t IIC_WAIT_ACK(void)
{
	uint8_t rpt=0;
	IIC_IN();
	IIC_SCL_L;IIC_SDA_H;IIC_DELAY();

	IIC_SCL_H;
	while(GPIO_ReadInputDataBit(IIC_SDA,IIC_SDA_PIN)==Bit_SET)   //等待应答信号
	{
		rpt++;
		if(rpt>254){
			IIC_STOP();
			return 1;
		}
	}
	IIC_SCL_L;
	return 0;
}
void IIC_SEND_BYTE(uint8_t byte)
{
	IIC_OUT();
	uint8_t i=0;
	for(i=0;i<8;i++){
		uint8_t bit=(byte>>(7-i)&0x01);
		IIC_SCL_L;
		if(bit){
			IIC_SDA_H;
		}else{
			IIC_SDA_L;
		}
		IIC_DELAY();		
		IIC_SCL_H;IIC_DELAY();
		IIC_SCL_L;
	}
}
uint8_t IIC_RECEIVE_BYTE(uint8_t ack)
{
	uint8_t temp,i;
	IIC_IN();
	for(i=0;i<8;i++)
	{
		IIC_SCL_L;IIC_DELAY();
		
		IIC_SCL_H;IIC_DELAY();
		temp<<=1;
		if(GPIO_ReadInputDataBit(IIC_SDA,IIC_SDA_PIN)==Bit_SET)temp|=0x01;
		IIC_SCL_L;	
	}					 
	if(!ack)
		 IIC_NACK();        //发送NACK
	else
		 IIC_ACK();         //发送ACK   
	return temp;
}
//R/W#   1/0
uint8_t IIC_READ(uint8_t addr,uint8_t reg,uint8_t len,uint8_t* data)
{
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|0);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	IIC_SEND_BYTE(reg);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|1);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	while(len){
		if(len==1)*data=IIC_RECEIVE_BYTE(0);
		else *data=IIC_RECEIVE_BYTE(1);
		len--;
		data++;	
	}
	IIC_STOP();
	return 0;
}
uint8_t IIC_WRITE(uint8_t addr,uint8_t reg,uint8_t len,uint8_t* data)
{
	IIC_START();
	IIC_SEND_BYTE((addr<<1)|0);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	
	IIC_SEND_BYTE(reg);
	if(IIC_WAIT_ACK()){
		IIC_STOP();
		return 1;
	}
	while(len){
		IIC_SEND_BYTE(*data);
		if(IIC_WAIT_ACK()){
			IIC_STOP();	
			return 1;
		}	
		len--;
		data++;
	}
	IIC_STOP();
	return 0;
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值