自学内容网 自学内容网

IIC相关介绍及oled实验(二)

//模块:OLED显示屏

1. 0.96寸OLED屏幕介绍

0.96 寸 4P OLED 屏幕模块是一种显示屏模块,它包括一个 0.96 英寸的 OLED 显示屏和四个引脚。这种 OLED 屏幕模块通常用于嵌入式系统和小型电子设备中,可以显示文本、图像和其他类型的信息。由于其小 尺寸和低功耗,也常用于智能手表、健康追踪器和其他便携式设备中。

 0.96OLED 屏幕模块的优点有:

1. 高对比度和高亮度:OLED 屏幕模块可以提供深黑色背景和明亮的字色,因此可以实现高对比度和高亮 度的显示效果;

2. 自发光:OLED 屏幕模块不需要背光灯,因此可以实现更薄、更轻的设计;

3. 响应速度快:OLED 屏幕模块的响应速度非常快,可以实现流畅的动画和视频效果;

4. 视角宽:OLED 屏幕模块的视角非常宽,即使从不同角度观察,图像和文字也能保持清晰。

0.96OLED 屏幕模块的缺点有:

1. 显示寿命短:与 LCD 显示屏相比,OLED 的显示寿命相对较短,因为它的有机材料会随着时间的推移 而逐渐失效;

2. 显示面积小:0.96 寸 OLED 屏幕模块的显示面积相对较小,因此不适合用于需要大屏幕的应用。

2. 如何驱动OLED屏幕显示内容?

3. OLED通讯协议

4. SSD1306

 5. GDDRAM

页地址模式:  

水平地址模式:

垂直地址模式: 

 

6. OLED命令

 

7. 如何取模 

 小实验:OLED实验

实验目的 驱动 OLED 屏幕,显示点、线、字符、字符串、汉字、图片等内容。

 

实现---点、线、A 

/------oled.h---------/

#include "sys.h"

//SCL配置
#define OLED_I2C_SCL_CLK()  __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SCL_PORT   GPIOB
#define OLED_I2C_SCL_PIN    GPIO_PIN_6

//SDA配置
#define OLED_I2C_SDA_CLK()  __HAL_RCC_GPIOB_CLK_ENABLE();
#define OLED_I2C_SDA_PORT   GPIOB
#define OLED_I2C_SDA_PIN    GPIO_PIN_7

//SCL引脚拉高拉低
#define OLED_SCL_RESET()   HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_RESET)
#define OLED_SCL_SET()     HAL_GPIO_WritePin(OLED_I2C_SCL_PORT, OLED_I2C_SCL_PIN, GPIO_PIN_SET)

//SDA引脚使能
#define OLED_SDA_RESET()   HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_RESET)
#define OLED_SDA_SET()     HAL_GPIO_WritePin(OLED_I2C_SDA_PORT, OLED_I2C_SDA_PIN, GPIO_PIN_SET)

void oled_init(void);
void oled_write_cmd(uint8_t cmd);
void oled_write_data(uint8_t data);
void oled_fill(uint8_t data);
void oled_set_cursor(uint8_t x, uint8_t y);

/------oled.c---------/

1、oled_gpio_init初始化函数

void oled_gpio_init(void)
{
    GPIO_InitTypeDef gpio_initstruct;

    OLED_I2C_SCL_CLK();
    OLED_I2C_SDA_CLK();
    
    gpio_initstruct.Pin = OLED_I2C_SCL_PIN; //PA7         
    gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             
    gpio_initstruct.Pull = GPIO_PULLUP;                     
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           
    HAL_GPIO_Init(OLED_I2C_SCL_PORT, &gpio_initstruct);//GPIOB
    
    gpio_initstruct.Pin = OLED_I2C_SDA_PIN;          
    HAL_GPIO_Init(OLED_I2C_SDA_PORT, &gpio_initstruct);
}

2、I2C起始信号:起始信号由主设备发起,用于通知总线上的所有设备即将开始数据传输

void oled_i2c_start(void)
{
    OLED_SCL_SET(); //确保scl在高电平为拉低做准备
    OLED_SDA_SET();//确保sda在高电平为拉低做准备
    OLED_SDA_RESET();//只有在sda拉低的条件是才能传输数据,拉低
    OLED_SCL_RESET();//当SCL为高电平时,SDA由高电平变为低电平,产生一个下降沿
}

3、I2C停止信号 由主设备发起,用于通知总线上的所有设备数据传输已经结束

void oled_i2c_stop(void)
{
/*当SCL为高电平时,SDA由低电平变为高电平,产生一个上升沿,表示停止信号的开始*/
    OLED_SCL_SET();
    OLED_SDA_RESET();
    OLED_SDA_SET();
}

4、I2C响应信号

每当一个字节的数据传输完成后,接收方会向发送方发送一个应答信号(ACK)或非应答信号 (NACK)。

应答信号在SCL的第9个时钟周期(当SCL为高电平时)发送。


void oled_i2c_ack(void)
{
    //默认低电平?
    OLED_SCL_SET();
    OLED_SCL_RESET();
}

/*如果SDA线为低电平,则表示ACK(有效应答),
表示接收方已成功接收该字节。 如果SDA线为高电平
则表示NACK(非应答),通常表示接收方接收该字节没有成功*/

5、I2C写byte  ??

void oled_i2c_write_byte(uint8_t data)
{
    uint8_t i, tmp;
    tmp = data;
    
    for(i = 0; i < 8; i++)
    {
        if((tmp & 0x80) == 0x80)
            OLED_SDA_SET();
        else
            OLED_SDA_RESET();
        tmp = tmp << 1;
        OLED_SCL_SET();
        OLED_SCL_RESET();
    }
}

6、I2C写命令

void oled_write_cmd(uint8_t cmd)
{
    oled_i2c_start();
    oled_i2c_write_byte(0x78);
    oled_i2c_ack();
    oled_i2c_write_byte(0x00);
    oled_i2c_ack();
    oled_i2c_write_byte(cmd);
    oled_i2c_ack();
    oled_i2c_stop();
}

7、I2C写数据


void oled_write_data(uint8_t data)
{
    oled_i2c_start();
    oled_i2c_write_byte(0x78);
    oled_i2c_ack();
    oled_i2c_write_byte(0x40);
    oled_i2c_ack();
    oled_i2c_write_byte(data);
    oled_i2c_ack();
    oled_i2c_stop();
}

8、oled初始化

void oled_init(void)
{
    oled_gpio_init();
    
    delay_ms(100);
    
    oled_write_cmd(0xAE);    //设置显示开启/关闭,0xAE关闭,0xAF开启

    oled_write_cmd(0xD5);    //设置显示时钟分频比/振荡器频率
    oled_write_cmd(0x80);    //0x00~0xFF

    oled_write_cmd(0xA8);    //设置多路复用率
    oled_write_cmd(0x3F);    //0x0E~0x3F

    oled_write_cmd(0xD3);    //设置显示偏移
    oled_write_cmd(0x00);    //0x00~0x7F

    oled_write_cmd(0x40);    //设置显示开始行,0x40~0x7F

    oled_write_cmd(0xA1);    //设置左右方向,0xA1正常,0xA0左右反置

    oled_write_cmd(0xC8);    //设置上下方向,0xC8正常,0xC0上下反置

    oled_write_cmd(0xDA);    //设置COM引脚硬件配置
    oled_write_cmd(0x12);

    oled_write_cmd(0x81);    //设置对比度
    oled_write_cmd(0xCF);    //0x00~0xFF

    oled_write_cmd(0xD9);    //设置预充电周期
    oled_write_cmd(0xF1);

    oled_write_cmd(0xDB);    //设置VCOMH取消选择级别
    oled_write_cmd(0x30);

    oled_write_cmd(0xA4);    //设置整个显示打开/关闭

    oled_write_cmd(0xA6);    //设置正常/反色显示,0xA6正常,0xA7反色

    oled_write_cmd(0x8D);    //设置充电泵
    oled_write_cmd(0x14);

    oled_write_cmd(0xAF);    //开启显示
}

9、oled起始位置设施函数


void oled_set_cursor(uint8_t x, uint8_t y)
{
    oled_write_cmd(0xB0 + y);
    oled_write_cmd((x & 0x0F) | 0x00);
    oled_write_cmd(((x & 0xF0) >> 4) | 0x10);
}

10、oled清屏函数


void oled_fill(uint8_t data)
{
    uint8_t i, j;
    for(i = 0; i < 8; i++)
    {
        oled_set_cursor(0, i);
        for(j = 0; j < 128; j++)
            oled_write_data(data);
    }
}

//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{
//定义两个循环判断有几个page
uint8_t i,j,page;

num = num - ' ';//做一个偏移显示我们的字符  空格的asci的值就是32
page = size / 8; //取整是多少确定有多少个page模式取出来
if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个page
page++;

for(j = 0;j<page;j++)
{

oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分  位置显示

//数据是高度的一半
//size / 2 * (j + 1)   j意思是第几个page
for(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始
{
//对不同尺寸做一个判断
if(size == 12)
oled_write_data(ascii_6X12[num][i]);
else if(size == 16)
oled_write_data(ascii_8X16[num][i]);
else if(size == 24)
}
}

}

 

打印一个字符

//指定位置 行和列,外循环选择page ,内循环写里面的内容
void oled_show_char(uint8_t x, uint8_t y, uint8_t num, uint8_t size) //高度16 / 8
{
//定义两个循环判断有几个page
uint8_t i,j,page;

num = num - ' ';//做一个偏移显示我们的字符  空格的asci的值就是32
page = size / 8; //取整是多少确定有多少个page模式取出来
if(size % 8)//需要两个page,再判断余数是否为0保证至少有1个page
page++;

for(j = 0;j<page;j++)
{

oled_set_cursor(x,y + j);//如果y没有加j会只显示上半部分  位置显示

//数据是高度的一半
//size / 2 * (j + 1)   j意思是第几个page
for(i=size / 2 * j; i < size / 2 * (j + 1); i++)//高度的一半*j j=0时size从0开始,下半部分除外除8,从第八个开始
{
//对不同尺寸做一个判断
if(size == 12)
oled_write_data(ascii_6X12[num][i]);
else if(size == 16)
oled_write_data(ascii_8X16[num][i]);
else if(size == 24)
oled_write_data(ascii_12X24[num][i]);
}
}

}

//显示一个字符串

void oled_show_string(uint8_t x, uint8_t y,char *p,uint8_t size)
{
//遍历数组
while(*p !=  '\0')
{
//遍历字符
oled_show_char(x,y,*p,size);
//偏移字符  字符的宽度是高度的一半
x += size/2;
p++;
}
}

 显示汉字

void oled_show_chinese(uint8_t x, uint8_t y,uint8_t N,uint8_t size)
{
uint16_t i,j;
for(j=0;j < size/8; j++)//第几个page
{
oled_set_cursor(x,y+j);//??
for(i = size * j;i < size * (j+1); i++)//判断尺寸
{
if(size == 16)
oled_write_data(chinese_16x16[N][i]);
else if(size == 24)
oled_write_data(chinese_24x24[N][i]);
}
}

}

图片显示,具体某图片

void oled_show_image(uint8_t x , uint8_t y, uint8_t width, uint8_t height, uint8_t *bmp)
{
uint16_t i,j,idx;//idx是索引把bmp中的东西提取出来
for(j = 0; j < height;j++)
{
oled_set_cursor(x,y+j);
for(i = 0;i < width; i++)//列
{
//指定坐标
oled_write_data(bmp[idx++]);
}

}

}

/-----main.c-----/ 

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "oled.h"

extern const unsigned char shuai_data[];

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    led_init();                         /* 初始化LED灯 */
    uart1_init(115200);
    oled_init();
    printf("hello world!\r\n");
    
    oled_fill(0x00);
oled_set_cursor(0, 0);
//    oled_write_cmd(0xB0);
//    oled_write_cmd(0x00);
//    oled_write_cmd(0x10);
   
    

//    oled_write_data(0x80);//显示一个点

/*显示字母   A    */
oled_write_data(0x00);
oled_write_data(0x00);
oled_write_data(0xC0);
oled_write_data(0x38);

oled_write_data(0xE0);
oled_write_data(0x00);
oled_write_data(0x00);
oled_write_data(0x00);
oled_set_cursor(0, 1);//前面8个显示完后换到page

oled_write_data(0x20);
oled_write_data(0x3C);
oled_write_data(0x23);
oled_write_data(0x02);

oled_write_data(0x02);
oled_write_data(0x27);
oled_write_data(0x38);
oled_write_data(0x20);

        uint8_t i;
for(i = 0;i < 5;i++)
oled_show_chinese(i*24,0,i,24);
    //假如显示24号字符,一个占用 从0 开始,一个宽度24个字符
oled_show_image(0,0,128,8,(unsigned char*)shui_data);//8*8  64
    while(1)
    { 

    }
}


原文地址:https://blog.csdn.net/qq_65524926/article/details/144252771

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!