返回

stm32f103c8t6 库移植

目录

本教程使用的是标准库

u8g2

“u8g2 github”
“u8g2 官方的移植文档”

Pre

  1. 只要复制csrc文件夹改名称为u8g2_libs
  2. 对于u8g2_d_*** 的文件,保留你屏幕使用的驱动,这里使用ssd_1306,所以选择u8g2_d_ssd1306_128x64_noname_f
  3. 精简u8g2_fonts.c,u8g2_d_setup.c, u8g2_d_memory.c 对于 u8g2_fonts 建议是根据需要保留字体
    “u8g2 字体查看”
    对于 u8g2_d_setup.c 保留这个函数 u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay)
    对于 u8g2_d_memory.c 只要保留上面使用到的 u8g2_m_16_8_f(&tile_buf_height);

软件iic

u8g2提供的模板,需要你自己填写,建议放在存放u8g2_init函数的文件内:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
uint8_t u8x8_gpio_and_delay_template(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
      break;    
    case U8X8_MSG_DELAY_100NANO:		// delay arg_int * 100 nano seconds
      break;
    case U8X8_MSG_DELAY_10MICRO:		// delay arg_int * 10 micro seconds
      break;
    case U8X8_MSG_DELAY_MILLI:			// delay arg_int * 1 milli second
      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
    //case U8X8_MSG_GPIO_SPI_CLOCK:
      break;
    case U8X8_MSG_GPIO_D1:				// D1 or SPI data pin: Output level in arg_int
    //case U8X8_MSG_GPIO_SPI_DATA:
      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 (chip select) pin: Output level in arg_int
      break;
    case U8X8_MSG_GPIO_DC:				// DC (data/cmd, A0, register select) pin: Output level in arg_int
      break;
    case U8X8_MSG_GPIO_RESET:			// Reset pin: Output level in arg_int
      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;
}

一个示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#define SCL_Pin GPIO_Pin_8
#define SDA_Pin GPIO_Pin_9
#define IIC_GPIO_Port GPIOB

void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );

	GPIO_InitStructure.GPIO_Pin = SCL_Pin|SDA_Pin;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(IIC_GPIO_Port, &GPIO_InitStructure);
} 

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:
		   	__NOP();
		   	break;
	   	case U8X8_MSG_DELAY_10MICRO:
		   	for (uint16_t n = 0; n < 320; n++)
		   	{
			   	__NOP();
		   	}
		   	break;
	   	case U8X8_MSG_DELAY_MILLI:
		   Delay_ms(1);
		   break;
	   	case U8X8_MSG_DELAY_I2C:
		   Delay_us(5);
		   break;
	   	case U8X8_MSG_GPIO_I2C_CLOCK:
		    arg_int ? GPIO_SetBits(IIC_GPIO_Port,SCL_Pin) : GPIO_ResetBits(IIC_GPIO_Port, SCL_Pin);
			break;
		case U8X8_MSG_GPIO_I2C_DATA:
			arg_int ? GPIO_SetBits(IIC_GPIO_Port,SDA_Pin) : GPIO_ResetBits(IIC_GPIO_Port, SDA_Pin);
		   	break;
	   	default:
		   	u8x8_SetGPIOResult(u8x8, 1);
		   	break;
	}
   	return 1;
}

void u8g2Init(u8g2_t *u8g2)
{
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay);
    u8g2_InitDisplay(u8g2);
    u8g2_SetPowerSave(u8g2, 0);
    u8g2_ClearBuffer(u8g2);
} 

intro

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
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);
1.屏幕句柄
2.旋转方向
3.u8g2_mirror 是否镜像
4.u8g2_mirror_vertial

/**
 * 画实心矩形,左上角坐标为(x,y),宽度为w,高度为h
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 方形的宽度
 * @param h 方形的高度
 */
void u8g2_DrawBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)

void u8g2_SetDrawColor(u8g2_t *u8g2, uint8_t color)

/**
 * 画空心圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rad 圆形的半径
 * @param opt 圆形选项
 *        U8G2_DRAW_ALL 整个圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *        选项可以通过 | 操作符来组合
 */
void u8g2_DrawCircle(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)

/**
 * 画实心圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rad 圆形的半径
 * @param opt 圆形选项
 *        U8G2_DRAW_ALL 整个圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *       选项可以通过 | 操作符来组合
 */
void u8g2_DrawDisc(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)

/**
 * 画空心椭圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rx 椭圆形水平x方向的半径
 * @param ry 椭圆形竖直y方向的半径
 * @param opt 圆形选项
 *        U8G2_DRAW_ALL 整个椭圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *        选项可以通过 | 操作符来组合
 */
void u8g2_DrawEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)

/**
 * 构造U8G2对象,初始化显示库。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param rotation 显示旋转角度(0, 90, 180, 270)
 * @param cb 回调函数,用于硬件通信
 * @param font 字体指针(可选)
 */
void u8g2_Setup(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);

/**
 * 简化版初始化,自动选择合适的回调函数。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param rotation 显示旋转角度
 * @param byte_cb 字节传输回调
 * @param gpio_and_delay_cb GPIO和延时回调
 */
void u8g2_Begin(u8g2_t *u8g2);

/**
 * 初始化显示控制器,通常由begin()内部调用。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_InitDisplay(u8g2_t *u8g2);

/**
 * 清除屏幕上的所有内容(物理屏幕)。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_ClearDisplay(u8g2_t *u8g2);

/**
 * 设置省电模式。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param is_enable 1开启省电,0关闭省电
 */
void u8g2_SetPowerSave(u8g2_t *u8g2, uint8_t is_enable);

/**
 * 清除绘图缓冲区的内容(内存中的画布)。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_ClearBuffer(u8g2_t *u8g2);

/**
 * 禁用UTF-8打印功能。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_DisableUTF8Print(u8g2_t *u8g2);

/**
 * 启用UTF-8打印功能(支持中文等)。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_EnableUTF8Print(u8g2_t *u8g2);

/**
 * 将光标位置重置到屏幕左上角(0,0)。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_Home(u8g2_t *u8g2);

/**
 * 画一个实心矩形。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 左上角x坐标
 * @param y 左上角y坐标
 * @param w 宽度
 * @param h 高度
 */
void u8g2_DrawBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h);

/**
 * 画一个空心圆。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 圆心x坐标
 * @param y 圆心y坐标
 * @param r 半径
 */
void u8g2_DrawCircle(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t rad);

/**
 * 画一个实心圆。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 圆心x坐标
 * @param y 圆心y坐标
 * @param r 半径
 */
void u8g2_DrawDisc(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t rad);

/**
 * 画一个空心椭圆。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x0 圆心x坐标
 * @param y0 圆心y坐标
 * @param rx 水平半径
 * @param ry 垂直半径
 * @param opt 绘制选项 (U8G2_DRAW_ALL, U8G2_DRAW_UPPER_RIGHT等)
 */
void u8g2_DrawEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option);

/**
 * 画一个实心椭圆。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x0 圆心x坐标
 * @param y0 圆心y坐标
 * @param rx 水平半径
 * @param ry 垂直半径
 */
void u8g2_DrawFilledEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry);

/**
 * 画一个空心矩形边框。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 左上角x坐标
 * @param y 左上角y坐标
 * @param w 宽度
 * @param h 高度
 */
void u8g2_DrawFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h);

/**
 * 画单个字符(较少用)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y 起始y坐标
 * @param encoding 字符编码
 */
void u8g2_DrawGlyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding);

/**
 * 画一条水平线。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y y坐标
 * @param len 长度
 */
void u8g2_DrawHLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len);

/**
 * 画一条直线。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x1 起点x坐标
 * @param y1 起点y坐标
 * @param x2 终点x坐标
 * @param y2 终点y坐标
 */
void u8g2_DrawLine(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2);

/**
 * 画一个像素点。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x x坐标
 * @param y y坐标
 */
void u8g2_DrawPixel(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y);

/**
 * 画一个带圆角的实心矩形。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 左上角x坐标
 * @param y 左上角y坐标
 * @param w 宽度
 * @param h 高度
 * @param r 圆角半径
 */
void u8g2_DrawRBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r);

/**
 * 画一个带圆角的空心矩形边框。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 左上角x坐标
 * @param y 左上角y坐标
 * @param w 宽度
 * @param h 高度
 * @param r 圆角半径
 */
void u8g2_DrawRFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r);

/**
 * 画字符串。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y 起始y坐标
 * @param str 字符串
 */
void u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);

/**
 * 画一个实心三角形。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x1 第一个顶点x坐标
 * @param y1 第一个顶点y坐标
 * @param x2 第二个顶点x坐标
 * @param y2 第二个顶点y坐标
 * @param x3 第三个顶点x坐标
 * @param y3 第三个顶点y坐标
 */
void u8g2_DrawTriangle(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2, u8g2_uint_t x3, u8g2_uint_t y3);

/**
 * 画UTF-8编码的字符串(支持中文)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y 起始y坐标
 * @param str UTF-8字符串
 */
void u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);

/**
 * 画一条竖直线。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x x坐标
 * @param y 起始y坐标
 * @param len 长度
 */
void u8g2_DrawVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len);

/**
 * 画位图图片。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y 起始y坐标
 * @param w 图片宽度
 * @param h 图片高度
 * @param data 图片数据数组
 */
void u8g2_DrawXBM(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *data);

/**
 * 开始分页绘制的第一帧。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 返回1表示有更多页,0表示结束
 */
uint8_t u8g2_FirstPage(u8g2_t *u8g2);

/**
 * 绘制下一页。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 返回1表示有更多页,0表示结束
 */
uint8_t u8g2_NextPage(u8g2_t *u8g2);

/**
 * 将缓冲区内容发送到屏幕显示。
 * @param u8g2 指向u8g2_t结构体的指针
 */
void u8g2_SendBuffer(u8g2_t *u8g2);

/**
 * 获取当前字体中字符基线以上的高度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 高度值
 */
int8_t u8g2_GetAscent(u8g2_t *u8g2);

/**
 * 获取当前字体中字符基线以下的高度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 高度值
 */
int8_t u8g2_GetDescent(u8g2_t *u8g2);

/**
 * 获取显示器的高度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 屏幕高度
 */
u8g2_uint_t u8g2_GetDisplayHeight(u8g2_t *u8g2);

/**
 * 获取显示器的宽度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 屏幕宽度
 */
u8g2_uint_t u8g2_GetDisplayWidth(u8g2_t *u8g2);

/**
 * 获取当前字体中最大字符的高度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 最大高度
 */
uint8_t u8g2_GetMaxCharHeight(u8g2_t *u8g2);

/**
 * 获取当前字体中最大字符的宽度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 最大宽度
 */
uint8_t u8g2_GetMaxCharWidth(u8g2_t *u8g2);

/**
 * 获取字符串在当前字体下的像素宽度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param str 字符串
 * @return 像素宽度
 */
u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *str);

/**
 * 获取UTF-8字符串的像素宽度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param str UTF-8字符串
 * @return 像素宽度
 */
u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str);

/**
 * 设置是否在每次分页时自动清空缓冲区。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param enable 1启用,0禁用
 */
void u8g2_SetAutoPageClear(u8g2_t *u8g2, uint8_t enable);

/**
 * 设置位图绘制模式(如透明/不透明)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param mode 0为不透明,1为透明
 */
void u8g2_SetBitmapMode(u8g2_t *u8g2, uint8_t mode);

/**
 * 设置总线时钟频率(高级用法)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param clock_freq 时钟频率(Hz)
 */
void u8g2_SetBusClock(u8g2_t *u8g2, uint32_t clock_freq);

/**
 * 设置绘图裁剪窗口。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param x 起始x坐标
 * @param y 起始y坐标
 * @param w 宽度
 * @param h 高度
 */
void u8g2_SetClipWindow(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h);

/**
 * 设置显示器的旋转角度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param rotation 旋转角度 (0, 90, 180, 270)
 */
void u8g2_SetDisplayRotation(u8g2_t *u8g2, uint8_t rotation);

/**
 * 设置绘图颜色(前景色/背景色)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param color 0为背景色,1为前景色
 */
void u8g2_SetDrawColor(u8g2_t *u8g2, uint8_t color);

/**
 * 设置当前使用的字体。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param font 字体指针
 */
void u8g2_SetFont(u8g2_t *u8g2, const uint8_t *font);

/**
 * 设置字体方向(从左到右或从右到左)。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param direction 0为从左到右,1为从右到左
 */
void u8g2_SetFontDirection(u8g2_t *u8g2, uint8_t direction);

/**
 * 获取缓存空间的地址。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 缓冲区指针
 */
uint8_t *u8g2_GetBufferPtr(u8g2_t *u8g2);

/**
 * 获取缓冲区的Tile高度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return Tile高度
 */
uint8_t u8g2_GetBufferTileHeight(u8g2_t *u8g2);

/**
 * 获取缓冲区的Tile宽度。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return Tile宽度
 */
uint8_t u8g2_GetBufferTileWidth(u8g2_t *u8g2);

/**
 * 获取缓冲区的当前Tile行号。
 * @param u8g2 指向u8g2_t结构体的指针
 * @return 当前行号
 */
uint8_t u8g2_GetBufferCurrTileRow(u8g2_t *u8g2);

/**
 * 设置缓冲区的当前Tile行号。
 * @param u8g2 指向u8g2_t结构体的指针
 * @param row 行号
 */
void u8g2_SetBufferCurrTileRow(u8g2_t *u8g2, uint8_t row);

使用icon

icon list

1
2
u8g2_SetFont(u8g2, u8g2_font_open_iconic_all_4x_t);
u8g2_DrawGlyph(u8g2, 0, 60, 64);

使用自己的字模

1
extern const uint8_t zhaocha[] U8G2_FONT_SECTION("***");

预设

横向重复滚动

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
char scroll_text[] = "hello world! ";
uint16_t scroll_offset = 0;

void my_draw(u8g2_t *u8g2)
{
    u8g2_ClearBuffer(u8g2);

    u8g2_SetFont(u8g2, u8g2_font_chargen_92_te);

    uint8_t screen_w = u8g2_GetDisplayWidth(u8g2);
    uint8_t screen_h = u8g2_GetDisplayHeight(u8g2);
    uint16_t text_width = u8g2_GetStrWidth(u8g2, scroll_text);

    uint8_t y = screen_h / 2 + u8g2_GetAscent(u8g2) / 2;

    scroll_offset+= 5;
    if (scroll_offset > text_width + screen_w) {
        scroll_offset = 0;
    }

    // 画两次文本,实现无缝滚动
    u8g2_DrawStr(u8g2, screen_w - scroll_offset, y, scroll_text);
    u8g2_DrawStr(u8g2, screen_w - scroll_offset + text_width + 5, y, scroll_text);

    u8g2_SendBuffer(u8g2);
}

SPIFFS

“SPIFFS github”

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "spiffs.h"
#include "w25q32.h"  // 你的 W25Q32 驱动

// SPIFFS 工作区(必须 4 字节对齐)
static u8_t spiffs_work_buf[LOG_PAGE_SIZE * 2];
static u8_t spiffs_fds[32 * 4];
static u8_t spiffs_cache[(LOG_PAGE_SIZE + 32) * 4];

// HAL 函数:SPIFFS 调用
static s32_t my_spi_read(u32_t addr, u32_t size, u8_t *dst) {
    w25q32_read(addr, dst, size);
    return SPIFFS_OK;
}

static s32_t my_spi_write(u32_t addr, u32_t size, const u8_t *src) {
    w25q32_write(addr, (u8_t*)src, size);  // 内部已处理页写入和 busy 等待
    return SPIFFS_OK;
}

static s32_t my_spi_erase(u32_t addr, u32_t size) {
    // SPIFFS 默认每次擦除 1 个 block(这里设为 4KB)
    for (u32_t i = 0; i < size; i += 4096) {
        w25q32_sector_erase(addr + i);  // 擦除 4KB 扇区
    }
    return SPIFFS_OK;
}

// 初始化 SPIFFS
int spiffs_init(void) {
    spiffs_config cfg = {0};
    cfg.phys_size = 1024 * 1024;        // 使用前 1MB(可改)
    cfg.phys_addr = 0;                  // 从 Flash 起始地址开始
    cfg.phys_erase_block = 4096;        // W25Q32 扇区大小 4KB
    cfg.log_block_size = 4096;          // 逻辑块 = 物理块
    cfg.log_page_size = 256;            // 页大小(W25Q32 页写 256B)

    cfg.hal_read_f = my_spi_read;
    cfg.hal_write_f = my_spi_write;
    cfg.hal_erase_f = my_spi_erase;

    int res = SPIFFS_mount(&fs, &cfg,
        spiffs_work_buf, spiffs_fds, sizeof(spiffs_fds),
        spiffs_cache, sizeof(spiffs_cache), NULL);

    if (res != SPIFFS_OK) {
        // 首次使用需格式化
        SPIFFS_format(&fs);
        res = SPIFFS_mount(&fs, &cfg,
            spiffs_work_buf, spiffs_fds, sizeof(spiffs_fds),
            spiffs_cache, sizeof(spiffs_cache), NULL);
    }
    return res;
}

// 使用示例:写文件
void test_spiffs(void) {
    spiffs_file fd = SPIFFS_open(&fs, "hello.txt", SPIFFS_CREAT | SPIFFS_RDWR, 0);
    const char *msg = "Hello, SPIFFS on W25Q32!";
    SPIFFS_write(&fs, fd, (void*)msg, strlen(msg));
    SPIFFS_close(&fs, fd);

    // 读回来
    fd = SPIFFS_open(&fs, "hello.txt", SPIFFS_RDONLY, 0);
    char buf[50] = {0};
    SPIFFS_read(&fs, fd, buf, sizeof(buf));
    SPIFFS_close(&fs, fd);
    // buf 现在是 "Hello, SPIFFS on W25Q32!"
}

LittleFS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "lfs.h"

// variables used by the filesystem
lfs_t lfs;
lfs_file_t file;

// configuration of the filesystem is provided by this struct
const struct lfs_config cfg = {
    // block device operations
    .read  = user_provided_block_device_read,
    .prog  = user_provided_block_device_prog,
    .erase = user_provided_block_device_erase,
    .sync  = user_provided_block_device_sync,

    // block device configuration
    .read_size = 16,
    .prog_size = 16,
    .block_size = 4096,
    .block_count = 128,
    .cache_size = 16,
    .lookahead_size = 16,
    .block_cycles = 500,
};


// 主要是手动实现
.read  = user_provided_block_device_read,
.prog  = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync  = user_provided_block_device_sync,
Licensed under CC BY-NC-SA 4.0