在已知头文件#include <stdint.h>,#include <TFTv2.h>,#include <SPI.h>并且只能使用两个按钮的情况下,使用Arduino控制显示屏ili9341,在屏幕上显示一个尽可能大的时钟表盘,包含12个刻度和对应的1~12数字,以及一个秒针。秒针最初向上指向数字12。 () Arduino 上连接1个按钮。按钮第一次按下,秒表开始计时,秒针要准确地转动。按钮第二次按下,秒针暂停,在时钟表盘旁边用数字显示过去了多少秒(精确到0.01秒)。按钮第三次按下,秒针接着继续转动。第四次按下,秒针再次暂停,在时钟表盘旁边换行用数字显示过去了多少秒(精确到0.01秒)。第五次按下,同第三次……如此重复。 (iii)使用定时暴进行准确的计时。Arduino 上再加1个按钮,此按钮按下时,秒针归零。全部重新开始。如何在仿真平台上实现
时间: 2023-12-29 07:03:45 浏览: 128
首先,需要定义一些常量和变量,如屏幕尺寸、刻度半径、数字半径、秒针长度、按钮引脚等。代码如下:
```c++
#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define SCALE_RADIUS 80
#define NUM_RADIUS 60
#define SEC_LENGTH 70
#define BUTTON_PIN 2
TFT TFTscreen = TFT(SCREEN_WIDTH, SCREEN_HEIGHT);
volatile bool buttonPressed = false;
volatile bool reset = false;
volatile uint32_t startMillis = 0;
volatile uint32_t pauseMillis = 0;
void interruptHandler() {
buttonPressed = true;
}
```
接着,在`setup()`函数中初始化TFT屏幕、SPI接口、按钮以及定时器,代码如下:
```c++
void setup() {
TFTscreen.begin();
SPI.begin();
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), interruptHandler, FALLING);
Timer1.initialize(10000);
Timer1.attachInterrupt(timerHandler);
}
```
在`loop()`函数中,首先判断按钮是否按下,如果按下了,则执行相应的操作。如果是第一次按下,记录当前时间戳;如果是第二次按下,计算过去了多少秒并显示在屏幕上;如果是第三次按下,恢复计时;如果是第四次按下,同第二次按下;如果是第五次按下,同第三次按下。代码如下:
```c++
void loop() {
static uint8_t state = 0;
static uint32_t prevMillis = 0;
if (buttonPressed) {
buttonPressed = false;
switch (state) {
case 0:
startMillis = millis();
state = 1;
break;
case 1:
pauseMillis = millis();
state = 2;
break;
case 2:
startMillis += millis() - pauseMillis;
state = 1;
break;
case 3:
pauseMillis = millis();
state = 4;
break;
case 4:
uint32_t elapsedMillis = pauseMillis - startMillis;
uint16_t seconds = elapsedMillis / 1000;
uint16_t millisecs = elapsedMillis % 1000;
char buffer[16];
sprintf(buffer, "%d.%02d", seconds, millisecs / 10);
TFTscreen.stroke(255, 255, 255);
TFTscreen.setTextSize(2);
TFTscreen.text(buffer, SCREEN_WIDTH - 80, SCREEN_HEIGHT - 40);
state = 3;
break;
}
}
if (reset) {
reset = false;
startMillis = millis();
state = 1;
}
uint32_t currentMillis = millis();
if (currentMillis - prevMillis >= 1000) {
prevMillis = currentMillis;
drawClock();
}
}
```
最后,还需要定义定时器的中断处理函数`timerHandler()`,用于更新秒针位置。代码如下:
```c++
void timerHandler() {
static uint16_t prevSeconds = 0;
uint32_t elapsedMillis = millis() - startMillis;
uint16_t seconds = elapsedMillis / 1000;
if (seconds != prevSeconds) {
TFTscreen.stroke(0, 0, 0);
TFTscreen.line(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2,
SCREEN_WIDTH / 2 + SEC_LENGTH * sin((seconds - 15) * PI / 30),
SCREEN_HEIGHT / 2 - SEC_LENGTH * cos((seconds - 15) * PI / 30));
TFTscreen.stroke(255, 0, 0);
TFTscreen.line(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2,
SCREEN_WIDTH / 2 + SEC_LENGTH * sin((seconds - 15) * PI / 30),
SCREEN_HEIGHT / 2 - SEC_LENGTH * cos((seconds - 15) * PI / 30));
prevSeconds = seconds;
}
}
```
完整的代码如下:
```c++
#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>
#include <TimerOne.h>
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define SCALE_RADIUS 80
#define NUM_RADIUS 60
#define SEC_LENGTH 70
#define BUTTON_PIN 2
TFT TFTscreen = TFT(SCREEN_WIDTH, SCREEN_HEIGHT);
volatile bool buttonPressed = false;
volatile bool reset = false;
volatile uint32_t startMillis = 0;
volatile uint32_t pauseMillis = 0;
void interruptHandler() {
buttonPressed = true;
}
void timerHandler() {
static uint16_t prevSeconds = 0;
uint32_t elapsedMillis = millis() - startMillis;
uint16_t seconds = elapsedMillis / 1000;
if (seconds != prevSeconds) {
TFTscreen.stroke(0, 0, 0);
TFTscreen.line(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2,
SCREEN_WIDTH / 2 + SEC_LENGTH * sin((seconds - 15) * PI / 30),
SCREEN_HEIGHT / 2 - SEC_LENGTH * cos((seconds - 15) * PI / 30));
TFTscreen.stroke(255, 0, 0);
TFTscreen.line(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2,
SCREEN_WIDTH / 2 + SEC_LENGTH * sin((seconds - 15) * PI / 30),
SCREEN_HEIGHT / 2 - SEC_LENGTH * cos((seconds - 15) * PI / 30));
prevSeconds = seconds;
}
}
void drawClock() {
TFTscreen.background(255, 255, 255);
TFTscreen.stroke(0, 0, 0);
TFTscreen.fill(255, 255, 255);
TFTscreen.circle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCALE_RADIUS);
TFTscreen.setTextSize(3);
for (uint8_t i = 0; i < 12; i++) {
uint16_t x = SCREEN_WIDTH / 2 + SCALE_RADIUS * sin(i * PI / 6);
uint16_t y = SCREEN_HEIGHT / 2 - SCALE_RADIUS * cos(i * PI / 6);
TFTscreen.text(String(i + 1), x - 8, y - 16);
TFTscreen.line(x, y, x + NUM_RADIUS * sin(i * PI / 6), y - NUM_RADIUS * cos(i * PI / 6));
}
}
void setup() {
TFTscreen.begin();
SPI.begin();
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), interruptHandler, FALLING);
Timer1.initialize(10000);
Timer1.attachInterrupt(timerHandler);
}
void loop() {
static uint8_t state = 0;
static uint32_t prevMillis = 0;
if (buttonPressed) {
buttonPressed = false;
switch (state) {
case 0:
startMillis = millis();
state = 1;
break;
case 1:
pauseMillis = millis();
state = 2;
break;
case 2:
startMillis += millis() - pauseMillis;
state = 1;
break;
case 3:
pauseMillis = millis();
state = 4;
break;
case 4:
uint32_t elapsedMillis = pauseMillis - startMillis;
uint16_t seconds = elapsedMillis / 1000;
uint16_t millisecs = elapsedMillis % 1000;
char buffer[16];
sprintf(buffer, "%d.%02d", seconds, millisecs / 10);
TFTscreen.stroke(255, 255, 255);
TFTscreen.setTextSize(2);
TFTscreen.text(buffer, SCREEN_WIDTH - 80, SCREEN_HEIGHT - 40);
state = 3;
break;
}
}
if (reset) {
reset = false;
startMillis = millis();
state = 1;
}
uint32_t currentMillis = millis();
if (currentMillis - prevMillis >= 1000) {
prevMillis = currentMillis;
drawClock();
}
}
```
阅读全文