STM32利用I2C驱动SSD1306代码

编程入门 行业动态 更新时间:2024-10-11 01:14:36

STM32利用I2C驱动SSD1306<a href=https://www.elefans.com/category/jswz/34/1771412.html style=代码"/>

STM32利用I2C驱动SSD1306代码

前言:

之前购买了一款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();        //发送NACKelseIIC_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  128unsigned 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,//默认为00x40,//设置显示开始行 [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);//WRITEIIC_WAIT_ACK();IIC_SEND_BYTE(0x00);//   DC位为0 表示是cmdIIC_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 表示是dataIIC_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);//WRITEIIC_WAIT_ACK();for(unsigned int i=0;i<len;i++){IIC_SEND_BYTE(0x80);//   DC位为0 表示是cmdIIC_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);//WRITEIIC_WAIT_ACK();unsigned int i;for(i=0;i<len;i++){   IIC_SEND_BYTE(0xC0);//DC位为1 表示是dataIIC_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;//SDAGPIO_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;//SCLGPIO_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();        //发送NACKelseIIC_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;
}

更多推荐

STM32利用I2C驱动SSD1306代码

本文发布于:2024-02-13 15:00:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759051.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:代码   I2C

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!