通过OLED显示电流曲线图,可以更直观地观测电流的变化情况
1、平滑滚动显示ADC曲线函数(点间距4像素)
主要的思路是用画线的方式擦除之前屏幕的线段,再绘制上新的线段。
没有使用显示缓冲,为了减少闪烁,直接在屏幕擦点,画点
OLED_DrawPixe、OLED_DrawLine、OLED_ClearLine函数均已重写为在在屏幕上直接绘制。
static uint8_t prev_point_count = 0; // 上一次的点数(用于清除旧线)
参数adc_value:采集的电流值
void Draw_ADCCurve_4px_Scroll(uint16_t adc_value)
{ static uint8_t y_buffer[MAX_POINTS]; // 存储历史Y坐标
static uint8_t point_count = 0; // 已存储的点数
static uint8_t start_index = 0; // 起始索引(用于滚动)
// 计算当前Y坐标
uint8_t current_y = OLED_HEIGHT - 1 - (adc_value * (OLED_HEIGHT - 1)) / ADC_MAX;
// 存储当前点
if(point_count < MAX_POINTS)
{
y_buffer[point_count] = current_y;
point_count++;
}
else
{
// 缓冲区已满,滚动显示
for(uint8_t i = 0; i < MAX_POINTS - 1; i++)
{
y_buffer[i] = y_buffer[i+1];
}
y_buffer[MAX_POINTS-1] = current_y;
}
// 清除旧线,画上新线
if(prev_point_count > 1)
{
for(uint8_t i = 0; i < prev_point_count-1; i++)
{
uint8_t x1 = i * POINT_INTERVAL;
uint8_t x2 = (i + 1) * POINT_INTERVAL;
uint8_t y1 = y_buffer[i];
uint8_t y2 = y_buffer[i + 1];
// 清除旧线
OLED_ClearLine(x1, y1, x2, y2);
if(i<prev_point_count-2)
{
y1=y_buffer[i + 1];
y2 = y_buffer[i + 2];
OLED_DrawLine(x1, y1, x2, y2);
}
}
}
// 更新上一次的点数
prev_point_count = point_count;
}2、OLED_DrawPixel函数
参数:color 1:画点;2:檫除
// 绘制像素点
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color) {
if(x >= 128 || y >= 64) return;
uint8_t page = y / 8;
uint8_t mask = 1 << (y % 8);
OLED_SetCursor(x, page);
uint8_t data;
// 这里需要读取当前数据,修改后再写回
// 由于I2C OLED通常不支持读取,需要维护一个显示缓冲区
if(color) {
data |= mask;
} else {
data &= ~mask;
}
OLED_WriteData(data);
}3、OLED_DrawLine函数
/**
* @brief 清除两点之间的线段
*/
void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
// 简单实现:逐点清除
if(x1 == x2)
{
// 垂直线
uint8_t y_start = (y1 < y2) ? y1 : y2;
uint8_t y_end = (y1 < y2) ? y2 : y1;
for(uint8_t y = y_start; y <= y_end; y++)
{
//OLED_DrawPoint(x1, y);
OLED_DrawPixel(x1,y,1);
}
}
else
{
// 非垂直线,使用Bresenham算法
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
while(1)
{
//OLED_DrawPoint(x1, y1);
OLED_DrawPixel(x1,y1,1);
if(x1 == x2 && y1 == y2) break;
int e2 = 2 * err;
if(e2 > -dy)
{
err -= dy;
x1 += sx;
}
if(e2 < dx)
{
err += dx;
y1 += sy;
}
}
}
}4、调用
float current = INA219_ReadCurrent();
if(Cur_Page==0)//曲线页
{
//绘制曲线图
Draw_ADCCurve_4px_Scroll(current * 1000);
HAL_Delay(200);
}
else if(Cur_Page==1)//文字页
{
//显示电流、电压、功率的文字信息
}
https://www.bilibili.com/video/BV1qpjuzjEyb?share_source=copy_web
我要赚赏金
