:(i)使用Arduino控制OLED显示屏SSD1306(proteus中搜索UG-2864HSWEG01),在屏幕上显示一个尽可能大的时钟表盘,包含12个刻度和对应的1~12数字,以及一个秒针。秒针最初向上指向数字12。 (ii)Arduino上连接1个按钮。按钮第一次按下,秒表开始计时,秒针要准确地转动。按钮第二次按下,秒针暂停,在时钟表盘旁边用数字显示过去了多少秒(精确到0.01秒)。按钮第三次按下,秒针接着继续转动。第四次按下,秒针再次暂停,在时钟表盘旁边换行用数字显示过去了多少秒(精确到0.01秒)。第五次按下,同第三次……如此重复。 (iii)使用定时器进行准确的计时。Arduino上再加1个按钮,此按钮按下时,秒针归零。全部重新开始。
时间: 2023-07-15 21:12:16 浏览: 186
好的,这个问题比较复杂,需要分步骤来实现。
1. 硬件连接
首先,我们需要将Arduino与OLED显示屏和按钮连接起来。我们可以将OLED显示屏的VCC引脚接到Arduino的5V引脚上,GND引脚接到Arduino的GND引脚上,SCL引脚接到Arduino的A5引脚上,SDA引脚接到Arduino的A4引脚上。
然后,我们需要将按钮连接到Arduino的数字引脚上,例如将按钮连接到数字引脚2上。
2. 显示时钟表盘
接下来,我们需要使用Arduino控制OLED显示屏来显示时钟表盘。我们可以使用Adafruit_SSD1306库来控制OLED显示屏,并使用Arduino的Wire库来与OLED显示屏通信。
下面是一个简单的代码示例,可以在OLED显示屏上显示时钟表盘:
```C++
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.drawCircle(64, 32, 30, WHITE);
for (int i = 1; i <= 12; i++) {
float angle = i * PI / 6 - PI / 2;
int x = 64 + 23 * cos(angle);
int y = 32 + 23 * sin(angle);
display.setTextSize(2);
display.setCursor(x - 7, y - 8);
display.print(i);
}
display.display();
}
void loop() {
}
```
在上面的代码中,我们使用了`Adafruit_SSD1306`库来控制OLED显示屏,首先初始化了显示屏,并清除了显示内容。然后,我们绘制了一个半径为30的圆形,作为时钟表盘。接着,我们使用一个循环来绘制12个数字,并计算每个数字在圆周上的位置。最后,我们将数字显示在屏幕上,并调用`display.display()`函数来显示内容。
3. 显示秒针
接下来,我们需要在时钟表盘上显示秒针。我们可以使用Arduino的`millis()`函数来计算时间,并根据时间来更新秒针的位置。
下面是一个示例代码:
```C++
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
const int BUTTON_PIN = 2;
volatile bool button_pressed = false;
void button_handler() {
button_pressed = true;
}
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.drawCircle(64, 32, 30, WHITE);
for (int i = 1; i <= 12; i++) {
float angle = i * PI / 6 - PI / 2;
int x = 64 + 23 * cos(angle);
int y = 32 + 23 * sin(angle);
display.setTextSize(2);
display.setCursor(x - 7, y - 8);
display.print(i);
}
display.display();
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), button_handler, RISING);
}
void loop() {
static unsigned long last_time = 0;
static unsigned long elapsed_time = 0;
static bool running = false;
if (button_pressed) {
button_pressed = false;
running = !running;
if (!running) {
elapsed_time = millis() - last_time;
}
}
if (running) {
unsigned long current_time = millis();
elapsed_time += current_time - last_time;
last_time = current_time;
float angle = elapsed_time / 1000.0 * PI / 30 - PI / 2;
int x = 64 + 20 * cos(angle);
int y = 32 + 20 * sin(angle);
display.drawLine(64, 32, x, y, WHITE);
display.display();
} else {
if (elapsed_time > 0) {
char buffer[20];
sprintf(buffer, "%.2f s", elapsed_time / 1000.0);
display.setTextSize(1);
display.setCursor(0, 40);
display.print(buffer);
display.display();
}
}
}
```
在上面的代码中,我们使用了一个变量`last_time`来记录上一次更新秒针的时间,使用一个变量`elapsed_time`来记录经过的时间。我们使用了一个变量`running`来记录秒表是否正在运行。当按钮被按下时,我们切换`running`的状态,并记录经过的时间。
在`loop()`函数中,如果秒表正在运行,我们计算当前时间与上一次更新秒针的时间之差,并将这个差值加到`elapsed_time`中。然后,我们根据`elapsed_time`计算秒针的位置,并在屏幕上绘制秒针。最后,我们调用`display.display()`函数来显示更新后的内容。
如果秒表没有运行,我们将`elapsed_time`转换为字符串,并在屏幕上显示出来。
4. 归零秒针
最后,我们需要添加一个按钮来归零秒针。我们可以将另一个按钮连接到Arduino的数字引脚3上,并在代码中添加相应的处理程序。
下面是最终的代码:
```C++
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
const int START_STOP_BUTTON_PIN = 2;
volatile bool start_stop_button_pressed = false;
const int RESET_BUTTON_PIN = 3;
volatile bool reset_button_pressed = false;
void start_stop_button_handler() {
start_stop_button_pressed = true;
}
void reset_button_handler() {
reset_button_pressed = true;
}
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.drawCircle(64, 32, 30, WHITE);
for (int i = 1; i <= 12; i++) {
float angle = i * PI / 6 - PI / 2;
int x = 64 + 23 * cos(angle);
int y = 32 + 23 * sin(angle);
display.setTextSize(2);
display.setCursor(x - 7, y - 8);
display.print(i);
}
display.display();
pinMode(START_STOP_BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(START_STOP_BUTTON_PIN), start_stop_button_handler, RISING);
pinMode(RESET_BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RESET_BUTTON_PIN), reset_button_handler, RISING);
}
void loop() {
static unsigned long last_time = 0;
static unsigned long elapsed_time = 0;
static bool running = false;
if (start_stop_button_pressed) {
start_stop_button_pressed = false;
running = !running;
if (!running) {
elapsed_time = millis() - last_time;
}
}
if (reset_button_pressed) {
reset_button_pressed = false;
last_time = millis();
elapsed_time = 0;
running = false;
display.clearDisplay();
display.drawCircle(64, 32, 30, WHITE);
for (int i = 1; i <= 12; i++) {
float angle = i * PI / 6 - PI / 2;
int x = 64 + 23 * cos(angle);
int y = 32 + 23 * sin(angle);
display.setTextSize(2);
display.setCursor(x - 7, y - 8);
display.print(i);
}
display.display();
}
if (running) {
unsigned long current_time = millis();
elapsed_time += current_time - last_time;
last_time = current_time;
float angle = elapsed_time / 1000.0 * PI / 30 - PI / 2;
int x = 64 + 20 * cos(angle);
int y = 32 + 20 * sin(angle);
display.drawLine(64, 32, x, y, WHITE);
display.display();
} else {
if (elapsed_time > 0) {
char buffer[20];
sprintf(buffer, "%.2f s", elapsed_time / 1000.0);
display.setTextSize(1);
display.setCursor(0, 40);
display.print(buffer);
display.display();
}
}
}
```
在上面的代码中,我们添加了一个按钮来归零秒针,并在`setup()`函数中添加了相应的处理程序。当按钮被按下时,我们将`last_time`和`elapsed_time`都重置为0,并清除屏幕上的显示内容,重新绘制时钟表盘。
现在,你可以将这个代码上传到Arduino上,并使用按钮来控制秒表的运行和归零。
阅读全文