esp8266-01虽然小众,但是功能可不能少。因航模需要让ESP8266-01生成PPM波形。
#include <ESP8266WiFi.h>
#include <Ticker.h> // 仅用于延时函数替代
#define PPM_PIN 2 // 使用 GPIO2 (需断开串口上传时的连接)
#define CHANNELS 4 // PPM通道数量
#define FRAME_LENGTH 22500 // 完整PPM帧长度(us) - 标准22.5ms
#define SYNC_PULSE 400 // 同步脉冲宽度(us)
#define CHANNEL_PULSE 200 // 通道脉冲宽度(us)
// 通道数据 (单位: 微秒 us)
int ppmValues[CHANNELS] = {1150, 1240, 1180, 1195};
volatile unsigned int currentChannel = 0;
volatile unsigned long nextEdge = 0;
bool outputState = false;
// 硬件定时器中断 (每1us计数)
void IRAM_ATTR onTimer() {
static unsigned long counter = 0;
counter++;
if (counter >= nextEdge) {
if (!outputState) {
// 开始新脉冲
digitalWrite(PPM_PIN, HIGH);
outputState = true;
// 设置脉冲结束时间
nextEdge = counter + (currentChannel == 0 ? SYNC_PULSE : CHANNEL_PULSE);
} else {
// 结束当前脉冲
digitalWrite(PPM_PIN, LOW);
outputState = false;
// 移动到下一通道
currentChannel = (currentChannel + 1) % (CHANNELS + 1);
// 设置下一脉冲开始时间
if (currentChannel == 0) {
nextEdge = counter + FRAME_LENGTH - SYNC_PULSE;
} else {
nextEdge = counter + ppmValues[currentChannel - 1] - CHANNEL_PULSE;
}
}
}
}
void setup() {
pinMode(PPM_PIN, OUTPUT);
digitalWrite(PPM_PIN, LOW);
// 配置硬件定时器 (Timer1)
noInterrupts();
timer1_isr_init();
timer1_attachInterrupt(onTimer);
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP); // 预分频1 (80MHz -> 80MHz)
timer1_write(80); // 80 ticks = 1us @ 80MHz (80,000,000 / 1,000,000 = 80)
interrupts();
}
void loop() {
// 这里可以动态更新通道数据
// 例如: ppmValues[0] = analogRead(A0) / 4 + 1000;
ppmValues[0] = ppmValues[0]+1;
ppmValues[1] = ppmValues[1]+2;
ppmValues[2] = ppmValues[2]+3;
ppmValues[3] = ppmValues[3]+4;
if(ppmValues[0] >=2000) ppmValues[0] =1000;
if(ppmValues[1] >=2000) ppmValues[1] =1000;
if(ppmValues[2] >=2000) ppmValues[2] =1000;
if(ppmValues[3] >=2000) ppmValues[3] =1000;
delay(50);
}
观察波形:
