U8G2库使用案例(stm32)

目录

一、小球在 OLED 屏幕平面内运动并碰撞反弹的效果

二、 简单的波形生成和显示程序:

三、三维三角形旋转展示

四、正方形平面内顺时针旋转

五、带有旋转点的空心圆圈应用

六、字幕滚动效果

七、下雪动画效果

八、进度条动画效果


自己移植的U8g2库,OLED库超好用,自己封装了用户层不需要再去查资料使用,注释写的很多很详细,有示例上手就会,初始化也很简单

个人移植的U8g2库:

超简单的stm32 U8g2移植

  大家可以自己去官网移植,也可以用我的         U8G2官网

  很多大家都可以举一反三

一、小球在 OLED 屏幕平面内运动并碰撞反弹的效果

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

// 小球结构体,包含位置、速度等信息
typedef struct {
    int16_t x;
    int16_t y;
    int16_t vx;  // x方向速度
    int16_t vy;  // y方向速度
    uint8_t radius;  // 小球半径
} Ball;

// 初始化小球的位置和速度
void init_ball(Ball *ball) {
    ball->x = 10;
    ball->y = 10;
    ball->vx = 2;
    ball->vy = 2;
    ball->radius = 5;
}

// 更新小球的位置,处理边界碰撞
void update_ball_position(Ball *ball, u8g2_uint_t screen_width, u8g2_uint_t screen_height) {
    // 更新x坐标
    ball->x += ball->vx;
    // 检查是否碰到左右边界,碰到则反弹
    if (ball->x <= ball->radius || ball->x >= screen_width - ball->radius) {
        ball->vx = -ball->vx;
    }

    // 更新y坐标
    ball->y += ball->vy;
    // 检查是否碰到上下边界,碰到则反弹
    if (ball->y <= ball->radius || ball->y >= screen_height - ball->radius) {
        ball->vy = -ball->vy;
    }
}

// 在OLED屏幕上绘制小球
void draw_ball(Ball ball) {
    WU_OLED_U8G2_DrawDisc(ball.x, ball.y, ball.radius, U8G2_DRAW_ALL);
}

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



OLED_WUStartTask04(void *argument)
{

	Ball my_ball;
	init_ball(&my_ball);
	while(1)
	{
		//Wu_oled_Proc();

		// 清空缓冲区
		WU_OLED_U8G2_ClearBuffer();

		// 获取屏幕宽度和高度
		u8g2_uint_t screen_width = WU_OLED_U8G2_GetDisplayWidth();
		u8g2_uint_t screen_height = WU_OLED_U8G2_GetDisplayHeight();

		// 更新小球位置
		update_ball_position(&my_ball, screen_width, screen_height);

		// 绘制小球
		draw_ball(my_ball);

		// 刷新缓冲区,显示内容到OLED屏幕
		WU_OLED_U8G2_SendBuffer();

		//osDelay(50);
	}
}

二、 简单的波形生成和显示程序:

#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include "../../WU/OLED_U8g2/U8g2/WU_U8g2_Init.h"
#include "USER_OLED.h"
#include "../../WU/OLED_U8g2/U8g2/u8g2.h"

// 定义屏幕的宽度和高度
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// 定义波形参数
#define WAVE_AMPLITUDE 20  // 波形的振幅
#define WAVE_FREQUENCY 0.2 // 波形的频率(加快频率)

// 初始化波形数据
void InitWave(void) {
    // 无需初始化,因为每次都会重新计算正弦波
}

// 更新波形数据(生成正弦波)
void UpdateWave(uint8_t *waveData, float time) {
    for (int i = 0; i < SCREEN_WIDTH; i++) {
        // 计算正弦波的值,并将其映射到屏幕范围内
        float value = WAVE_AMPLITUDE * sin(WAVE_FREQUENCY * (i + time));
        waveData[i] = SCREEN_HEIGHT / 2 + (uint8_t)value;
    }
}

// 绘制波形
void DrawWave(uint8_t *waveData) {
    // 清空屏幕
    WU_OLED_U8G2_ClearBuffer();

    // 绘制波形
    for (int i = 0; i < SCREEN_WIDTH; i++) {
        // 确保波形在屏幕范围内
        if (waveData[i] < SCREEN_HEIGHT) {
            WU_OLED_U8G2_DrawPixel(i, waveData[i]);
        }
    }

    // 刷新发送缓冲区
    WU_OLED_U8G2_SendBuffer();
}

// 主函数
int main(void) {
    uint8_t waveData[SCREEN_WIDTH];  // 存储每个像素点的Y坐标
    float time = 0;                  // 时间变量,用于生成动态波形

    // 初始化OLED
    WU_OLED_U8G2_Init();

    // 主循环
    while (1) {
        // 更新波形数据
        UpdateWave(waveData, time);

        // 绘制波形
        DrawWave(waveData);

        // 更新时间(加快波形移动速度)
        time += 1.0;

        // 延时一段时间,控制波形刷新速度(减少延时时间)
        // 这里假设有一个延时函数 delay_ms
        //delay_ms(20);  // 将延时时间从50ms减少到20ms
    }

    return 0;
}

三、三维三角形旋转展示

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

// 定义更大的三角形在三维空间中的三个顶点坐标
float triangleVertices[3][3] = {
		{-15, -15, 0},  // 第一个顶点,调整了坐标使三角形更大
		{15, -15, 0},   // 第二个顶点
		{0, 15, 0}      // 第三个顶点
};

// 用于记录绕X、Y、Z轴旋转的角度
float angleX = 0;
float angleY = 0;
float angleZ = 0;

// 旋转角度的增量,这里固定一个合适的速度,可按需调整
const float angleIncrement = 0.03;

// 投影平面距离视点(类似相机到投影平面的距离,影响投影效果,可调整)
const float projectionPlaneDistance = 8;

// 转换三维坐标到二维屏幕坐标(简单的正投影示例,实际可替换为更复杂的投影算法比如透视投影等)
void project3DTo2D(float point3D[3], float* x2D, float* y2D) {
	// 先绕X轴旋转
	float rotatedX = point3D[0];
	float rotatedY = point3D[1] * cos(angleX) - point3D[2] * sin(angleX);
	float rotatedZ = point3D[1] * sin(angleX) + point3D[2] * cos(angleX);

	// 再绕Y轴旋转
	rotatedX = rotatedX * cos(angleY) + rotatedZ * sin(angleY);
	rotatedZ = -rotatedX * sin(angleY) + rotatedZ * cos(angleY);

	// 接着绕Z轴旋转
	rotatedX = rotatedX * cos(angleZ) - rotatedY * sin(angleZ);
	rotatedY = rotatedX * sin(angleZ) + rotatedY * cos(angleZ);

	// 进行正投影,将三维坐标投影到二维平面(这里假设投影平面平行于XY平面,且在Z轴固定位置)
	*x2D = rotatedX * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);
	*y2D = rotatedY * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);

	// 转换坐标到屏幕坐标系(以屏幕中心为原点,根据屏幕尺寸进行偏移等调整)
	*x2D += 64;  // 这里假设屏幕宽度为128像素,取一半作为中心原点的X偏移量,可根据实际屏幕宽度调整
	*y2D += 32;  // 这里假设屏幕高度为64像素,取一半作为中心原点的Y偏移量,可根据实际屏幕高度调整
}

// 绘制旋转后的空心三角形
void drawRotatedTriangle() {
	float x1, y1, x2, y2, x3, y3;
	// 对三角形的三个顶点分别进行投影转换
	project3DTo2D(triangleVertices[0], &x1, &y1);
	project3DTo2D(triangleVertices[1], &x2, &y2);
	project3DTo2D(triangleVertices[2], &x3, &y3);

	// 绘制空心三角形(使用绘制线的函数来连接三个顶点形成三角形)
	WU_OLED_U8G2_DrawLine(x1, y1, x2, y2);
	WU_OLED_U8G2_DrawLine(x2, y2, x3, y3);
	WU_OLED_U8G2_DrawLine(x3, y3, x1, y1);
}


/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



OLED_WUStartTask04(void *argument)
{


	while(1)
	{
		//Wu_oled_Proc();

		// 清空发送缓冲区
		WU_OLED_U8G2_ClearBuffer();

		// 绘制旋转后的空心三角形
		drawRotatedTriangle();

		// 更新旋转角度(分别绕X、Y、Z轴增加一定角度,实现旋转效果)
		angleX += angleIncrement;
		angleY += angleIncrement;
		angleZ += angleIncrement;
		if (angleX >= 2 * M_PI) angleX -= 2 * M_PI;
		if (angleY >= 2 * M_PI) angleY -= 2 * M_PI;
		if (angleZ >= 2 * M_PI) angleZ -= 2 * M_PI;

		// 刷新发送缓冲区,将绘制内容显示到屏幕上
		WU_OLED_U8G2_SendBuffer();


		// 可以添加适当延时,控制动画速度,这里简单示意,实际可根据需求调整延时时间
		//osDelay(50);
	}
}

四、正方形平面内顺时针旋转

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

// 定义正方形在三维空间中的四个顶点坐标,调整大小使其适配屏幕
float squareVertices[4][3] = {
    {-20, -20, 0},  // 左下角顶点
    {20, -20, 0},   // 右下角顶点
    {20, 20, 0},    // 右上角顶点
    {-20, 20, 0}    // 左上角顶点
};

// 用于记录绕 Z 轴旋转的角度(仅绕 Z 轴旋转可实现平面内顺时针旋转)
float angleZ = 0;

// 旋转角度的增量,用于控制旋转速度,可根据实际需求调整
const float angleIncrement = 0.05;

// 投影平面距离视点(类似相机到投影平面的距离,影响投影效果,可调整)
const float projectionPlaneDistance = 5;

// 转换三维坐标到二维屏幕坐标(简单的正投影示例,实际可替换为更复杂的投影算法比如透视投影等)
void project3DTo2D(float point3D[3], float* x2D, float* y2D) {
	// 先绕 Z 轴旋转
	float rotatedX = point3D[0] * cos(angleZ) - point3D[1] * sin(angleZ);
	float rotatedY = point3D[0] * sin(angleZ) + point3D[1] * cos(angleZ);
	float rotatedZ = point3D[2];

	// 进行正投影,将三维坐标投影到二维平面(这里假设投影平面平行于XY平面,且在Z轴固定位置)
	*x2D = rotatedX * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);
	*y2D = rotatedY * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);

	// 转换坐标到屏幕坐标系(以屏幕中心为原点,根据屏幕尺寸进行偏移等调整)
	*x2D += 64;  // 这里假设屏幕宽度为128像素,取一半作为中心原点的X偏移量,可根据实际屏幕宽度调整
	*y2D += 32;  // 这里假设屏幕高度为64像素,取一半作为中心原点的Y偏移量,可根据实际屏幕高度调整
}

// 绘制旋转后的正方形
void drawRotatedSquare() {
	float x1, y1, x2, y2, x3, y3, x4, y4;
	// 对正方形的四个顶点分别进行投影转换
	project3DTo2D(squareVertices[0], &x1, &y1);
	project3DTo2D(squareVertices[1], &x2, &y2);
	project3DTo2D(squareVertices[2], &x3, &y3);
	project3DTo2D(squareVertices[3], &x4, &y4);

	// 绘制正方形的四条边
	WU_OLED_U8G2_DrawLine(x1, y1, x2, y2);
	WU_OLED_U8G2_DrawLine(x2, y2, x3, y3);
	WU_OLED_U8G2_DrawLine(x3, y3, x4, y4);
	WU_OLED_U8G2_DrawLine(x4, y4, x1, y1);
}

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



OLED_WUStartTask04(void *argument)
{


	while(1)
	{
		//Wu_oled_Proc();

		// 清空发送缓冲区
		WU_OLED_U8G2_ClearBuffer();

		// 绘制旋转后的正方形
		drawRotatedSquare();

		// 更新旋转角度(绕 Z 轴增加一定角度,实现顺时针旋转效果)
		angleZ += angleIncrement;
		if (angleZ >= 2 * M_PI) angleZ -= 2 * M_PI;

		// 刷新发送缓冲区,将绘制内容显示到屏幕上
		WU_OLED_U8G2_SendBuffer();


		// 可以添加适当延时,控制动画速度,这里简单示意,实际可根据需求调整延时时间
		//osDelay(50);
	}
}

五、带有旋转点的空心圆圈应用

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

// 定义大空心圆圈的圆心坐标及半径
float bigCircleCenter[2] = {0, 0};
float bigCircleRadius = 25;

// 定义实心小圆圈的初始坐标
float smallSolidCircle[3];

// 用于记录实心小圆圈绕大空心圆圈旋转的角度
float circleAngle = 0;
const float circleAngleIncrement = 0.03;

// 投影平面距离视点(类似相机到投影平面的距离,影响投影效果,可调整)
const float projectionPlaneDistance = 5;

// 转换三维坐标到二维屏幕坐标(简单的正投影示例,实际可替换为更复杂的投影算法比如透视投影等)
void project3DTo2D(float point3D[3], float* x2D, float* y2D) {
	// 先绕 Z 轴旋转(针对实心小圆圈所在平面内旋转)
	float rotatedX = point3D[0];
	float rotatedY = point3D[1];
	float rotatedZ = point3D[2];

	// 进行正投影,将三维坐标投影到二维平面(这里假设投影平面平行于XY平面,且在Z轴固定位置)
	*x2D = rotatedX * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);
	*y2D = rotatedY * projectionPlaneDistance / (rotatedZ + projectionPlaneDistance);

	// 转换坐标到屏幕坐标系(以屏幕中心为原点,根据屏幕尺寸进行偏移等调整)
	*x2D += WU_OLED_U8G2_GetDisplayWidth() / 2;
	*y2D += WU_OLED_U8G2_GetDisplayHeight() / 2;
}

// 绘制大空心圆圈
void drawBigHollowCircle() {
	float centerX, centerY;
	project3DTo2D(bigCircleCenter, &centerX, &centerY);
	WU_OLED_U8G2_DrawCircle(centerX, centerY, bigCircleRadius, U8G2_DRAW_ALL);
}

// 绘制实心小圆圈并更新其位置(绕大空心圆圈旋转)
void drawRotatingSmallSolidCircle() {
	float x, y;
	// 根据旋转角度更新实心小圆圈的坐标
	smallSolidCircle[0] = bigCircleRadius * cos(circleAngle);
	smallSolidCircle[1] = bigCircleRadius * sin(circleAngle);

	project3DTo2D(smallSolidCircle, &x, &y);
	WU_OLED_U8G2_DrawDisc(x, y, 5, U8G2_DRAW_ALL);
}

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



OLED_WUStartTask04(void *argument)
{

	// 初始化实心小圆圈的坐标
	smallSolidCircle[0] = bigCircleRadius;
	smallSolidCircle[1] = 0;
	smallSolidCircle[2] = 0;
	while(1)
	{
		//Wu_oled_Proc();

		// 清空发送缓冲区
		WU_OLED_U8G2_ClearBuffer();

		// 绘制大空心圆圈
		drawBigHollowCircle();

		// 绘制绕大空心圆圈旋转的实心小圆圈
		drawRotatingSmallSolidCircle();

		// 更新实心小圆圈绕大空心圆圈的旋转角度
		circleAngle += circleAngleIncrement;
		if (circleAngle >= 2 * M_PI) circleAngle -= 2 * M_PI;

		// 刷新发送缓冲区,将绘制内容显示到屏幕上
		WU_OLED_U8G2_SendBuffer();


		// 可以添加适当延时,控制动画速度,这里简单示意,实际可根据需求调整延时时间
		//osDelay(50);
	}
}

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

六、字幕滚动效果


void OLED_WUStartTask04(void *argument)
{
    const char* message = "祝大家新年快乐,恭喜发财!";  // 祝福语
    int messageWidth = WU_OLED_U8G2_GetUTF8Width(message);  // 获取祝福语的宽度
    int x = WU_OLED_U8G2_GetDisplayWidth();  // 获取屏幕宽度,初始x坐标为屏幕最右侧

    while (1)
    {
        // 清空显示缓冲区
        WU_OLED_U8G2_ClearBuffer();

        // 绘制祝福语,x坐标逐渐减小,实现从右往左滚动效果
        WU_OLED_U8G2_SetFont(u8g2_font_wqy13_t_gb2312a);  // 设置字体,支持中文
        WU_OLED_U8G2_DrawUTF8(x, 32, message);  // 在指定位置绘制祝福语

        // 刷新显示
        WU_OLED_U8G2_SendBuffer();

        // 更新x坐标,实现滚动效果
        x--;

        // 如果祝福语完全滚出屏幕,重置x坐标
        if (x < -messageWidth) {
            x = WU_OLED_U8G2_GetDisplayWidth();
        }

        // 控制滚动速度,避免过快或过慢
        //osDelay(20);  // 20ms的延时,可以根据实际效果调整
    }
}

七、下雪动画效果

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

// 定义屏幕的宽度和高度,你可根据实际OLED屏幕尺寸修改
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// 雪花结构体,用于表示每个雪花的属性
typedef struct Snowflake {
	int x;  // x坐标
	int y;  // y坐标
	int speed;  // 下落速度
} Snowflake;

// 最大雪花数量,可以根据想要的下雪密度调整
#define MAX_SNOWFLAKES 50

Snowflake snowflakes[MAX_SNOWFLAKES];

// 初始化雪花的位置和速度
void initSnowflakes() {
	for (int i = 0; i < MAX_SNOWFLAKES; i++) {
		snowflakes[i].x = rand() % SCREEN_WIDTH;
		snowflakes[i].y = rand() % SCREEN_HEIGHT;
		snowflakes[i].speed = rand() % 3 + 1;  // 速度在1到3之间随机
	}
}

// 更新雪花的位置,实现下落效果,超出屏幕底部则重新回到顶部
void updateSnowflakes() {
	for (int i = 0; i < MAX_SNOWFLAKES; i++) {
		snowflakes[i].y += snowflakes[i].speed;
		if (snowflakes[i].y > SCREEN_HEIGHT) {
			snowflakes[i].y = 0;
			snowflakes[i].x = rand() % SCREEN_WIDTH;
		}
	}
}

// 在OLED屏幕上绘制雪花(白色像素点)
void drawSnowflakes() {
	WU_OLED_U8G2_SetDrawColor(1);  // 设置为白色,用于绘制雪花
	for (int i = 0; i < MAX_SNOWFLAKES; i++) {
		WU_OLED_U8G2_DrawPoint(snowflakes[i].x, snowflakes[i].y);
	}
}



/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



OLED_WUStartTask04(void *argument)
{

	initSnowflakes();
	while(1)
	{
		//Wu_oled_Proc();

		WU_OLED_U8G2_ClearBuffer();  // 清空缓冲区

		updateSnowflakes();
		drawSnowflakes();

		WU_OLED_U8G2_SendBuffer();  // 刷新缓冲区,将绘制内容显示到屏幕上


		// 可以添加适当延时,控制动画速度,这里简单示意,实际可根据需求调整延时时间
		//osDelay(50);
	}
}

/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

八、进度条动画效果

OLED_WUStartTask04(void *argument)
{

	int dat;
	while(1)
	{
		//Wu_oled_Proc();

		while(dat<101)
		{
			WU_OLED_U8G2_ClearBuffer();

			WU_OLED_U8G2_SetFont(u8g2_font_wqy13_t_gb2312a);//选择字库

			WU_OLED_U8G2_Printf(25,18,CHINA,"WU-有点东");
			WU_OLED_U8G2_DrawButtonUTF8(65, 35,  U8G2_BTN_SHADOW1|U8G2_BTN_HCENTER|U8G2_BTN_BW2, 0, 2, 2, "请等待初始化完成" );
			WU_OLED_U8G2_Printf(101,60,CHINA,"%d%%",dat);
			WU_OLED_U8G2_DrawRFrame(0, 50, 100,10,4);
			WU_OLED_U8G2_DrawRBox(0, 50, dat,10,4);

			WU_OLED_U8G2_SendBuffer();

			dat+=2;
		}
		WU_OLED_U8G2_DrawButtonUTF8(65, 35,  U8G2_BTN_SHADOW1|U8G2_BTN_HCENTER|U8G2_BTN_BW2|U8G2_BTN_INV, 0, 2, 2, "请等待初始化完成" );
		WU_OLED_U8G2_SendBuffer();

		dat=0;

		//osDelay(50);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值