arduino 中snprintf和sprintf函数的使用注意
arduino 中snprintf和sprintf函数的使用注意
作者:多西多软件
阅读:5
更新:2024-10-09
arduino 中snprintf和sprintf函数的使用注意
在 Arduino 的标准库中,Serial.println()
函数并不支持像 C 语言中的 printf
函数那样的格式化字符串。因此,不能直接使用 Serial.println("%d", 1)
这种格式来打印。在 Arduino 中,需要以不同的方式来打印变量。
要想使用类似C语言的格式化打印风格可以使用:
char message[20];
int number = 1;
sprintf(message, "The number is: %d", number);
Serial.println(message);
除了sprintf,另一个更安全的选择是使用 snprintf()
,它允许指定缓冲区的最大大小,从而避免溢出:
char buffer[50];
int temperature = 23;
float humidity = 50.5;
snprintf(buffer, sizeof(buffer), "Temperature: %d C, Humidity: %.1f%%", temperature, humidity);
Serial.println(buffer);
值得注意的是两种函数的缓冲存储数组大小一定要比,后面打印的字符串大小要大,否则溢出将可能影响程序当中的其余变量,2024年1月7日调试了下午的BUG:
/******************************Sound_follower*********************************
@Data: 2024.1.7
@Version: 1
@Site: HITSZ
******************************************************************************/
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define Do_C 262
#define Re_D 294
#define Mi_E 330
#define Fa_F 349
#define Sol_G 392
#define La_A 440
#define Si_B 494// 对应每个按键的音符频率(Do_C, Re_D, Mi_E, Fa_F, Sol_G, La_A, Si_B)
#define TITLE "TITLE"
int numberOfButtons = 7;
int buttonPins[] = {2, 3, 4, 5, 6, 7, 8};//numberOfButtons个按键对应的引脚号
volatile bool button_pressed_flag = 0;//按键按下标志位1(有):0(无)
int button_pressed_num_per_cycle = 0;//每个检测周期按键按下的次数
int buzzerPin = 9;//蜂鸣器对于的引脚号
int Sound_Delay = 500;//单位毫秒
unsigned long lastInterruptTime = 0;// 记录程序执行时间的变量
char message[50];//OLED显示存储变量,需要设置的比显示字符大,否则溢出可能会导致程序中其余变量的值被修改
const int notes[] = {Do_C, Re_D, Mi_E, Fa_F, Sol_G, La_A, Si_B};
// String Display_notes[] = {"Do", "Re", "Mi", "Fa", "Sol", "La", "Si"};//*使用string 无法实现数组的结构化打印,虽然串口显示数据正确,但到OLED就是乱码,原因待查
const char* Display_notes[] = {"Do", "Re", "Mi", "Fa", "Sol", "La", "Si"};
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);// 初始化OLED显示屏对象,设置分辨率为128x64
void setup() {
pinMode(buzzerPin, OUTPUT);
for(int i = 0; i < numberOfButtons; i++){
pinMode(buttonPins[i], INPUT_PULLUP);
}
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// 初始化OLED显示屏
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);//必须得设置文本颜色,不能取消注释
display.setCursor(10, 30);//(列,行)
snprintf(message, sizeof(message), "Welcome to %s", TITLE);
display.println(message);
display.display();// 更新显示内容
}
void loop() {
unsigned long currentTime = millis();//记录当前时间,实现按键无阻塞循环检测
button_pressed_num_per_cycle = 0;
for(int i = 0; i < numberOfButtons; i++){
if(digitalRead(buttonPins[i]) == LOW){ // 如果按键被按下
button_pressed_flag = 1;//按键按下标志位置1
button_pressed_num_per_cycle ++;//统计一个周期内,numberOfButtons个按键按下的个数
tone(buzzerPin, notes[i]); // 播放音符
// while(digitalRead(buttonPins[i]) == LOW); //需要按键按多久,蜂鸣器响多久,就取消改行注释
display.clearDisplay();
display.setTextSize(1);
display.setCursor(10, 8);//(列,行)
display.println(TITLE);// 显示提示信息 Drawing Shapes
display.setCursor(8, 25);
snprintf(message, sizeof(message), "Button %d is pressed!", i);
// sprintf(message, "Button %d is pressed!", i);
//使用时message大小如果设置为20,此处会造成缓冲区溢出,下面的button_pressed_flag变量会被修改,为了避免溢出,需要将message的空间设置的比显示字符大
display.println(message);
display.setCursor(10, 42);
snprintf(message, sizeof(message), "Buzzer ON: %s", Display_notes[i]);
display.println(message);
display.display();// 更新显示内容
}
}
if (button_pressed_num_per_cycle == 0){//一个扫描周期内无按键按下时,按键按下标志位置0
button_pressed_flag = 0;
}
if ((currentTime - lastInterruptTime > Sound_Delay) && (button_pressed_flag == false)) {// 检查自上次中断以来是否已经过了足够的消抖时间
lastInterruptTime = currentTime;
noTone(buzzerPin); // 延时Sound_Delay,停止播放音符
display.clearDisplay();
display.setTextSize(1);
display.setCursor(10, 8);//(列,行)
display.println(TITLE);// 显示提示信息 Drawing Shapes
display.setCursor(10, 25);
display.println("No button pressed!");
display.setCursor(10, 42);
display.println("Buzzer OFF");
display.display();// 更新显示内容
}
}
如果char message[50];/中message的大小被修改为20以内包括20,loop循环中button_pressed_flag 的值竟然会被影响,影响源是snprintf(message, sizeof(message), "Button %d is pressed!", i);中显示的字符刚好达到了20位。
调试了一下午,终于在19点解决了这个BUG:
相关文章
在linux上安装运行virtualBox虚拟机的详细步骤
作者:多西多软件
阅读:3
更新:2024-10-15
在 Windows 11 中将登录方式修改为本地账户登录的步骤
作者:多西多软件
阅读:2
更新:2024-10-25
GDSFactory是一个使用Python语言编写的开源设计工具软件包,主要用于快速、高效地生成GDSII(Graphic Data System II)格式的集成电路布局和掩模图形。GDSII是一种
作者:多西多软件
阅读:1
更新:2024-11-04