U8G2库使用案例(stm32)
U8G2官网:
自己移植的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; // 时间变量,用于生成动态波形// 初始化OLEDWU_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, ¢erX, ¢erY);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);}
}/*------------------------------------------------------------------------------------------------------------------------------------------------------------------*/