(硬件SPI代码已测试,硬件I2C代码未测试)
一、源码下载
U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动。
U8g2源码的开源库地址:https://github.com/olikraus/u8g2
二、移植修改
U8g2 的官方移植教程 https://github.com/olikraus/u8g2/wiki/Porting-to-new-MCU-platform
1. 只保留csrc文件夹内容
2.u8x8_d_器件名.c
csrc下的文件,其中u8x8_d_器件名.c
的文件只需保留自己对应的显示器驱动芯片即可,比如OLED12864显示器,显示器驱动为SSD1306,分辨率为128x64,选择的文件为u8x8_d_ssd1306_128x64_noname.c
3. 修改u8g2_d_setup.c
文件
只保留自己使用的芯片对应的setup文件。u8g2_Setup_ssd1306_128x64_noname_f
4.修改u8g2_d_memory.c
它需要根据 u8g2_d_setup.c
中的调用情况决定用到哪些函数。由于 u8g2_Setup_ssd1306_i2c_128x64_noname_f()
函数只用到 u8g2_m_16_8_f()
这一个函数,因此只需要保留它,其余函数全部删除即可
4.精简字体文件
u8x8_fonts.c
和 u8g2_fonts.c
,尤其是 u8g2_fonts.c
字体类型的变量非常多,建议先复制一个备份后将所有变量删除,之后视情况再添加字体。字体变量的命名大致遵循以下规则:
5. 回调
创建u8g2_init.h
#ifndef __U8G2_INIT_H__
#define __U8G2_INIT_H__
#include "main.h"
#include "u8g2.h"
void u8g2Init(u8g2_t *u8g2);
uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr);
/*Hw I2C*/
//uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
#endif
创建u8g2_init.c
#include "u8g2.h"
#include "u8g2_init.h"
#include "main.h"
#include "spi.h"
//#include "i2c.h"
/*硬件SPI回调函数*/
uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_BYTE_SEND: /*通过SPI发送arg_int个字节数据*/
// HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)arg_ptr, arg_int);while(hspi1.TxXferCount);
//使用DMA可以将上面的注释解除,把下面不带DMA的给注释掉
HAL_SPI_Transmit(&hspi1,(uint8_t *)arg_ptr,arg_int,200);
break;
case U8X8_MSG_BYTE_INIT: /*初始化函数*/
break;
case U8X8_MSG_BYTE_SET_DC: /*设置DC引脚,表明发送的是数据还是命令*/
HAL_GPIO_WritePin(OLED_DC_GPIO_Port,OLED_DC_Pin,arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
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_GPIO_AND_DELAY_INIT: /*delay和GPIO的初始化,在main中已经初始化完成了*/
break;
case U8X8_MSG_DELAY_MILLI: /*延时函数*/
HAL_Delay(arg_int); //调用谁stm32系统延时函数
break;
case U8X8_MSG_GPIO_CS: /*片选信号*/ //由于只有一个SPI设备,所以片选信号在初始化时已经设置为为常有效
HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, arg_int);
break;
case U8X8_MSG_GPIO_DC: /*设置DC引脚,表明发送的是数据还是命令*/
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
break;
case U8X8_MSG_GPIO_RESET:
break;
}
return 1;
}
void u8g2Init(u8g2_t *u8g2)
{
HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, GPIO_PIN_SET); //显示器复位拉高
u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_4wire_hw_spi, u8x8_gpio_and_delay); // 初始化0.96寸OLED u8g2 结构体
u8g2_InitDisplay(u8g2); //初始化显示
u8g2_SetPowerSave(u8g2, 0); //开启显示
}
///*硬件I2C HAL (未测试)*/
// uint8_t u8x8_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:
// break;
//
// case U8X8_MSG_DELAY_MILLI:
// HAL_Delay(arg_int);//change it!
// break;
//
// default:
// return 0;
// }
// return 1; // command processed successfully.
//}
//uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
//{
// static uint8_t buffer[32]; /* 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 > 0 )
// {
// buffer[buf_idx++] = *data;
// data++;
// arg_int--;
// }
// break;
// case U8X8_MSG_BYTE_INIT:
// /* add your custom code to init i2c subsystem */
// break;
// case U8X8_MSG_BYTE_SET_DC:
// /* ignored for i2c */
// break;
// case U8X8_MSG_BYTE_START_TRANSFER:
// buf_idx = 0;
// break;
// case U8X8_MSG_BYTE_END_TRANSFER:
// HAL_I2C_Master_Transmit(&hi2c1,u8x8_GetI2CAddress(u8x8), buffer, buf_idx,0x100);//change it
// break;
// default:
// return 0;
// }
// return 1;
//}
//void u8g2Init(u8g2_t *u8g2)
//{
// HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, GPIO_PIN_SET); //显示器复位拉高
// u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8x8_gpio_and_delay); // 初始化0.96寸OLED u8g2 结构体
// u8g2_InitDisplay(u8g2); //初始化显示
// u8g2_SetPowerSave(u8g2, 0); //开启显示
//}
三、调试
1.mybmp.c & mybmp.h
Img2Lcd软件转换图片为bmp格式
生成字模
mybmp.c
#include "mybmp.h"
const uint8_t Cuteghost_BMP[] = {
/*字模
*/
/* 32*32 */
};
const uint8_t Lighting_BMP[] = {
/*字模
*/
/* 32*32 */
};
//...........自行添加
mybmp.h
#ifndef __MYBMP_H
#define __MYBMP_H
extern const uint8_t Lighting_BMP[];
extern const uint8_t Cuteghost_BMP[];
//.........
#endif
2.main.c添加或修改
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "u8g2_init.h"
#include "AHT10.h"
#include "appheart.h"
#include "mybmp.h"
extern uint16_t usPulse[128]; //心率采集缓存数组
extern uint8_t ucPos; //心率数据保存位置
u8g2_t u8g2;
/* USER CODE END Includes */ //添加
int main(void)
{
ahtData_t AhtData;
uint8_t i;
uint8_t ucPulse = 0;
uint16_t usMaxValue = 0;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_I2C2_Init();
MX_USART1_UART_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
u8g2Init(&u8g2);
u8g2_ClearBuffer(&u8g2);
while (1)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
/*AHT10*/
char temDataTime[10];
char humDataTime[10];
AHT10_Read_predata(&AhtData);
sprintf(temDataTime, "TEM: %.1f C", AhtData.temp);
sprintf(humDataTime, "HUM: %d% %", (uint8_t)AhtData.humi);
u8g2_SendBuffer(&u8g2);
// u8g2_SetFont(&u8g2, u8g2_font_DigitalDiscoThin_tf);
u8g2_SetFont(&u8g2, u8g2_font_ncenB12_tf);
// u8g2_SetFont(&u8g2, u8g2_font_inb24_mf); //选择字库,选谁,打开谁
u8g2_DrawStr(&u8g2, 3,20,temDataTime);
u8g2_DrawStr(&u8g2, 3,40,humDataTime);
/*Pulse Sensor*/
char heartDataTime[10];
HAL_ADC_Start(&hadc1);
getPulse(&ucPulse, &usMaxValue);
if(ucPos == 0)
{
for(i=0;i<128;i++)
{
}
sprintf(heartDataTime, "BPM: %d", ucPulse);
u8g2_DrawStr(&u8g2, 3,60,heartDataTime);
printf("心率%d/分钟 \n",ucPulse);
}
printf("温度:%d/n",(uint8_t)AhtData.humi);
printf("湿度:%d/n",(uint8_t)AhtData.temp);
HAL_Delay(20);
/*图像*/
// u8g2_SendBuffer(&u8g2);
// u8g2_DrawBox(&u8g2, 19, 25, 20, 20);
// u8g2_DrawFrame(&u8g2, 10, 45, 19, 19);
// u8g2_SetFont(&u8g2, u8g2_font_DigitalDiscoThin_tf);
// u8g2_DrawStr(&u8g2, 0, 18, "Cold-blooded");
// u8g2_SetFont(&u8g2, u8g2_font_inb24_mf);
// u8g2_DrawStr(&u8g2, 100, 25, "M");
// u8g2_DrawXBMP(&u8g2, 50, 30, 32, 32, Lighting_BMP);
// u8g2_DrawXBMP(&u8g2, 90, 30, 32, 32, Cuteghost_BMP);
// HAL_Delay(200);
}
}