guanjiaer 发表于 2025-8-14 11:21

STM32 | IIC 驱动OLED显示字符

I2C
(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。

硬件连接图:




它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps。

【串口】只能做点对点------115200bps
【 IIC 】 可以一对多------400kbps(比串口更快),但是半双工通信
OLED模块
TB上选的一个支持IIC通信的OLED模块




在STM32上的准备
需要加入I2C通信,直接使用STM32带有的库就好,当然也可根据IIC的时序自己来写模拟IIC




代码
GPIO口配置
对GPIO进行复用配置
还需要对IIC进行配置(I2C 总线的时钟频率)
void I2C_Configuration(void)
{
        I2C_InitTypeDefI2C_InitStructure;
        GPIO_InitTypeDefGPIO_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

        // 初始化GPIO的设置
        /*STM32硬件I2C: PB10 -- SCL; PB11 -- SDA */
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10 | GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        // 对I2C2进行配置
        I2C_DeInit(I2C2);//使用I2C2
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

        I2C_Cmd(I2C2, ENABLE);
        I2C_Init(I2C2, &I2C_InitStructure);
}



IIC写操作函数
目的是写一个字节数据到寄存器中,采用阻塞式设计,会等待每个操作完成后再继续下一步,确保数据正确传输。

接收两个参数,addr代表寄存器地址,data代表数据
先写入设备地址,用于选中总线上的IIC设备
再写入寄存器地址
最后写入要写的寄存器的值
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
       
        I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1

        // 等待事件(EV5,主模式),确认起始信号已成功发送。
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

        I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//发送器件地址(选中从设备)
        // 等待事件,确认设备已响应并进入发送模式。
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        I2C_SendData(I2C1, addr);//发送寄存器地址
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_SendData(I2C1, data);//发送数据
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
       
        I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线
}



OLED写数据接口封装
用于写命令(写到寄存器地址0x00)和写数据(写到寄存器地址0x40)

void WriteCmd(unsigned char I2C_Command)//写命令
{
        I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)//写数据
{
        I2C_WriteByte(0x40, I2C_Data);
}


OLED_Init() OLED的初始化
也是调用底层的IIC操作接口所封装而成:

void OLED_Init(void)
{
        delay_ms(100);

        printf("OLED_Init()\r\n");
       
        WriteCmd(0xAE); //display off
        WriteCmd(0x20);        //Set Memory Addressing Mode       
        WriteCmd(0x10);        //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
        WriteCmd(0xb0);        //Set Page Start Address for Page Addressing Mode,0-7
        WriteCmd(0xc8);        //Set COM Output Scan Direction
        WriteCmd(0x00); //---set low column address
        WriteCmd(0x10); //---set high column address
        WriteCmd(0x40); //--set start line address
        WriteCmd(0x81); //--set contrast control register
        WriteCmd(0xff); //亮度调节 0x00~0xff
        WriteCmd(0xa1); //--set segment re-map 0 to 127
        WriteCmd(0xa6); //--set normal display
        WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
        WriteCmd(0x3F); //
        WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
        WriteCmd(0xd3); //-set display offset
        WriteCmd(0x00); //-not offset
        WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
        WriteCmd(0xf0); //--set divide ratio
        WriteCmd(0xd9); //--set pre-charge period
        WriteCmd(0x22); //
        WriteCmd(0xda); //--set com pins hardware configuration
        WriteCmd(0x12);
        WriteCmd(0xdb); //--set vcomh
        WriteCmd(0x20); //0x20,0.77xVcc
        WriteCmd(0x8d); //--set DC-DC enable
        WriteCmd(0x14); //
        WriteCmd(0xaf); //--turn on oled panel
}


OLED一些基础函数的封装
也是通过写命令 WriteCmd() 和写数据 WriteDat() 来实现


void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{
        WriteCmd(0xb0+y);
        WriteCmd(((x&0xf0)>>4)|0x10);
        WriteCmd((x&0x0f)|0x01);
}

void OLED_Fill(unsigned char fill_Data)//全屏填充
{
        unsigned char m,n;
        for(m=0;m<8;m++)
        {
                WriteCmd(0xb0+m);                //page0-page1
                WriteCmd(0x00);                //low column start address
                WriteCmd(0x10);                //high column start address
                for(n=0;n<128;n++)
                        {
                                WriteDat(fill_Data);
                        }
        }
}

void OLED_CLS(void)//清屏
{
        OLED_Fill(0x00);
}

//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          :
// Parameters   : none
// Description    : 将OLED从休眠中唤醒
//--------------------------------------------------------------
void OLED_ON(void)
{
        WriteCmd(0X8D);//设置电荷泵
        WriteCmd(0X14);//开启电荷泵
        WriteCmd(0XAF);//OLED唤醒
}

//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          :
// Parameters   : none
// Description    : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
        WriteCmd(0X8D);//设置电荷泵
        WriteCmd(0X10);//关闭电荷泵
        WriteCmd(0XAE);//OLED休眠
}






OLED_ShowStr() 显示字符串
接收四个参数,分别是:

x:起始点横坐标 (0~127)
y:起始点纵坐标 (0~7)
ch:要显示的字符串
TextSize -- 字符大小选择 (1:6*8 ; 2:8*16)
//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          :
// Parameters   : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
        unsigned char c = 0,i = 0,j = 0;
        switch(TextSize)
        {
                case 1:
                {
                        while(ch != '\0')
                        {
                                c = ch - 32;
                                if(x > 126)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i<6;i++)
                                        WriteDat(F6x8);
                                x += 6;
                                j++;
                        }
                }break;
                case 2:
                {
                        while(ch != '\0')
                        {
                                c = ch - 32;
                                if(x > 120)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i<8;i++)
                                        WriteDat(F8X16);
                                OLED_SetPos(x,y+1);
                                for(i=0;i<8;i++)
                                        WriteDat(F8X16);
                                x += 8;
                                j++;
                        }
                }break;
        }
}


主函数调用:
void task1_task(void *pvParameters)
{
        unsigned char i;
        I2C_Configuration();        /*I2C: PB10 -- SCL; PB11 -- SDA */
        OLED_Init();
       
        while(1)
        {
                OLED_Fill(0xFF);//全屏点亮
                delay_ms(2000);
                OLED_Fill(0x00);//全屏灭
                delay_ms(2000);

                delay_ms(2000);
                OLED_ShowStr(0,3,"asdfasdfasY",2);
                OLED_ShowStr(0,6,"1997 1998 2025 07 08",1);
                delay_ms(2000);
               
                OLED_CLS();//清屏
                OLED_OFF();//测试OLED休眠
                delay_ms(2000);
               
                OLED_ON();//测试OLED休眠后唤醒

                delay_ms(2000);
        }       

}



显示中文:
这个可以通过取模软件的出来,在软件中输入汉字,就可以得到这些对应的数组内容




/***************************16*16的点阵字体取模方式:共阴——列行式——逆向输出*********/
unsigned char F16x16[] =
{
        0x00,0x40,0x20,0x1E,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00,
        0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFF,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,/*"牛",0*/

        0x40,0x40,0x42,0xCC,0x00,0x82,0xBA,0xAA,0xAA,0xAA,0xAA,0xAA,0xBA,0x82,0x00,0x00,
        0x00,0x40,0x20,0x1F,0x20,0x5F,0x4A,0x4A,0x4A,0x4F,0x4A,0x4A,0x4A,0x5F,0x40,0x00,/*"逼",1*/

        0xFC,0x04,0xFC,0x00,0xFE,0x42,0xBE,0x00,0xF2,0x12,0xF2,0x02,0xFE,0x02,0x00,0x00,
        0x0F,0x04,0x0F,0x00,0xFF,0x10,0x0F,0x00,0x0F,0x04,0x4F,0x80,0x7F,0x00,0x00,0x00,/*"啊",2*/

};



//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          :
// Parameters   : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description    : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
        unsigned char wm=0;
        unsigned intadder=32*N;
        OLED_SetPos(x , y);
        for(wm = 0;wm < 16;wm++)
        {
                WriteDat(F16x16);
                adder += 1;
        }
        OLED_SetPos(x,y + 1);
        for(wm = 0;wm < 16;wm++)
        {
                WriteDat(F16x16);
                adder += 1;
        }
}



// 调用,一般打横显示,注意每个字符之间的大小间距
{
    for(i=0; i<CharNum; i++)
        {
                OLED_ShowCN(22+i*16,0,i);//测试显示中文
        }
}



————————————————
版权声明:本文为CSDN博主「扣篮发型不乱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/KawhiLeo/article/details/149140065

页: [1]
查看完整版本: STM32 | IIC 驱动OLED显示字符