【U8g2】U8g2是嵌入式设备的单色图形库,一句话简单明了
【前言】网上找了其他的移植例程,但是移植到CH32V307的好象还没有,我花了两天时间把移植的过程记录如下。
1、要完成硬件i2c的移植,首先要驱动CH32V307的硬件I2C。驱动示例烦请大家移步我前的帖子:【新提醒】【沁恒微CH32V307评估板试用体验】SSD1306之HELLOWORLD
2、网上下载u8g2的源码,官方地址为:U8g2下载地址https://github.com/olikraus/u8g2。
3、下载完后解压驱动包,选取csrc目录。
3、把csrc目录复制到CH32V307的工程目录下面:
4、删除不用的驱动文件,因为我使用的是ssd1306,即只保留u8x8_d_ssd1306_128x64_noname.c,其余u8X8_d_xxxx.c都可以删除掉:
5、修改u8g2_d_setup.c文件,只保留自己使用的芯片对应的setup文件。比如我选择的是u8g2_Setup_ssd1306_128x64_noname_f,控制芯片SSD1306,分辨率128x64,1024字节页大小。
- /* u8g2_d_setup.c */
- /* generated code, codebuild, u8g2 project */
- #include "u8g2.h"
- /* ssd1306 1 */
- /* ssd1306 f */
- 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)
- {
- uint8_t tile_buf_height;
- uint8_t *buf;
- u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_fast_i2c, byte_cb, gpio_and_delay_cb);
- buf = u8g2_m_16_8_f(&tile_buf_height);
- u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_l***, rotation);
- }
- /* end of generated code */
6、在我原来的i2c初始化my_ii2中书写如下4个函数:
- void IIC_send_data(uint8_t *data,uint8_t len )
- {
- if (len<=0) {
- return;
- }
- while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
- ;
- I2C_GenerateSTART(I2C1, ENABLE);
- 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))
- ;
- for (uint8_t i = 0; i < len; ++ i) {
- if(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) != RESET)
- {
- I2C_SendData(I2C1, data[i]);
- }
- while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET);
- }
- while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
- ;
- I2C_GenerateSTOP(I2C1, ENABLE);
- }
- uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
- {
- /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
- static uint8_t buffer[128];
- static uint8_t buf_idx;
- uint8_t *data;
- switch (msg)
- {
- case U8X8_MSG_BYTE_INIT:
- {
- /* add your custom code to init i2c subsystem */
- IIC_Init(400000,OLED_ADDRESS); //I2C初始化
- }
- break;
- case U8X8_MSG_BYTE_START_TRANSFER:
- {
- buf_idx = 0;
- }
- break;
- case U8X8_MSG_BYTE_SEND:
- {
- data = (uint8_t *)arg_ptr;
- while (arg_int > 0)
- {
- buffer[buf_idx++] = *data;
- data++;
- arg_int--;
- }
- }
- break;
- case U8X8_MSG_BYTE_END_TRANSFER:
- {
- IIC_send_data(buffer,buf_idx);
- }
- break;
- case U8X8_MSG_BYTE_SET_DC:
- break;
- default:
- return 0;
- }
- return 1;
- }
- uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
- {
- switch (msg)
- {
- case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
- __NOP();
- break;
- case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
- for (uint16_t n = 0; n < 320; n++)
- {
- __NOP();
- }
- break;
- case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
- Delay_Ms(500);
- break;
- case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
- Delay_Us(1);
- break; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
- case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
- break; // arg_int=1: Input dir with pullup high for I2C clock pin
- case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin
- break; // arg_int=1: Input dir with pullup high for I2C data pin
- case U8X8_MSG_GPIO_MENU_SELECT:
- u8x8_SetGPIOResult(u8x8, /* get menu select pin state */ 0);
- break;
- case U8X8_MSG_GPIO_MENU_NEXT:
- u8x8_SetGPIOResult(u8x8, /* get menu next pin state */ 0);
- break;
- case U8X8_MSG_GPIO_MENU_PREV:
- u8x8_SetGPIOResult(u8x8, /* get menu prev pin state */ 0);
- break;
- case U8X8_MSG_GPIO_MENU_HOME:
- u8x8_SetGPIOResult(u8x8, /* get menu home pin state */ 0);
- break;
- default:
- u8x8_SetGPIOResult(u8x8, 1); // default return value
- break;
- }
- return 1;
- }
- void u8g2Init(u8g2_t *u8g2)
- {
- u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay); // 初始化 u8g2 结构体
- u8g2_InitDisplay(u8g2); // 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
- u8g2_SetPowerSave(u8g2, 0); // 打开显示器
- u8g2_ClearBuffer(u8g2);
- }
7、完成以面的步骤后,到u8g_d_memory.c,删去不用的函数,只留u8g2_m_16_8_f函数。
8、到这里移植的工作就完成了,在主程序里引用 u8g2.h,创建结构体u8g2_t u8g2。man.c如下:
- u8g2_t u8g2; // a structure which will contain all the data for one display
- /*官方提供的Log绘制demo*/
- void test_draw(void)
- {
- u8g2_ClearBuffer(&u8g2);
- u8g2_SendBuffer(&u8g2);
- u8g2_SetFontMode(&u8g2, 1); /*字体模式选择*/
- u8g2_SetFontDirection(&u8g2, 0); /*字体方向选择*/
- u8g2_SetFont(&u8g2, u8g2_font_inb24_mf); /*字库选择*/
- u8g2_DrawStr(&u8g2, 0, 20, "U");
- u8g2_SetFontDirection(&u8g2, 1);
- u8g2_SetFont(&u8g2, u8g2_font_inb30_mn);
- u8g2_DrawStr(&u8g2, 21,8,"8");
- u8g2_SetFontDirection(&u8g2, 0);
- u8g2_SetFont(&u8g2, u8g2_font_inb24_mf);
- u8g2_DrawStr(&u8g2, 51,30,"g");
- u8g2_DrawStr(&u8g2, 67,30,"xb2");
- u8g2_DrawHLine(&u8g2, 2, 35, 47);
- u8g2_DrawHLine(&u8g2, 3, 36, 47);
- u8g2_DrawVLine(&u8g2, 45, 32, 12);
- u8g2_DrawVLine(&u8g2, 46, 33, 12);
- u8g2_SetFont(&u8g2, u8g2_font_4x6_tr);
- u8g2_DrawStr(&u8g2, 1,54,"github.com/olikraus/u8g2");
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_SendBuffer(&u8g2);
- u8g2_DrawBox(&u8g2,0,0,20,20);
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_DrawBox(&u8g2,20,20,20,20);
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_DrawFrame(&u8g2,10,40,20,20);
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_SetFont(&u8g2,u8g2_font_DigitalDiscoThin_tf);
- u8g2_DrawStr(&u8g2,30,10,"TEST by LUGL");
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_DrawStr(&u8g2,60,60,"U8G2..");
- u8g2_SendBuffer(&u8g2);
- Delay_Ms(1000);
- u8g2_DrawStr(&u8g2,50,30,"CH32V307");
- u8g2_SendBuffer(&u8g2);
- }
- /*********************************************************************
- * @fn main
- *
- * [url=home.php?mod=space&uid=2666770]@Brief[/url] Main program.
- *
- * [url=home.php?mod=space&uid=1141835]@Return[/url] none
- */
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%drn",SystemCoreClock);
- printf("This is printf examplern");
- u8g2Init(&u8g2);
- while(1)
- {
- test_draw();
- Delay_Ms(2000);
- }
- }
【总结】u8g2的移植我是手工第一次,主要是编写两个回调函数。花了两天时间,但是学会以后,移植到其他的芯片上就非常方便了。使用I2C硬件驱动,速非常快。但是使用u8g2还得花一定的时间。