ESP32----Arduino编程笔记

本笔记是基于有一定嵌入式基础的学习比较,但门槛不高

1. 基本的语法

1.1 IO口的基本操作

对于ESP32这类开发板而言,我们开发的本质逻辑其实就是控制IO口的操作,譬如输出一个高电平,或者在某个时候输出一个低电平、PWM,输入如采样AD、检测电平状态等等。因此对于IO口的操作语法是最基本的操作。

首先,Arduino语法与C++类似,与micropython对于Pin脚的操作不同。在Arduino中都是通过函数对Pin脚操作,比如:
pinMode(2, OUTPUT);
这里就是用函数来对Pin2操作

下面列出一些IO的常规操作(只列出比较常用的);

操作指令细化指令对应的Arduino命令备注
初始化端口输出
pinMode(2,OUTPUT)

端口2配置成输出模式;

要使用端口就必须先初始化,先给端口赋予其基本的功能,如输出、输入、AD采样、PWM等等

输入 
pinMode(2,INPUT);//这是是输入引脚,但无内部上拉
pinMode(2,INPUT_PULLUP);//使用内部上拉电阻

端口2配置成输入;可以读出端口的高低电平状态
端口操作输出高低电平
digitalWrite(2,HIGH)//这里将端口2配置为高,还可以设置为低,HIGH改为LOW即可

读取引脚电平
digitalRead(2);//读取2脚电平,读取前需要设置引脚为输入状态

返回的是HIGH或者LOW

注意:设置因为为OUT类型也可以用这个函数读取它的值。

INTPUT与OUTPUT最大的差别是INPUT不会主动改变端口的值,仅仅作为输入

AD采样-读取
pinMode(26,INPUT);//先设置为输入模式
analogRead(26);//读取AD值

AD采样-写
pinMode(2,HIGH);
analogWrite(2,value);//value的值范围为0~255,可以输出一个PWM值,经滤波后可以当DAC来用

低频PWM
analogWrite(pin, value);//value为占空比

这个方法输出一个定频的PWM信号(频率大约为490Hz),value为占空比

不同开发板的脚位不同需要按照支持的脚位来设置

专用PWM主要通过LEDC这个外设来驱动,内容较多,后面章节会详细说明LED PWM 控制器可以生成 16 路通道(0 ~ 15),波形的周期和占空比可配置。分为高低速两组,高速通道(0 ~ 7)由 80MHz 时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。另外,每路 LED PWM 支持自动步进式地增加或减少占空比,可以用于 LED RGB 彩色梯度发生器。
串口初始化及打开串口
Serial.begin(9600);//9600是串口波特率

打印串口
Serial.println(value);//打印数据在串口,value可以是任意类型
Serial.wirte(data);//打印串口数据,但data的值会被转换为16进制数据发出,数据需要额外处理,但速度快

系统函数获取机器运行时间
millis();

 另外我们还可以先把端口设置成一个变量,下次可以通过变量来配置IO口,这样可以增加程序的可读性。

比如:

int LED = 2;//
pinMode(LED,OUTPUT);

1.2 中断

简单来说,当触发中断,就会执行中断的函数,而这个中断的触发方式就有低电平触发、高电平触发等等,一般来常用来检测按键、或者一些触发信号。

怎么理解呢,就是说中断就是无论你主程序跑到哪里,一旦检测到中断信号,它就得从主程序中跳出来,先执行你的中断函数,完了之后再回到之前主程序跳出来的位置继续执行主程序。

外部中断:

不同的开发板触发中断的引脚都不一样,一般至少有两个外部中断,需要根据自己开发板来做设置。

void attachInterrupt (uint8_t interruptNum, void(*)(void)userFunc, int mode);/*设置中断

指定中断函数. 外部中断有0和1两种, 一般对应2号和3号数字引脚.

参数:

interrupt 中断类型, 0或1
fun 对应函数
mode 触发方式. 有以下几种:
LOW 低电平触发中断
CHANGE 变化时触发中断
RISING 低电平变为高电平触发中断
FALLING 高电平变为低电平触发中断

*/

例子:

注解:
在中断函数中 delay 函数不能使用, millis 始终返回进入中断前的值. 读串口数据的话, 可能会丢失. 中断函数中使用的变量需要定义为 volatile 类型.
下面的例子如果通过外部引脚触发中断函数, 然后控制LED的闪烁.

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

void loop()
{
  digitalWrite(pin, state);
}

void blink()
{
  state = !state;
}

定时中断:

定时中断涉及的内容就比较多也比较复杂,后面单开来做笔记,有两种定时器,一种是硬件定时器,一种是软件定时器。

硬件定时器:简而言之通过自带的时钟信号计时,精确度较高,不受代码干扰,用于高精度和实时性的定时任务,例如 PWM 输出、捕获输入脉冲等。

软件定时器:软件定时器简单来说(个人理解)就是通过软件来识别时间,类似与跑这段代码大致需要1ms,程序估会算各个代码的时间来确定当前的时间间隔。精度相对没那么高,对于高速型号等会产生不少误差。

,简单来概述下硬件定时器的使用步骤:详细看这里https://docs.geeksman.com/esp32/Arduino/16.esp32-arduino-timer.html#_1-%E7%A1%AC%E4%BB%B6%E5%AE%9A%E6%97%B6%E5%99%A8

  1. 初始化定时器:使用 timerBegin() 函数初始化所需的硬件定时器;
  2. 注册中断处理函数:使用 timerAttachInterrupt() 函数将中断处理函数与定时器关联起来,简而言之就是触发定时中断之后你要他做什么;
  3. 设置定时器模式:使用 timerAlarmWrite(),设置触发一次,还是周期性触发;
  4. 启动定时器:使用 timerAlarmEnable() 函数启动定时器,使其开始计数。

实例:

#define LED   2
#define LED_ONCE  4

hw_timer_t *timer = NULL;
hw_timer_t *timer_once=NULL;


// 定时器中断处理函数
void timer_interrupt(){
  digitalWrite(LED, !digitalRead(LED));
}

void timer_once_interrupt() {
  digitalWrite(LED_ONCE, !digitalRead(LED_ONCE));
}
 
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(LED_ONCE, OUTPUT);

  // 初始化定时器
  timer = timerBegin(0,80,true);
  timer_once = timerBegin(1, 80, true);

  // 配置定时器
  timerAttachInterrupt(timer,timer_interrupt,true);
  timerAttachInterrupt(timer_once, timer_once_interrupt, true);

  // 定时模式,单位us,只触发一次
  timerAlarmWrite(timer,1000000,true); 
  timerAlarmWrite(timer_once, 3000000, false);
  // 启动定时器
  timerAlarmEnable(timer); 
  timerAlarmEnable(timer_once);
 
}
 
void loop() {
}

1.2 一些小技巧

在编程过程中可以通过串口将某些信息打印出来,由于ESP32开发板的内部串口与调试烧录串口是复用的,可以直接调用。比如:

#define POT 26

 
// 初始化电位计输入信号
int pot_value;

 
void setup() {
    // 设置串口通信波特率 9600
    Serial.begin(9600);
    pinMode(POT, INPUT);
}
 
void loop() {
    // 读取电位计模拟输入值
    pot_value = analogRead(POT);
    // 打印模拟值在串口屏上
    Serial.println(pot_value);
    delay(50);
}

1.3 PWM

这里单开一章来说明下。PWM主要属性无非就是:频率,占空比。这两个核心参数,对于一些精度要求高的还有一个关键属性就是分辨率。分辨率简而言之就是,将方波分为多少份,如8位,就是2^8=256,就是你调节占空比的时候最小可以调节1/256格,100%占空比就是256格。

初始函数如下,下面的channel是指PWM的通道,不是指具体的IO脚,譬如ESP32内部有16个通道的PWM,它可以输出16个PWM。分为高低速两组,高速通道(0 ~ 7)由 80MHz 时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。

实现步骤如下:

使用 ledcSetup;//(通道,频率,分辨率) 函数建立 LEDC 通道,设置频率、分辨率
通过 ledcAttachPin(Pin脚号); //将 GPIO 口与 LEDC 通道关联;
通过 ledcWrite(通道,占空比); //设置占空比,注意这里的占空比不是0~100%,是根据你的分辨率来换算,譬如分辨率是8也就是256格,想要10%,占空比这里写入25

相关的函数说明如下:

可以在<esp32_hal_led.h>中找到。

// 设置 LEDC 通道对应的频率和计数位数(占空比分辨率),返回最终频率
// 分辨率的意思就是把一个周期分成 2 的 resolution_bits 份。
uint32_t    ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);

// 指定通道输出一定占空比波形
void        ledcWrite(uint8_t channel, uint32_t duty);

// 类似于 arduino 的 tone ,当外接无源蜂鸣器的时候可以发出某个声音(根据频率不同而不同)
uint32_t    ledcWriteTone(uint8_t channel, uint32_t freq);

//  该方法是上面方法的进一步封装,可以直接输出指定调式和音阶声音的信号
uint32_t    ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);

// 返回指定通道占空比的值
uint32_t    ledcRead(uint8_t channel);

// 返回指定通道当前频率(如果当前占空比为0 则该方法返回0)
uint32_t    ledcReadFreq(uint8_t channel);

// 将 LEDC 通道绑定到指定 IO 口上以实现输出
void        ledcAttachPin(uint8_t pin, uint8_t channel);

// 解除 IO 口的 LEDC 功能
void        ledcDetachPin(uint8_t pin);
#define FREQ        2000    // 频率
#define CHANNEL     0       // 通道
#define RESOLUTION  8       // 分辨率
#define LED         12      // LED 引脚


void setup()
{
  ledcSetup(CHANNEL, FREQ, RESOLUTION); // 设置通道
  ledcAttachPin(LED, CHANNEL);          // 将通道与对应的引脚连接
  
}

void loop()
{
  // 逐渐变亮
  for (int i=0;i<pow(2, RESOLUTION); i++)
  {
    ledcWrite(CHANNEL, i); // 输出PWM
    delay(5);
  }

  // 逐渐变暗
  for (int i=pow(2, RESOLUTION)-1;i>=0;i--)
  {
    ledcWrite(CHANNEL, i); // 输出PWM
    delay(5);
  }
}


//这里通过改变占空比的值实现的呼吸灯效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值