ESP32+FreeRTOS
Esp32 模块中已经提供了 FreeRTOS(实时操作系统)固件。
FreeRTOS有助于提高系统性能和管理模块的资源。FreeRTOS允许用户处理多项任务,如测量传感器读数,发出网络请求,控制电机速度等,所有这些任务都可以同时独立运行。
FreeRTOS为不同的应用程序提供了多个API。这些 API 可用于创建任务并使其在不同内核上运行。您需要创建任务以将代码的特定部分分配给特定内核。您还可以确定代码将在哪个内核上运行的优先级。
硬件
软件
tone()
函数
Arduino 内置函数:Reference > Language > Functions > Advanced io > Tone
在引脚上生成指定频率(和 50% 占空比)的方波。可以指定持续时间,否则波形会一直持续到调用 noTone()
。该引脚可以连接到压电蜂鸣器或其他扬声器以播放音调。 一次只能产生一种音调。如果一个音调已经在另一个引脚上播放,则对tone() 的调用将无效。如果音调在同一个引脚上播放,则呼叫将设置其频率。 使用tone() 函数会干扰引脚3 和11 上的PWM 输出(在Mega以外的板上)。 不可能产生低于 31Hz 的音调。
语法
tone(pin, frequency) // 语法一
tone(pin, frequency, duration) // 语法二
入口参数:
- pin: 生成音调的 Arduino 引脚。
- frequency: 以赫兹为单位的音调频率。允许的数据类型:
unsigned int
无符号整数。 - duration: 以毫秒为单位的音调持续时间(可选)。允许的数据类型:
unsigned long
noTone()
函数
停止生成由tone() 触发的方波。如果没有生成音调,则无效。
语法
noTone(pin)
注意: 如果您想在多个引脚上播放不同的音高,您需要在一个引脚上调用 noTone(),然后再在下一个引脚上调用tone()。
示例程序
开发环境是VSCode + PlatformIO IDE
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
// buzzer pin
#define BUZZER 19
#define ADC_PIN 34
uint16_t adc = 0;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // U8G2_R0:屏幕旋转0°度
/**
* @brief 屏幕显示界面1
* @param 无
* @param 无
* @retval adc:检测电池电量ADC34
*/
void page1(int adc) {
u8g2.setFont(u8g2_font_helvR08_tf); //设置字体 字号 字形
u8g2.setFontPosTop(); // 设置定位的位置以字符顶开始
u8g2.setCursor(0,0); // 设置屏幕坐标
u8g2.print(String("ADC:") + String(adc));
u8g2.nextPage();//刷新屏幕
}
/**
* @brief 《两只老虎》简谱
* @param 无
* @param 无
* @retval count:计数
*/
void two_tigers_music_play()
{
byte count = 0; // byte 占1个字节 1*8bit=8位 0~256 节省内存
// low 1-7 低音
unsigned int LOW_1 = 262; // unsigned int 占4个字节 4*8bit=32位 0~4294967295
unsigned short LOW_1_P_5 = 277; // unsigned short 等于 uint16_t
uint16_t LOW_2 = 294; // uint16_t 占2个字节 2*8bit=16位 0~65535
uint16_t LOW_2_P_5 = 311;
uint16_t LOW_3 = 330;
uint16_t LOW_4 = 349;
uint16_t LOW_4_P_5 = 370;
uint16_t LOW_5 = 392;
uint16_t LOW_5_P_5 = 415;
uint16_t LOW_6 = 440;
uint16_t LOW_6_P_5 = 466;
uint16_t LOW_7 = 494;
for (count = 0; count < 2; count++) // 每句歌词唱两遍
{
tone(BUZZER, LOW_1);
delay(500);
tone(BUZZER, LOW_2);
delay(500);
tone(BUZZER, LOW_3);
delay(500);
tone(BUZZER, LOW_1);
delay(500);
noTone(BUZZER);
delay(500);
}
for (count = 0; count < 2; count++)
{
tone(BUZZER, LOW_3);
delay(500);
tone(BUZZER, LOW_4);
delay(500);
tone(BUZZER, LOW_5);
delay(1000);
noTone(BUZZER);
delay(500);
}
for (count = 0; count < 2; count++)
{
tone(BUZZER, LOW_5);
delay(350);
tone(BUZZER, LOW_6);
delay(150);
tone(BUZZER, LOW_5);
delay(350);
tone(BUZZER, LOW_4);
delay(150);
tone(BUZZER, LOW_3);
delay(500);
tone(BUZZER, LOW_1);
delay(500);
noTone(BUZZER);
delay(500);
}
for (count = 0; count < 2; count++)
{
tone(BUZZER, LOW_1_P_5);
delay(500);
tone(BUZZER, LOW_5_P_5);
delay(500);
tone(BUZZER, LOW_1_P_5);
delay(1000);
noTone(BUZZER);
delay(500);
}
}
/**
* @brief 任务2函数
* @param 无
* @param 无
* @retval pvParameters:
*/
void task_2( void * pvParameters ){
for(;;){
adc = analogRead(ADC_PIN);
page1(adc); // 显示电量
vTaskDelay(1);
}
}
/**
* @brief 任务3函数
* @param 无
* @param 无
* @retval pvParameters:
*/
void task_3( void * pvParameters ){
for(;;){
two_tigers_music_play();// 播放营业
vTaskDelay(1);
}
}
/**
* @brief 初始化setup()
* @param 无
* @param 无
* @retval
*/
void setup() {
pinMode(BUZZER, OUTPUT);
pinMode(ADC_PIN, INPUT);
u8g2.enableUTF8Print();
u8g2.setI2CAddress(0x3C*2);
u8g2.begin();
u8g2.firstPage();
do
{
page1(adc);
}while(u8g2.nextPage());
xTaskCreatePinnedToCore(task_2, "task_2", 4096, NULL, 0, NULL, 1);
xTaskCreatePinnedToCore(task_3, "task_3", 4096, NULL, 8, NULL, 1);
//xTaskCreatePinnedToCore 函数参数说明:
// task_2:实现任务的函数名称(task1)
// "task_2":任务的任何名称(“ task1”等)
// 4096:分配给任务的堆栈大小,以字为单位
// NULL:任务输入参数(可以为NULL)
// 2:任务的优先级(0是最低优先级)
// NULL:任务句柄(可以为NULL)
// 1:任务将运行的ESP32D的内核ID(0或1)
}
void loop() {
vTaskDelay(1);
}
参考资料
- [1] 使用ARDUINO UNO和无源蜂鸣器实现音乐-《两只老虎》
- [2] Arduino之运用u8gbil库控制OLED
- [3] Mixly2.0 中自带u8g2和freeRTOS积木模块