freeelectron 发表于 2022-4-25 21:26

【AT-START-F425测评】+移植u8g2单色图形库驱动0.96吋OLED

<p><span style="font-size:26px;">1、前言</span></p>

<p><span style="font-size:16px;">关于0.96吋oled的详细驱动,可参考<a href="https://bbs.eeworld.com.cn/thread-1196777-1-1.html" target="_blank">【BLE 5.3无线MCU CH582】5、硬件I2C驱动0.96吋OLED</a>,本文移植u8g2图形库来驱动OLED。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">2、关于u8g2库</span></p>

<p><span style="font-size:16px;">u8g2是单色显示库的第二个版本。支持lcd和oled,支持众多驱动芯片,比如SSD1305, SSD1306, SSD1309, SSD1312, SSD1316, SSD1320, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1108, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1617, UC1638, UC1701, ST7511, ST7528, ST7565, ST7567, ST7571, ST7586, ST7588, ST75256, ST75320, NT7534, ST7920, IST3020, IST7920, LD7032, KS0108, KS0713, HD44102, T7932, SED1520, SBN1661, IL3820, MAX7219等。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">开源,可直接下载代码移植:https://github.com/olikraus/u8g2。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">3、移植</span></p>

<p><span style="font-size:16px;">(1)直接从github下载代码,u8g2支持c/c++</span>&nbsp;,csrc文件夹下面是c源码</p>

<p></p>

<p><span style="font-size:16px;">(2)u8g2里面支持多种芯片,这里添加自己与自己芯片对应的,以u8x8_d_xxx.c命名的就是驱动文件,这里我们使用的ssd1306,因此只需将u8x8_d_ssd1312_128x64_noname.c这个驱动文件添加到工程中</span></p>

<p></p>

<p><span style="font-size:16px;">(3)修改&quot;u8g2_d_setup.c&quot;这个文件,删除其他函数只留下自己器件相关的。由于我用的硬件IIC,而且因为自己单片机空间较大所以选择后缀为f的函数使用,即我选择的是&quot;u8g2_Setup_ssd1306_i2c_128x64_noname_f&quot;这个函数,其他都删除了。当然也可以使用后缀为1或者2的函数,比较省空间,但是自然的会比较耗时。</span></p>

<p></p>

<p><span style="font-size:16px;">(4)修改&ldquo;u8g2_d_memory.c&rdquo;文件,这个文件里面其实就是&ldquo;u8g2_d_setup.c&rdquo;文件对应的缓冲区,同上面一样,屏蔽掉没用到的,留下用到的。</span></p>

<p></p>

<p><span style="font-size:16px;">(5)关于字库</span></p>

<p><span style="font-size:16px;">&ldquo;u8g2_fonts.c&rdquo;文件中定义了各种字库,这些字库比较占用空间,根据使用情况屏蔽掉没有使用的。&nbsp;</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">(6)两个回调函数</span></p>

<p><span style="font-size:16px;">void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);</span></p>

<p>参数<span style="font-size:16px;">byte_cb和gpio_and_delay_cb是需要编写的两个回调函数。</span></p>

<p><span style="font-size:16px;">byte_cb是硬件接口相关的函数,gpio_and_delay_cb是关于io口操作延时相关的函数。</span></p>

<p><span style="font-size:16px;">关于回调函数的写法可以参考官方的描述:</span><a>https://github.com/olikraus/u8g2/wiki/Porting-to-new-MCU-platform,,针对at32f425的如下:</a></p>

<pre>
<code>uint8_t u8x8_byte_at32f425_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
        static uint8_t buffer;                /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
        static uint8_t buf_idx;
        uint8_t *data;

        switch(msg)
        {
                case U8X8_MSG_BYTE_SEND:
                  data = (uint8_t *)arg_ptr;      
                  while( arg_int &gt; 0 ){
                                        buffer = *data;
                                        data++;
                                        arg_int--;
                                }      
                break;
                               
                case U8X8_MSG_BYTE_INIT:
                  /* add your custom code to init i2c subsystem */
                break;
                       
                case U8X8_MSG_BYTE_START_TRANSFER:
                  buf_idx = 0;
                break;
                       
                case U8X8_MSG_BYTE_END_TRANSFER:
                        HW_I2cWrite(buffer,buf_idx);
                break;
                       
                default:
                  return 0;
        }
        return 1;
}</code></pre>

<pre>
<code>uint8_t u8g2_gpio_and_delay_at32f425(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
        switch(msg)
        {
                case U8X8_MSG_GPIO_AND_DELAY_INIT:
                        break;
                       
                case U8X8_MSG_DELAY_MILLI:
                        delay_ms(arg_int);
                        break;
                       
                case U8X8_MSG_GPIO_I2C_CLOCK:               
                        break;                                                       
                       
                case U8X8_MSG_GPIO_I2C_DATA:                       
                        break;
                       
                default:       
                        return 0;
        }
        return 1; // command processed successfully.
}</code></pre>

<p>&nbsp;u8x8_byte_at32f425_hw_i2c函数中关于硬件i2c写的具体函数如下:</p>

<pre>
<code>void HW_I2cWrite(uint8_t *buf,uint8_t len)
{
        if(len&lt;=0)
                return ;

        /* wait for the busy falg to be reset */
        while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) );

        /* start transfer */
        i2c_transmit_set(I2C1, I2C_SLAVE_ADDRESS7, len, I2C_SOFT_STOP_MODE, I2C_GEN_START_WRITE);

        i2c_start_generate(I2C1);
        while(i2c_flag_get(I2C1, I2C_ADDRF_FLAG) );

        for(uint8_t i=0;i&lt;len;i++)
        {
                while(!i2c_flag_get(I2C1, I2C_TDIS_FLAG) );
                i2c_data_send(I2C1, buf);
        }
        i2c_stop_generate(I2C1);

        while(!i2c_flag_get(I2C1, I2C_STOPF_FLAG) );
        i2c_flag_clear(I2C1, I2C_STOPF_FLAG);
}</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:26px;">4、代码测试</span></p>

<pre>
<code>static u8g2_t u8g2;

void U8g2Init(void)
{
        HW_I2cInit();
        u8g2_Setup_ssd1306_i2c_128x64_noname_f(&amp;u8g2,U8G2_R0,u8x8_byte_at32f425_hw_i2c,u8g2_gpio_and_delay_at32f425);

        u8g2_InitDisplay(&amp;u8g2); // send init sequence to the display, display is in sleep mode after this,
        u8g2_SetPowerSave(&amp;u8g2, 0); // wake up display       
        u8g2_ClearBuffer(&amp;u8g2);
       
        void DrawLogo(void);
        DrawLogo();
}

void DrawLogo(void)
{
    u8g2_SetFontMode(&amp;u8g2, 1); /*字体模式选择*/
    u8g2_SetFontDirection(&amp;u8g2, 0); /*字体方向选择*/
    u8g2_SetFont(&amp;u8g2, u8g2_font_inb24_mf); /*字库选择*///u8g2_font_inb24_mf
    u8g2_DrawStr(&amp;u8g2, 0, 20, "U");
   
    u8g2_SetFontDirection(&amp;u8g2, 1);
    u8g2_SetFont(&amp;u8g2, u8g2_font_inb30_mn); //u8g2_font_inb30_mn
    u8g2_DrawStr(&amp;u8g2, 21,8,"8");
      
    u8g2_SetFontDirection(&amp;u8g2, 0);
    u8g2_SetFont(&amp;u8g2, u8g2_font_inb24_mf); //u8g2_font_inb24_mf
    u8g2_DrawStr(&amp;u8g2, 51,30,"g");
    u8g2_DrawStr(&amp;u8g2, 67,30,"\xb2");
   
    u8g2_DrawHLine(&amp;u8g2, 2, 35, 47);
    u8g2_DrawHLine(&amp;u8g2, 3, 36, 47);
    u8g2_DrawVLine(&amp;u8g2, 45, 32, 12);
    u8g2_DrawVLine(&amp;u8g2, 46, 33, 12);

    u8g2_SetFont(&amp;u8g2, u8g2_font_4x6_tr);//u8g2_font_4x6_tr
    u8g2_DrawStr(&amp;u8g2, 1,54,"github.com/olikraus/u8g2");
       
        u8g2_SendBuffer(&amp;u8g2);
}
</code></pre>

<p><span style="font-size:26px;">5、显示</span></p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

lugl4313820 发表于 2022-4-26 08:56

有没有显示中文的字库呀?还有占有空间大吗?

freeelectron 发表于 2022-4-26 09:00

lugl4313820 发表于 2022-4-26 08:56
有没有显示中文的字库呀?还有占有空间大吗?

<p>有的,搜了一下,其中的一个中文字库,14k</p>

<p> &nbsp;</p>
页: [1]
查看完整版本: 【AT-START-F425测评】+移植u8g2单色图形库驱动0.96吋OLED