|  | 
 
 
 楼主|
发表于 2025-6-12 15:37:02
|
显示全部楼层 
| 本来准备使用自定义字体,搞了个数码管字体,看着还行,结果发现自定义字体不支持设置背景色,只能先刷一层黑色再输出数字,导致闪屏严重,无奈使用内置字体,有点丑 
 
 复制代码#include "common.h"
#include "Arduino.h"
#include <Adafruit_GFX.h>      
#include <Adafruit_ST7735.h> 
#include "OneButton.h"
// #include "DS_Digital12pt7b.h"
// #include "DS_Digital18pt7b.h"
// #include "Fonts/FreeSerifBold18pt7b.h"
// #include "Fonts/FreeSerifBold12pt7b.h"
// LCD
SPIClass SPI_2(LCD_MOSI,LCD_MISO,LCD_SCK,-1);
Adafruit_ST7735 tft = Adafruit_ST7735(&SPI_2,LCD_CS, LCD_DC, LCD_RES); 
//key
OneButton btnPower(POWER_S, true);
OneButton btn2(KEY2,true);
OneButton btn3(KEY3,true);
#define UPPER_LIMIT 999999
// MENU
//菜单选项,取值123,切换菜单是设置为对应负值
signed char menu=-1;
#define menuRPM 1
#define menuCTR 2
#define menuIR 3
//是否激光模式 true激光 false霍尔
bool isLD=true;
//是否启动
bool isStart=false;
//计数器 计数统计
unsigned long count = 0;
//频率计 记录上次触发时间
unsigned long lastTime = 0;
//频率计 触发间隔,用于计算频率
long delayTime = 0;
float rps = 0.0;
float rpsMax= 0.0;
bool isBtn2Click=false;
bool isBtn3Click=false;
//计数器模式 启动时间
int startTime = 0;
long runningTime;
void pulseInterrupt() {
  long micro=micros();
  delayTime=micro-lastTime;
  lastTime=micro;
  count++;
}
//GPIO初始化
void initPin(){
  pinMode(POWER_C,OUTPUT);
  pinMode(POWER_S,INPUT_PULLUP);
  pinMode(KEY2,INPUT_PULLUP);
  pinMode(KEY3,INPUT_PULLUP);
  pinMode(LD_CTRL, OUTPUT);
  pinMode(SIGNAL,INPUT_PULLUP);
  pinMode(LD_POWER,OUTPUT);
  pinMode(HL_POWER,OUTPUT);
  pinMode(LCD_BLK,OUTPUT);
  pinMode(BAT_ADC,INPUT);
  digitalWrite(POWER_C,LOW);
  digitalWrite(LD_CTRL,LOW);
  digitalWrite(LD_POWER, LOW);
  digitalWrite(HL_POWER, HIGH);
  digitalWrite(LCD_BLK, LOW);
}
//电源键单击
void btnPowerClick(){
  menu++;
  if(menu>3)
    menu=1;
  menu=-menu;
}
//电源键长按
void btnPowerLongPress(){
  powerOff();
}
void btn2Click(){
  isBtn2Click=true;
}
void btn3Click(){
  isBtn3Click=true;
}
//屏幕初始化
void initLCD(){
// INITR_GREENTAB
// INITR_144GREENTAB
// INITR_HALLOWING
// INITR_MINI160x80
// INITR_MINI160x80_PLUGIN
// INITR_BLACKTAB
// INITR_HALLOWING
// tft.initR(INITR_MINI160x80_PLUGIN);
  tft.initR(INITR_MINI160x80_PLUGIN);
  // tft.setTextWrap(true);
  tft.setFont(NULL);
  tft.setRotation(1);
  tft.fillScreen(ST7735_BLACK);
  digitalWrite(LCD_BLK,HIGH);
}
//开机
void powerOn(){
  digitalWrite(POWER_C,HIGH);
}
//关机
void powerOff(){
  digitalWrite(POWER_C,LOW);
}
void startLD(){
  digitalWrite(LD_CTRL,HIGH);
  digitalWrite(LD_POWER,LOW);
  attachInterrupt(digitalPinToInterrupt(SIGNAL), pulseInterrupt, FALLING);  // 下降沿触发   
}
void stopLD(){
  digitalWrite(LD_CTRL,LOW);
  digitalWrite(LD_POWER,HIGH);
  detachInterrupt(digitalPinToInterrupt(SIGNAL));
}
void startHALL(){
  digitalWrite(HL_POWER,LOW);
  attachInterrupt(digitalPinToInterrupt(SIGNAL), pulseInterrupt, FALLING);  // 下降沿触发
}
void stopHALL(){
  digitalWrite(HL_POWER,HIGH);
  detachInterrupt(digitalPinToInterrupt(SIGNAL));
}
void stop(int menu){
  isStart=false;
  stopLD();
  stopHALL();
}
// 刷新电池图标
void refreshBat(){
    int analogValue = analogRead(BAT_ADC); 
    int endX=156;
    int length=24;
    // 4.15(643)满格  3.5(543)没电
    int max=643;
    int min=543;
    float step=(max-min)/length;
    step=(analogValue-min)/step;
    if(step<0)
      step=0;
    else if(step>length)
      step=length;
    length=round(step);
    //电池头
    tft.fillRect(130,7,2,10,ST7735_WHITE);
    //电池体外壳
    tft.drawRect(132,4,26,16,ST7735_WHITE);
    //清空
    tft.fillRect(133,5,24,14,ST7735_BLACK);
    //电量
    tft.fillRect(endX-length+1,5,length,14,ST7735_GREEN);
}
//菜单切换
void switchMenu (int menu){
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(0,0,120,24,ST7735_BLACK);
  tft.drawRect(0,0,41,24,ST7735_GREEN);
  tft.drawRect(40,0,41,24,ST7735_GREEN);
  tft.drawRect(80,0,41,24,ST7735_GREEN);
  tft.fillRect((menu-1)*40,0,41,24,ST7735_GREEN);
  // tft.setFont(&FreeSerifBold12pt7b);
  tft.setTextSize(2);
  tft.setTextColor(menu==1?ST7735_RED:ST7735_GREEN);
  tft.setCursor(3,5);
  tft.print("RPM");
  tft.setTextColor(menu==2?ST7735_RED:ST7735_GREEN);
  tft.setCursor(43,5);
  tft.print("CTR");
  tft.setTextColor(menu==3?ST7735_RED:ST7735_GREEN);
  tft.setCursor(88,5);
  tft.print("IR");
  tft.fillRect(0,25,160,55,ST7735_BLACK);
}
//刷新RPM界面
void refreshRPM(){
  float rps;
  char buffer[7]; // 6位数字 + 1位字符串结束符 '\0'
  long lRps; // 四舍五入取整
  long ms=millis();
  //micro时钟溢出或者第一次统计,不计算
  if(delayTime>0){
    rps=1000000.0/delayTime;
    if((rps*60)<6)
      rps=0;
  }
  //最低频率限制 6rpm,小于6rpm时为0
  if((lastTime/1000+1000*10)<ms)
    rps=0;
  if(rpsMax<rps)
    rpsMax=rps;
  if(!isStart){
    rps=rpsMax;
  }
  // tft.setFont(&FreeSerifBold12pt7b);
    tft.setTextSize(2);
  tft.setTextColor(ST7735_YELLOW,ST7735_BLACK);
  tft.setCursor(0,40);
  if(isStart)
    tft.print("RPM:");
  else
    tft.print("MAX:");
  tft.setTextColor(ST7735_MAGENTA,ST7735_BLACK);
  tft.setCursor(0,65);
  tft.print("RPS:");
  tft.setTextColor(ST7735_MAGENTA,ST7735_BLACK);
  tft.setCursor(52,65);
  lRps= (long)round(rps);
  sprintf(buffer, "%05d", lRps);
  //  tft.fillRect(45, 60, 115, 20, ST7735_BLACK);
  tft.print(buffer); 
  // tft.setFont(&FreeSerifBold18pt7b);
  tft.setTextSize(3);
  tft.setCursor(52,35);
  lRps= (long)round(rps*60);
  //上限999999,超过999999显示999999红色
  tft.setTextColor(lRps<UPPER_LIMIT?ST7735_YELLOW:ST7735_RED,ST7735_BLACK);
   if(lRps>UPPER_LIMIT){
    lRps=UPPER_LIMIT;
   }
  sprintf(buffer, "%06d", lRps);
  //  tft.fillRect(45, 30, 115, 30, ST7735_BLACK);
  tft.print(buffer); 
  tft.setTextSize(2);
  tft.setTextColor(isStart?ST7735_GREEN:ST7735_RED,ST7735_BLACK);
  tft.setCursor(135,65);
  tft.print(isLD?"LD":"HL");
  
}
void refreshCTR(){
  if(isStart){
    runningTime=millis()/1000-startTime/1000;
  }
  char buffer[9]; // 6位数字 + 1位字符串结束符 '\0'
  tft.setTextSize(2);
  tft.setTextColor(ST7735_YELLOW,ST7735_BLACK);
  tft.setCursor(0,40);
  tft.print("CTR:");
  int hours = runningTime / 3600;
  int remainingSeconds = runningTime % 3600;
  int minutes = remainingSeconds / 60;
  int seconds = remainingSeconds % 60;
  sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
  tft.setTextColor(ST7735_MAGENTA,ST7735_BLACK);
  tft.setCursor(0,65);
  tft.print(buffer); 
  tft.setTextSize(3);
   tft.setTextColor(ST7735_YELLOW,ST7735_BLACK);
   tft.setTextColor(count<UPPER_LIMIT?ST7735_YELLOW:ST7735_RED,ST7735_BLACK);
  tft.setCursor(52,35);
  sprintf(buffer, "%06d", count<UPPER_LIMIT?count:UPPER_LIMIT);
  tft.print(buffer); 
  tft.setTextSize(2);
  tft.setTextColor(isStart?ST7735_GREEN:ST7735_RED,ST7735_BLACK);
  tft.setCursor(135,65);
  tft.print(isLD?"LD":"HL");
}
void btnHandler(){
  //菜单切换
  if(menu<0){
    menu=-menu;
    switchMenu(menu);
    isStart=false;
    stop(menu);
    switch(menu){
      case 1:
        rps=0;
        delayTime=100000000;
        rpsMax=0;
        break;
      case 2:
        count=0;  
        startTime=millis();
        runningTime=0;
    }
  }
  //RPM页面按键处理
  if(menu==1){
    if(isBtn2Click){
      isBtn2Click=false;
      isLD=!isLD;
    }
    if(isBtn3Click){
      isBtn3Click=false;
      isStart=!isStart;
      if(isStart){
        rps=0;
        rpsMax=0;
        if(isLD)
          startLD();
        else
          startHALL();
      }else{
        stop(menu);
      }
    }
    //CTR页面按键处理
  }else if(menu==2){
    if(isBtn2Click){
      isBtn2Click=false;
      isLD=!isLD;
    }
    if(isBtn3Click){
      isBtn3Click=false;
      isStart=!isStart;
      if(isStart){
         count=0;  
        startTime=millis();
        if(isLD)
          startLD();
        else
          startHALL();
      }else{
        stop(menu);
      }
    }
  }
  else if(menu==3){
  }
}
void setup() {
  Serial.setTx(SERIAL_TX);
  Serial.setRx(SERIAL_RX);
  Serial.begin(115200);
  initPin();
  delay(800);
  powerOn();
  initLCD();
  btnPower.attachClick(btnPowerClick);
  btnPower.attachLongPressStart(btnPowerLongPress);
  btn2.attachClick(btn2Click);
  btn3.attachClick(btn3Click);
}
long refreshTime;
// the loop function runs over and over again forever
void loop() {
  long ms=millis();
  //屏幕刷新
  if((ms-refreshTime)>200){
    refreshTime=ms;
    refreshBat();
    if(menu==1)
      refreshRPM();
    else if (menu==2){
      refreshCTR();
    }
  }
  //按键tick
  btnPower.tick();
  btn2.tick();
  btn3.tick();
  //按键处理
  btnHandler();
}
 
 | 
 打赏
查看全部打赏
 |