【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
项目之一百一十九:ESP32+GC9A01之随机移动表针的专业仪表盘
实验开源代码
- /*
- 【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
- 实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
- 项目之一百一十九:ESP32+GC9A01之随机移动表针的专业仪表盘
- */
-
- // GC9A01---------- ESP32
- // RST ------------ NC(复位引脚,此处未连接)
- // CS ------------- D4(片选引脚,连接到ESP32的D4引脚)
- // DC ------------- D2(数据/命令选择引脚,连接到ESP32的D2引脚)
- // SDA ------------ D23 (green)(主数据输出引脚,连接到ESP32的D23引脚,绿色线)
- // SCL ------------ D18 (yellow)(时钟信号引脚,连接到ESP32的D18引脚,黄色线)
- // GND ------------ GND(接地引脚,连接到ESP32的接地端)
- // VCC -------------3V3(电源引脚,连接到ESP32的3.3V电源)
-
- // 定义指针的长度、宽度、半径和颜色
- #define NEEDLE_LENGTH 35 // 可见长度
- #define NEEDLE_WIDTH 5 // 指针宽度 - 设置为奇数
- #define NEEDLE_RADIUS 90 // 指针顶端的半径
- #define NEEDLE_COLOR1 TFT_MAROON // 指针外围颜色
- #define NEEDLE_COLOR2 TFT_RED // 指针中心颜色
- #define DIAL_CENTRE_X 120 // 表盘中心的X坐标
- #define DIAL_CENTRE_Y 120 // 表盘中心的Y坐标
-
- // 加载字体
- #include "NotoSansBold36.h"
- #define AA_FONT_LARGE NotoSansBold36
-
- #include <TFT_eSPI.h>
- TFT_eSPI tft = TFT_eSPI(); // 创建TFT对象
- TFT_eSprite needle = TFT_eSprite(&tft); // 用于指针的精灵对象
- TFT_eSprite spr = TFT_eSprite(&tft); // 用于显示刻度的精灵对象
-
- // 加载jpeg图片数据
- #include "dial.h"
-
- // 包含jpeg解码库
- #include <TJpg_Decoder.h>
-
- uint16_t* tft_buffer; // 用于存储TFT屏幕像素块的缓冲区
- bool buffer_loaded = false; // 缓冲区是否已加载
- uint16_t spr_width = 0; // 精灵宽度
- uint16_t bg_color =0; // 背景颜色
-
- // 这个函数将在解码jpeg文件时被调用
- bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
- {
- // 如果图片超出了屏幕边界,停止进一步解码
- if ( y >= tft.height() ) return 0;
-
- // 该函数会自动剪裁图像块,并将其渲染到TFT屏幕上
- tft.pushImage(x, y, w, h, bitmap);
-
- // 返回1以解码下一个块
- return 1;
- }
-
- // 初始化设置
- void setup() {
- Serial.begin(115200); // 仅用于调试
-
- // 设置字节顺序(对于TFT_eSPI设置为true)
- TJpgDec.setSwapBytes(true);
-
- // 必须给jpeg解码器指定渲染函数
- TJpgDec.setCallback(tft_output);
-
- tft.begin();
- tft.setRotation(2);
- tft.fillScreen(TFT_BLACK);
-
- // 绘制表盘
- TJpgDec.drawJpg(0, 0, dial, sizeof(dial));
- tft.drawCircle(DIAL_CENTRE_X, DIAL_CENTRE_Y, NEEDLE_RADIUS-NEEDLE_LENGTH, TFT_DARKGREY);
-
- // 加载字体并创建显示刻度的精灵
- spr.loadFont(AA_FONT_LARGE);
- spr_width = spr.textWidth("777"); // 数字7在此字体中最宽
- spr.createSprite(spr_width, spr.fontHeight());
- bg_color = tft.readPixel(120, 120); // 从表盘中心获取颜色
- spr.fillSprite(bg_color);
- spr.setTextColor(TFT_WHITE, bg_color, true);
- spr.setTextDatum(MC_DATUM);
- spr.setTextPadding(spr_width);
- spr.drawNumber(0, spr_width/2, spr.fontHeight()/2);
- spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2);
-
- // 绘制标签文字
- tft.setTextColor(TFT_WHITE, bg_color);
- tft.setTextDatum(MC_DATUM);
- tft.drawString("(degrees)", DIAL_CENTRE_X, DIAL_CENTRE_Y + 48, 2);
-
- // 在创建指针之前,定义指针在TFT上的旋转中心点
- tft.setPivot(DIAL_CENTRE_X, DIAL_CENTRE_Y);
-
- // 创建指针精灵
- createNeedle();
-
- // 将指针位置重置为0
- plotNeedle(0, 0);
-
- delay(2000); // 延迟2秒
- }
-
- // 主循环
- void loop() {
- uint16_t angle = random(241); // 随机生成0到240范围内的角度
-
- // 以每次40ms的增量绘制指针到随机角度
- plotNeedle(angle, 30);
-
- // 在新位置暂停2.5秒
- delay(2500);
- }
-
- // 创建指针精灵
- void createNeedle(void)
- {
- needle.setColorDepth(16); // 设置颜色深度
- needle.createSprite(NEEDLE_WIDTH, NEEDLE_LENGTH); // 创建指针精灵
-
- needle.fillSprite(TFT_BLACK); // 用黑色填充精灵
-
- // 定义相对于精灵左上角的指针旋转点
- uint16_t piv_x = NEEDLE_WIDTH / 2; // 精灵的旋转点x(在中间)
- uint16_t piv_y = NEEDLE_RADIUS; // 精灵的旋转点y
- needle.setPivot(piv_x, piv_y); // 设置旋转点
-
- // 在精灵中绘制红色指针
- needle.fillRect(0, 0, NEEDLE_WIDTH, NEEDLE_LENGTH, TFT_MAROON);
- needle.fillRect(1, 1, NEEDLE_WIDTH-2, NEEDLE_LENGTH-2, TFT_RED);
-
- // 获取旋转后边界的参数
- int16_t min_x;
- int16_t min_y;
- int16_t max_x;
- int16_t max_y;
-
- // 计算必须从TFT上抓取的最坏情况区域(45度旋转时)
- needle.getRotatedBounds(45, &min_x, &min_y, &max_x, &max_y);
-
- // 计算缓冲区大小并分配用于抓取TFT区域的缓冲区
- tft_buffer = (uint16_t*) malloc( ((max_x - min_x) + 2) * ((max_y - min_y) + 2) * 2 );
- }
-
- // 将指针移动到新位置
- void plotNeedle(int16_t angle, uint16_t ms_delay)
- {
- static int16_t old_angle = -120; // 初始角度为-120度
-
- // 边界框参数
- static int16_t min_x;
- static int16_t min_y;
- static int16_t max_x;
- static int16_t max_y;
-
- if (angle < 0) angle = 0; // 限制角度以模拟指针停止
- if (angle > 240) angle = 240;
-
- angle -= 120; // 从-120度开始
-
- // 逐步移动指针,直到达到新角度
- while (angle != old_angle || !buffer_loaded) {
-
- if (old_angle < angle) old_angle++;
- else old_angle--;
-
- // 仅在偶数值时绘制指针以提高绘制性能
- if ( (old_angle & 1) == 0)
- {
- if (buffer_loaded) {
- // 将原始区域推回到屏幕上以擦除旧指针图形
- tft.pushRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
- }
-
- if ( needle.getRotatedBounds(old_angle, &min_x, &min_y, &max_x, &max_y) )
- {
- // 在绘制指针之前抓取该区域的副本
- tft.readRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
- buffer_loaded = true;
- }
-
- // 在新位置绘制指针,指针图像中的黑色为透明
- needle.pushRotated(old_angle, TFT_BLACK);
-
- // 在下一次更新之前延迟
- delay(ms_delay);
- }
-
- // 更新表盘中心的数字
- spr.setTextColor(TFT_WHITE, bg_color, true);
- spr.drawNumber(old_angle+120, spr_width/2, spr.fontHeight()/2);
- spr.pushSprite(120 - spr_width / 2, 120 - spr.fontHeight() / 2);
-
- // 在指针接近新位置时稍微放慢速度
- if (abs(old_angle - angle) < 10) ms_delay += ms_delay / 5;
- }
- }
复制代码
|