ESP32的pwm_channel有16个(0-15),在选用时不能重复,也不能与定时器冲突。高速通道(0-7): 80MHz时钟,低速通道(8-15): 1MHz时钟。这里用的是低速通道。
绑定io口
const int Motor_PWM_PinA = 5;
const int Motor_PWM_PinB = 4;
分配pwm通道
const int Motor_channel_PWMA = 2;
const int Motor_channel_PWMB = 3;
设置pwm频率以及分辨率。为了方便之后的调试pwm频率这里是直接设置的,但是不能超过时钟。分辨率将一个周期分成块,分辨率越大,控制精度越高。
// PWM频率,直接设置即可
int Motor_freq_PWM = 1000;
// PWM分辨率,取值为 0-20 之间,这里填写为10,那么后面的ledcWrite这个里面填写的pwm值就在 0 - 2的10次方 之间 也就是 0-1024
int Motor_resolution_PWM = 10;
绑定ledc以及使能pwm
ledcSetup(Motor_channel_PWMA, Motor_freq_PWM, Motor_resolution_PWM); // 设置通道
ledcSetup(Motor_channel_PWMB, Motor_freq_PWM, Motor_resolution_PWM); // 设置通道
ledcAttachPin(Motor_PWM_PinA, Motor_channel_PWMA); //将 LEDC 通道绑定到指定 IO 口上以实现输出
ledcAttachPin(Motor_PWM_PinB, Motor_channel_PWMB);
到这里一个简单的pwm输出就已经设置好了。在使用时只需要输入pwm值就可以输出对应占空比的pwm了。
void PWM_SetDuty(uint16_t DutyA, uint16_t DutyB)
{
ledcWrite(Motor_channel_PWMA, DutyA);
ledcWrite(Motor_channel_PWMB, DutyB);
}
PWM_SetDuty(200, 200);
定时器设置:
// 函数名称:timerBegin()
// 函数功能:Timer初始化,分别有三个参数
// 函数输入:1. 定时器编号(0到3,对应全部4个硬件定时器)
// 2. 预分频器数值(ESP32计数器基频为80M,80分频单位是微秒)
// 3. 计数器向上(true)或向下(false)计数的标志
// 函数返回:一个指向 hw_timer_t 结构类型的指针(hw_timer_t *timer = NULL;)
timer = timerBegin(0, 80, true);
// 函数名称:timerAttachInterrupt()
// 函数功能:绑定定时器的中断处理函数,分别有三个参数
// 函数输入:1. 指向已初始化定时器的指针
// 2. 中断服务函数的函数指针
// 3. 表示中断触发类型是边沿(true)还是电平(false)的标志
// 无返回函数
timerAttachInterrupt(timer, &TimerEvent, true);
// 函数名称:timerAlarmWrite()
// 函数功能:指定触发定时器中断的计数器值,分别有三个参数
// 函数输入:1. 指向已初始化定时器的指针
// 2. 第二个参数是触发中断的计数器值
// 3. 定时器在产生中断时是否重新加载的标志
// 无返回函数
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer); // 使能定时器
举例:
#include <Arduino.h>
int interruptCounter = 0;
hw_timer_t *timer = NULL;
const int Motor_PWM_PinA = 2;
const int Motor_channel_PWMA = 2;
int Motor_freq_PWM = 1000;
int Motor_resolution_PWM = 10;
void IRAM_ATTR TimerEvent()
{
Serial.println(interruptCounter++);
if (interruptCounter > 5)
{
interruptCounter = 1;
}
}
void Motor_Init(void)
{
ledcSetup(Motor_channel_PWMA, Motor_freq_PWM, Motor_resolution_PWM);
ledcAttachPin(Motor_PWM_PinA, Motor_channel_PWMA);
}
void PWM_SetDuty(uint16_t DutyA, uint16_t DutyB)
{
ledcWrite(Motor_channel_PWMA, DutyA);
}
void setup()
{
Serial.begin(115200);
Motor_Init();
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &TimerEvent, true);
timerAlarmWrite(timer, 1000000, true);//1000000us==1s
timerAlarmEnable(timer); // 使能定时器
}
void loop()
{
PWM_SetDuty(200 * interruptCounter, 0);
}
yan'shi's'p