【沁恒微CH32V307评估板试用体验】硬件I2C移植U8g2——OLED:SSD1306 - RISC-V MCU技术社区 - 电子技术william hill官网 - 广受欢迎的专业电子william hill官网 - 威廉希尔官方网站
分享 收藏 返回

[文章]

【沁恒微CH32V307评估板试用体验】硬件I2C移植U8g2——OLED:SSD1306

【U8g2】U8g2是嵌入式设备的单色图形库,一句话简单明了
【前言】网上找了其他的移植例程,但是移植到CH32V307的好象还没有,我花了两天时间把移植的过程记录如下。
1、要完成硬件i2c的移植,首先要驱动CH32V307的硬件I2C。驱动示例烦请大家移步我前的帖子:【新提醒】【沁恒微CH32V307评估板试用体验】SSD1306之HELLOWORLD
2、网上下载u8g2的源码,官方地址为:U8g2下载地址https://github.com/olikraus/u8g2
3、下载完后解压驱动包,选取csrc目录。
选择u8g2目录.png
3、把csrc目录复制到CH32V307的工程目录下面:
复制目录到工程.png
4、删除不用的驱动文件,因为我使用的是ssd1306,即只保留u8x8_d_ssd1306_128x64_noname.c,其余u8X8_d_xxxx.c都可以删除掉:
删除掉u8x8_d_xxx.png
5、修改u8g2_d_setup.c文件,只保留自己使用的芯片对应的setup文件。比如我选择的是u8g2_Setup_ssd1306_128x64_noname_f,控制芯片SSD1306,分辨率128x64,1024字节页大小。
  1. /* u8g2_d_setup.c */
  2. /* generated code, codebuild, u8g2 project */

  3. #include "u8g2.h"

  4. /* ssd1306 1 */

  5. /* ssd1306 f */
  6. 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)
  7. {
  8.   uint8_t tile_buf_height;
  9.   uint8_t *buf;
  10.   u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
  11.   buf = u8g2_m_16_8_f(&tile_buf_height);
  12.   u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_l***, rotation);
  13. }

  14. /* end of generated code */
6、在我原来的i2c初始化my_ii2中书写如下4个函数:

  1. void IIC_send_data(uint8_t *data,uint8_t len )
  2. {
  3.     if (len<=0) {
  4.         return;
  5.     }
  6.     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  7.             ;
  8.         I2C_GenerateSTART(I2C1, ENABLE);
  9.         while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
  10.             ;
  11.         I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);

  12.         while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  13.             ;
  14.         for (uint8_t i = 0;  i < len; ++ i) {
  15.             if(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) != RESET)
  16.                {
  17.                    I2C_SendData(I2C1, data[i]);

  18.                }
  19.             while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET);
  20.          }

  21.         while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  22.                 ;
  23.         I2C_GenerateSTOP(I2C1, ENABLE);
  24. }

  25. uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  26. {
  27.     /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
  28.     static uint8_t buffer[128];
  29.     static uint8_t buf_idx;
  30.     uint8_t *data;

  31.     switch (msg)
  32.     {
  33.     case U8X8_MSG_BYTE_INIT:
  34.     {
  35.         /* add your custom code to init i2c subsystem */
  36.         IIC_Init(400000,OLED_ADDRESS); //I2C初始化
  37.     }
  38.     break;

  39.     case U8X8_MSG_BYTE_START_TRANSFER:
  40.     {
  41.         buf_idx = 0;

  42.     }
  43.     break;

  44.     case U8X8_MSG_BYTE_SEND:
  45.     {
  46.         data = (uint8_t *)arg_ptr;
  47.         while (arg_int > 0)
  48.         {
  49.             buffer[buf_idx++] = *data;
  50.             data++;
  51.             arg_int--;
  52.         }
  53.     }
  54.     break;

  55.     case U8X8_MSG_BYTE_END_TRANSFER:
  56.     {
  57.         IIC_send_data(buffer,buf_idx);
  58.     }
  59.     break;

  60.     case U8X8_MSG_BYTE_SET_DC:
  61.         break;

  62.     default:
  63.         return 0;
  64.     }

  65.     return 1;
  66. }

  67. uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  68. {
  69.     switch (msg)
  70.     {
  71.     case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
  72.         __NOP();
  73.         break;
  74.     case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
  75.         for (uint16_t n = 0; n < 320; n++)
  76.         {
  77.             __NOP();
  78.         }
  79.         break;
  80.     case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
  81.         Delay_Ms(500);
  82.         break;
  83.     case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
  84.         Delay_Us(1);
  85.         break;                    // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
  86.     case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
  87.         break;                    // arg_int=1: Input dir with pullup high for I2C clock pin
  88.     case U8X8_MSG_GPIO_I2C_DATA:  // arg_int=0: Output low at I2C data pin
  89.         break;                    // arg_int=1: Input dir with pullup high for I2C data pin
  90.     case U8X8_MSG_GPIO_MENU_SELECT:
  91.         u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
  92.         break;
  93.     case U8X8_MSG_GPIO_MENU_NEXT:
  94.         u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
  95.         break;
  96.     case U8X8_MSG_GPIO_MENU_PREV:
  97.         u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
  98.         break;
  99.     case U8X8_MSG_GPIO_MENU_HOME:
  100.         u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
  101.         break;
  102.     default:
  103.         u8x8_SetGPIOResult(u8x8, 1); // default return value
  104.         break;
  105.     }
  106.     return 1;
  107. }
  108. void u8g2Init(u8g2_t *u8g2)
  109. {
  110.     u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay); // 初始化 u8g2 结构体
  111.     u8g2_InitDisplay(u8g2);                                                                       // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
  112.     u8g2_SetPowerSave(u8g2, 0);                                                                   // 打开显示器
  113.     u8g2_ClearBuffer(u8g2);
  114. }
7、完成以面的步骤后,到u8g_d_memory.c,删去不用的函数,只留u8g2_m_16_8_f函数。

8、到这里移植的工作就完成了,在主程序里引用 u8g2.h,创建结构体u8g2_t u8g2。man.c如下:
  1. u8g2_t u8g2; // a structure which will contain all the data for one display

  2. /*官方提供的Log绘制demo*/
  3. void test_draw(void)
  4. {
  5.    u8g2_ClearBuffer(&u8g2);
  6.    u8g2_SendBuffer(&u8g2);
  7.    u8g2_SetFontMode(&u8g2, 1); /*字体模式选择*/
  8.    u8g2_SetFontDirection(&u8g2, 0); /*字体方向选择*/
  9.    u8g2_SetFont(&u8g2, u8g2_font_inb24_mf); /*字库选择*/
  10.    u8g2_DrawStr(&u8g2, 0, 20, "U");

  11.    u8g2_SetFontDirection(&u8g2, 1);
  12.    u8g2_SetFont(&u8g2, u8g2_font_inb30_mn);
  13.    u8g2_DrawStr(&u8g2, 21,8,"8");

  14.    u8g2_SetFontDirection(&u8g2, 0);
  15.    u8g2_SetFont(&u8g2, u8g2_font_inb24_mf);
  16.    u8g2_DrawStr(&u8g2, 51,30,"g");
  17.    u8g2_DrawStr(&u8g2, 67,30,"xb2");

  18.    u8g2_DrawHLine(&u8g2, 2, 35, 47);
  19.    u8g2_DrawHLine(&u8g2, 3, 36, 47);
  20.    u8g2_DrawVLine(&u8g2, 45, 32, 12);
  21.    u8g2_DrawVLine(&u8g2, 46, 33, 12);

  22.    u8g2_SetFont(&u8g2, u8g2_font_4x6_tr);
  23.    u8g2_DrawStr(&u8g2, 1,54,"github.com/olikraus/u8g2");
  24.    u8g2_SendBuffer(&u8g2);
  25.    Delay_Ms(1000);
  26.   u8g2_SendBuffer(&u8g2);
  27.   u8g2_DrawBox(&u8g2,0,0,20,20);
  28.   u8g2_SendBuffer(&u8g2);
  29.   Delay_Ms(1000);
  30.   u8g2_DrawBox(&u8g2,20,20,20,20);
  31.   u8g2_SendBuffer(&u8g2);
  32.   Delay_Ms(1000);
  33.   u8g2_DrawFrame(&u8g2,10,40,20,20);
  34.   u8g2_SendBuffer(&u8g2);
  35.   Delay_Ms(1000);
  36.   u8g2_SetFont(&u8g2,u8g2_font_DigitalDiscoThin_tf);
  37.   u8g2_DrawStr(&u8g2,30,10,"TEST by LUGL");
  38.   u8g2_SendBuffer(&u8g2);
  39.   Delay_Ms(1000);
  40.   u8g2_DrawStr(&u8g2,60,60,"U8G2..");
  41.   u8g2_SendBuffer(&u8g2);
  42.   Delay_Ms(1000);
  43.   u8g2_DrawStr(&u8g2,50,30,"CH32V307");
  44.   u8g2_SendBuffer(&u8g2);
  45. }


  46. /*********************************************************************
  47. * @fn      main
  48. *
  49. * [url=home.php?mod=space&uid=2666770]@Brief[/url]   Main program.
  50. *
  51. * [url=home.php?mod=space&uid=1141835]@Return[/url]  none
  52. */
  53. int main(void)
  54. {
  55.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  56.         Delay_Init();
  57.         USART_Printf_Init(115200);
  58.         printf("SystemClk:%drn",SystemCoreClock);
  59.         printf("This is printf examplern");
  60.         u8g2Init(&u8g2);
  61.         while(1)
  62.     {
  63.             test_draw();

  64.        Delay_Ms(2000);
  65.         }
  66. }
【总结】u8g2的移植我是手工第一次,主要是编写两个回调函数。花了两天时间,但是学会以后,移植到其他的芯片上就非常方便了。使用I2C硬件驱动,速非常快。但是使用u8g2还得花一定的时间。




u8g2

回帖(2)

dianzi

2022-5-23 09:54:59
华仔哥 发报告速度真的赞

dianzi

2022-5-23 09:55:35
华仔哥 发报告速度真的赞
3 1

更多回帖

×
发帖