前面使用NKIA5110的显示屏制作了低功耗时间。这一篇,我将分享如何移植U8g2来实现图形化的界面。
【移植】
1、首先到github上下载一个开源的stm32f103的基于NKIA5110LCD屏的开源项目。
2、修改uint8_t u8x8_stm32_gpio_and_delay(u8x8_t u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr)函数中的几个GPIO的时钟,修改后的代码如下:
//This Function will independtly keep the screen running by init GPIO it self
uint8_t u8x8_stm32_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8
break; // can be used to setup pins
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
delay_us(1);
break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
delay_us(100);
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
delay_ms(10);
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
__NOP();
break;
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
break; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int
arg_int?HAL_GPIO_WritePin(SCREENGPIOGROUP, SCKPIN, GPIO_PIN_SET):HAL_GPIO_WritePin(SCREENGPIOGROUP, SCKPIN, GPIO_PIN_RESET);
break;
case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int
arg_int?HAL_GPIO_WritePin(SCREENGPIOGROUP, DATAPIN, GPIO_PIN_SET):HAL_GPIO_WritePin(SCREENGPIOGROUP, DATAPIN, GPIO_PIN_RESET);
break;
case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_CS: // CS CE (chip select) pin: Output level in arg_int
arg_int?HAL_GPIO_WritePin(SCREENGPIOGROUP, CEPIN, GPIO_PIN_SET):HAL_GPIO_WritePin(SCREENGPIOGROUP, CEPIN, GPIO_PIN_RESET);
break;
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
arg_int?HAL_GPIO_WritePin(SCREENGPIOGROUP, DCPIN, GPIO_PIN_SET):HAL_GPIO_WritePin(SCREENGPIOGROUP, DCPIN, GPIO_PIN_RESET);
break;
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
arg_int?HAL_GPIO_WritePin(GPIOB, RSTPIN, GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB, RSTPIN, GPIO_PIN_RESET);
//Set/Reset Bit in OneLine
break;
case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int
break;
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;
}
3、定义一个初始化的函数:
void InitNokia5110(u8g2_t *u8g2){
u8g2_Setup_pcd8544_84x48_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8x8_stm32_gpio_and_delay); // init u8g2 structure
u8g2_InitDisplay(u8g2); // send init sequence to the display, display is in sleep mode after this,
u8g2_SetPowerSave(u8g2, 0); // wake up display
u8g2_ClearBuffer(u8g2);
}
4、同时还需要提供三个延时函数给U8g2:

5、最后把u8g2文件夹下的csrc的文件添加到工程中:


LCD驱动为u8x8_d_pcd8544_84x48.c
6、添加测试代码如下:
InitNokia5110(&u8g2); //Screen Init
uint8_t t = 2;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
u8g2_FirstPage(&u8g2);
u8g2_SetFontMode(&u8g2, 1); /*字体模式选择*/
u8g2_SetFontDirection(&u8g2, 0);
u8g2_SetFont(&u8g2, u8g2_font_amstrad_cpc_extended_8u);
// 绘制时钟表盘
u8g2_DrawCircle(&u8g2,40, 24, 16, U8G2_DRAW_ALL);
u8g2_DrawCircle(&u8g2,40, 24, 15, U8G2_DRAW_ALL);
// 计算时针、分针、秒针的角度
float second_angle = (sTime.Seconds / 60.0) * 360;
float minute_angle = ((sTime.Minutes + sTime.Seconds / 60.0) / 60.0) * 360;
float hour_angle = ((sTime.Hours % 12 + sTime.Minutes / 60.0) / 12.0) * 360;
// 计算时针、分针、秒针的终点坐标
int center_x = 40 ;
int center_y = 24;
int second_x = center_x + 15 * sin(second_angle * 3.1415926 / 180);
int second_y = center_y - 15 * cos(second_angle * 3.1415926 / 180);
int minute_x = center_x + 12 * sin(minute_angle * 3.1415926 / 180);
int minute_y = center_y - 12 * cos(minute_angle * 3.1415926 / 180);
int hour_x = center_x + 10 * sin(hour_angle * 3.1415926 / 180);
int hour_y = center_y - 10 * cos(hour_angle * 3.1415926 / 180);
// 绘制时针、分针、秒针
u8g2_DrawLine(&u8g2, center_x, center_y, second_x, second_y);
u8g2_DrawLine(&u8g2, center_x, center_y, minute_x, minute_y);
u8g2_DrawLine(&u8g2, center_x, center_y, hour_x, hour_y);
// 绘制数字时间
char time_str[20];
sprintf(time_str, "%02d:%02d:%02d", sTime.Hours, sTime.Minutes, sTime.Seconds);
u8g2_DrawStr(&u8g2, 10, 8, time_str);
// 发送缓冲区内容到屏幕
u8g2_SendBuffer(&u8g2);
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
}
}
实现效果如下:
