tlled 发表于 2024-11-28 00:25

【AT-START-L021测评】+i2c驱动OLED显示屏

测试使用I2C硬件方式驱动OLED显示屏。

一、硬件接口

驱动OLED显示屏,使用i2c1,使用到PB6和PB7,在软件中配置端口。


二、程序部分

2.1、oled.c
#include "at32l021.h"
#include "oled/oled.h"
#include "oled/codetab.h"
#include "delay/delay.h"
#include "i2c/i2c.h"
#include "i2c_application.h"

void I2C_WriteByte(uint8_t addr, uint8_t dat)
{
uint8_t temp;
temp = addr;
        temp = dat;
        i2c_senddat(OLED_ADDRESS, temp, 2);
}


void WriteCmd(unsigned char I2C_Command)
{
    I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)
{
    I2C_WriteByte(0x40, I2C_Data);
}

void OLED_WrCmd(unsigned char IIC_Command)
{
        WriteCmd(IIC_Command);
}

void OLED_Init(void)
{
        delay_ms(100);
        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(0x40); //0x20,0.77xVcc
        WriteCmd(0x8d); //--set DC-DC enable
        WriteCmd(0x14); //
        WriteCmd(0xaf); //--turn on oled panel
}

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(0xff);
}

void OLED_ON(void)
{
        WriteCmd(0X8D);//设置电荷泵
        WriteCmd(0X14);//开启电荷泵
        WriteCmd(0XAF);//OLED唤醒
}

void OLED_OFF(void)
{
        WriteCmd(0X8D);//设置电荷泵
        WriteCmd(0X10);//关闭电荷泵
        WriteCmd(0XAE);//OLED休眠
}

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 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;
        }
}

void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
        unsigned int j=0;
        unsigned char x,y;

if(y1%8==0)
                y = y1/8;
else
                y = y1/8 + 1;
        for(y=y0;y<y1;y++)
        {
                OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
                {
                        WriteDat(BMP);
                }
        }
}

void oled_test(void)
{
        OLED_Init();
        OLED_Fill(0x00);
        OLED_ShowStr(0,0,"AT32L021 BOARD",2);
        OLED_ShowStr(0,2,"I2C OLED TEST",2);       
}


2.2、i2c.c
#include "at32l021.h"
#include "i2c/i2c.h"
#include "i2c_application.h"

i2c_handle_type hi2cx;

/**
* @briefinitializes peripherals used by the i2c.
* @paramnone
* @retval none
*/
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
gpio_init_type gpio_init_structure;

if(hi2c->i2cx == I2Cx_PORT)
{
    /* i2c periph clock enable */
    crm_periph_clock_enable(I2Cx_CLK, TRUE);
    crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
    crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);

    /* gpio configuration */
    gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);

    gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);

    /* configure i2c pins: scl */
    gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_structure.gpio_mode         = GPIO_MODE_MUX;
    gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_structure.gpio_pull         = GPIO_PULL_NONE;

    gpio_init_structure.gpio_pins         = I2Cx_SCL_GPIO_PIN;
    gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);

    /* configure i2c pins: sda */
    gpio_init_structure.gpio_pins         = I2Cx_SDA_GPIO_PIN;
    gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure);

    /* config i2c */
    i2c_init(hi2c->i2cx, 0x0F, I2Cx_CLKCTRL);

    i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2Cx_ADDRESS);
}
}

void init_i2c(void){
        hi2cx.i2cx = I2Cx_PORT;
        i2c_config(&hi2cx);
}

void i2c_senddat(uint16_t address, uint8_t* pdata, uint16_t size)
{
        i2c_master_transmit(&hi2cx, address, pdata, size, I2C_TIMEOUT);
       
}



2.3、main.c
#include "at32l021_clock.h"
#include "led/led.h"
#include "delay/delay.h"
#include "i2c/i2c.h"
#include "oled/oled.h"

int main(void)
{
system_clock_config();
        delay_init();
        init_led();
        init_i2c();
        OLED_Init();
        oled_test();
while(1)
{
    led2_tog();
    delay_ms(200);
    led3_tog();
    delay_ms(200);
    led4_tog();
    delay_ms(200);
}
}


三、程序运行

下载程序后,OLED显示屏显示内容

sanfuzi 发表于 2024-12-3 08:05

OLED的初始化过程涉及一系列I2C命令的发送,例如设置显示模式、对比度、显示方向等。

sanfuzi 发表于 2024-12-6 19:50

I2C接口的OLED显示屏通常带有控制器(如SSD1306),这使得显示屏的控制变得简单,只需发送相应的指令和数据即可。

zerorobert 发表于 2024-12-6 21:23

使用I2C驱动OLED显示屏可以提供较高的数据传输速率,满足大多数应用场景的需求。同时,AT-START-L021的高主频和强大的处理能力可以确保流畅的显示效果。

burgessmaggie 发表于 2024-12-7 00:24

硬件I2C相比软件I2C通常具有更高的通信速度和更好的稳定性,这有助于提升OLED显示屏的刷新率和显示效果。

fengm 发表于 2024-12-7 03:25

OLED显示屏本身也具有一定的成本,但在许多应用中,其高对比度、低功耗和轻薄的特点使得它成为了一个非常有价值的选择。

sheflynn 发表于 2024-12-7 06:29

I2C协议简单易懂,使得OLED显示屏的集成变得相对容易。

chenci2013 发表于 2024-12-9 10:08

I2C接口本身具有较低的功耗特性,适合电池供电的应用场景。AT-START-L021也具备多种低功耗模式,可以进一步降低系统功耗。

mattlincoln 发表于 2024-12-9 13:17

使用I2C硬件方式驱动OLED显示屏是一种常见的做法,因为它可以减少微控制器的引脚使用,同时提供较高的通信效率和稳定性。

10299823 发表于 2024-12-9 16:22

OLED显示屏具有许多优点,但它们的成本可能高于传统的LCD显示屏,这需要在设计时考虑成本效益。

gygp 发表于 2024-12-10 12:39

可以快速实现OLED显示屏的驱动和显示功能。

qiufengsd 发表于 2024-12-10 14:01

OLED 显示屏在硬件层面展现出诸多优势。

olivem55arlowe 发表于 2024-12-10 15:02

AT-START-L021开发板上配有Arduino Uno R3扩展接口?

tlled 发表于 2024-12-10 15:40

olivem55arlowe 发表于 2024-12-10 15:02
AT-START-L021开发板上配有Arduino Uno R3扩展接口?

有的

benjaminka 发表于 2024-12-10 17:05

OLED显示屏具有很高的对比度,可以提供清晰的显示效果,适合在各种光照条件下使用。

houjiakai 发表于 2024-12-10 18:01

硬件I2C需要额外的硬件资源,如I2C通信芯片或FPGA等,这可能会增加一些成本。然而,对于需要高速、稳定通信的应用来说,这些成本可能是值得的。

louliana 发表于 2024-12-10 18:58

OLED显示屏相比传统LCD显示屏具有更低的功耗,这使得整个系统更加节能。

jtracy3 发表于 2024-12-11 16:07

OLED显示屏的刷新率和分辨率可能会影响系统的性能,特别是在处理复杂图形或动画时。

primojones 发表于 2024-12-11 22:20

理解和使用这些库函数可能需要一定的学习成本。

bestwell 发表于 2024-12-11 22:47

使用DMA(直接内存访问)等高级功能可以进一步提升通信效率和显示效果,这在一些高级应用中可能是一个重要的考虑因素。
页: [1] 2
查看完整版本: 【AT-START-L021测评】+i2c驱动OLED显示屏