25/1/13 嵌入式笔记 继续学习Esp32

news2025/1/15 0:05:14

PWM(Pulse Width Modulation,脉宽调制) 是一种通过快速切换高低电平来模拟中间电压值的技术。它广泛应用于控制 LED 亮度、电机速度、音频生成等场景。

analogWrite函数:用于在微控制器(如 Arduino)上生成模拟信号

使用analogWrite改变亮度。

#define POT 26
#define LED 13
//初始化电位计输入信号
int pot_value;
int led_value;

void setup(){
  pinMode(POT,INPUT);
  pinMode(POT,INPUT);  
}
void loop(){
  //读取电位计模拟输入值
  pot_value=analogRead(POT);
  //吧电位计模拟输入值转换为LED模拟输出
  led_value = pot_value/16;
  analogWrite(LED,led_value);
  delay(50);
}

使用LEDC外设

#define POT 26
#define LED 13
#define CHANNEL 0
#define RESOLUTION 12
#define FREQ 1000

//初始化电位计输入信号
int pot_value;//用于存储电位计读取的模拟值
int led_value;

void setup(){ 
  //设置ADC分辨率
  analogReadResolution(12);
  //配置输入衰减
  analogSetAttenuation(ADC_11db);
  //建立LEDC通道,配置LEDC分辨率
  ledcSetup(CHANNEL,1000,12);
  //关联GPIO与LEDC通道
  ledcAttachPin(LED,CHANNEL);
}
void loop(){
  //读取电位计模拟输入值
  pot_value=analogRead(POT);
  //输出PWM
  ledcWrite(CHANNEL,pot_value);
  delay(50);
}

I2C控制LED1602

设计理念是:信号线尽量少并且速率要尽量高,信号线少,可以减少引脚占用,这对早期的芯片(引脚很少)的很重要。

标准的I2C需要两根信号线:

SCL:时钟线,时钟都是有master提供的

SDA:双向数据线,发数据或者收数据(收发不能同时)

简单来说,只需要2根线,就可以对多台设备传输大量数据,减少单片机上IO口的占用。

TIP:需要将LiquidCrystal_I2C.h和.cpp文件放在一个目录下

库的使用:

显示文字在液晶屏上。

#include "LiquidCrystal_I2C.h"

//构造LCD对象,设置地址,列数,行数
LiquidCrystal_I2C lcd(0x27,16,2);

void setup(){ 
  //初始化LCD对象
  lcd.init();

  //打印内容
  lcd.backlight();
  lcd.print("Hello,world!");
}
void loop(){
  
}

通过串口显示

Serial.available()//判断串口缓冲区有没有数据,若大于0就读取了数据

Serial.read()//从串口读取一个字节的数据,并将其写入 LCD 显示屏。这通常用于将通过串口接收到的字符显示在 LCD 上。

Adafruit_SSD1306的使用

上述知识均来自小破站的

18. SPI 控制 OLED 液晶屏_哔哩哔哩_bilibili这里面。

使用步骤:

1.初始化OLED,调用构造函数,调用begin方法

2.初始化完成后,调用绘制类函数,当然可以设置颜色,字体

3.绘制完毕,调用显示类函数display。

#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define WIDTH 128
#define HEIGH 64
#define OLED_MOSI 13 
#define OLED_SCK 18
#define OLED_DC 2 
#define OLED_CS 4
#define OLED_RESET 15


Adafruit_SSD1306 oled(WIDTH,HIGH,OLED_MOSI,OLED_SCK,
                      OLED_DC,OLED_RESET,OLED_CS);

//初始化进度
int progress=0;

void setup() {
  //OLED初始化
  oled.begin();
  //清除显示
  oled.clearDisplay();
  //绘制水平线
  oled.drawFastHLine(32,5,48,SSD1306_WHITE);
  //绘制斜线
  oled.drawLine(32,5,48,30,SSD1306_WHITE);
  //绘制矩形
  oled.drawRect(5,5,10,25,SSD1306_WHITE);
  //绘制实心矩阵
  oled.fillRect(75,5,10,30,SSD1306_WHITE);
  //设置光标位置
  oled.setCursor(5,50);
  //设置文本颜色
  oled.setTextColor(SSD1306_WHITE);
  //显示文字
  oled.println("Hello,world!");
  //显示内容
  oled.display();
}

void loop() {
  //清楚显示
  oled.clearDisplay();
  //设置光标位置
  oled.setCursor(25,40);
  //显示文字
  oled.println("Progress");
  //显示进度条边框
  oled.drawRoundRect(0,10,128,20,5,SSD1306_WHITE);
  //显示进度
  oled.fillRoundRect(5,15,progress,10,2,SSD1306_WHITE);
  //进度递增
if (progress<118)
{
  progress++;
}
else
{
  progress=0;
}
  //显示内容
  oled.display();
  //延时
  delay(50);
}

U8G2库控制OLED

平台支持性好,支持中文

#include <Arduino.h>
#include <U8g2lib.h>

//构造对象
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0,18,13,4,2,15);

void setup() {
  //初始化OLED对象
  u8g2.begin();
  //开启中文字符集支持
  u8g2.enableUTF8Print();
  //设置字体
  u8g2.setFont(u8g2_font_wqy12_t_chinese2);

}

void loop() {
  //清除缓存区内容
  u8g2.clearBuffer();
  //绘制内容
  u8g2.setCursor(0,15);
  u8g2.print("Hello,World!");

  u8g2.setCursor(0,40);
  u8g2.print("你好,ESP32");
  //发送缓存区内容到OLED显示
}

按键控制菜单

#include <Arduino.h>
#include <U8g2lib.h>

#define BUTTON_UP 12
#define BUTTON_DOWN 14

void display_menu();

//定义菜单列表
char *menu[4] = {"Item 1","Item 2","Item 3","Item 4"};
//构造对象
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0,18,13,4,2,15);

//初始化按键列表
unsigned int order = 0;
void setup() {
  //初始化OLED对象
  u8g2.begin();
  u8g2.setFont(u8g2_font_6x12_tr);

  //配置输出按键
  pinMode(BUTTON_UP,INPUT_PULLUP);
  pinMode(BUTTON_DOWN,INPUT_PULLUP);
}

void loop() 
{
  //判断按键是否按下,并记录位置
  if(!digitalRead(BUTTON_UP)){
    order = (order - 1 + 4)%4;
  }
  if(!digitalRead(BUTTON_DOWN)){
    order = (order + 1)%4;
  }
  display_menu(order);
  delay(80);
}
void display_menu(){
  u8g2.firstPage();
  do 
  {
    //绘制页面内容
    u8g2.drawStr(0,12,"Menu");
    u8g2.drawHLinie(0,14,128);
    for(int i=0;i<4;i++){
      if(i==index){
        u8g2.drawStr(5,(i+2)*12+2,">");
        u8g2.drawStr(20,(i+2)*12+2,menu[i]);
      }else{
      u8g2.drawStr(5,(i+2)*12+2,menu[i]);
      }
    }
  }while(u8g2.nextPage());

}
   

中断分类:

硬件中断,也称外部中断,一键中断响应外部硬件时间而发生,

软件中断:当触发软件事件时,会发生这种类型的中断。

在中断执行函数中不能用delay()函数

delay() 的工作原理
  • delay() 函数依赖于 Arduino 的 millis() 函数,后者通过定时器中断来更新时间。

  • 在 delay() 执行期间,程序会不断检查 millis() 的值,直到达到指定的延时时间。

  • 如果在 ISR 中使用 delay(),会导致以下问题:

    • 阻塞其他中断delay() 依赖于定时器中断,但在 ISR 中,定时器中断被禁用,导致 millis() 无法更新,delay() 会一直阻塞。

    • 影响系统实时性:ISR 应该尽快执行完毕,delay() 会延长 ISR 的执行时间,影响系统的响应能力。

简单来说delay是一个阻塞函数,他会暂停代码的执行,会中断积压。

定时器中断

ESP32通过定时器可以完成各种预设好的任务,ESP32定时器达到指定时间后也会产生中断,然后在回调函数内执行所需功能。

#define LED 2
#define LED_ONCE 4

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

// 定时中断函数:用于 LED 闪烁
void IRAM_ATTR timer_interrupt() {
  digitalWrite(LED, !digitalRead(LED)); // 切换 LED 状态
}

// 一次性定时中断函数:用于点亮 LED_ONCE
void IRAM_ATTR timer_once_interrupt() {
  digitalWrite(LED_ONCE, HIGH); // 点亮 LED_ONCE
}

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(LED_ONCE, OUTPUT);

  // 初始化定时器
  timer = timerBegin(0, 80, true);         // 使用定时器 0,分频系数 80,向上计数
  timer_once = timerBegin(1, 80, true);    // 使用定时器 1,分频系数 80,向上计数

  // 配置定时器中断
  timerAttachInterrupt(timer, &timer_interrupt, true);         // 绑定 timer_interrupt 到定时器 0
  timerAttachInterrupt(timer_once, &timer_once_interrupt, true); // 绑定 timer_once_interrupt 到定时器 1

  // 设置定时器周期(单位:微秒)
  timerAlarmWrite(timer, 1000000, true);         // 定时器 0 每 1 秒触发一次
  timerAlarmWrite(timer_once, 5000000, false);   // 定时器 1 在 5 秒后触发一次(仅一次)

  // 启用定时器报警
  timerAlarmEnable(timer);
  timerAlarmEnable(timer_once);
}

void loop() {
  // 主循环无需操作
}

软件定时器

#include <Ticker.h>
#define LED 2
#define LED_ONCE 4

//定义定时器对象
Ticker timer;
Ticker timer_once;

//切换指定引脚的电平状态
void toggle(int pin){
  digitalWrite(pin,!digitalRead(pin));
}


void setup() {
  pinMode(LED, OUTPUT);
  pinMode(LED_ONCE, OUTPUT);

  //配置定时器
  timer.attach(0.5,toggle,LED);
  timer_once.once(3,toggle,toggle,LED_ONCE);
}

void loop() {
  // 主循环无需操作
}

舵机转动

CHANNEL 是 ESP32 的 LEDC(LED PWM 控制器) 通道编号。ESP32 的 LEDC 模块提供了多个独立的 PWM 通道,可以用来生成 PWM 信号,控制设备如 LED 亮度、舵机角度等。

  • 通道 0 用于生成 PWM 信号,控制连接到 SERVO 引脚(GPIO 13)的设备(如舵机)。

#define FREQ 50
#define CHANNEL 0
#define RESOLUTION 8
#define SERVO 13
 
int calculatePWM(int degree){
  int min_width=0.5/20*pow(2,RESOLUTION);
  int max_width=2.5/20*pow(2,RESOLUTION);

  return (max_width-min_width)*degree/180+min_width;

}

void setup(){
  //建立LEDC通道
  ledcSetup(CHANNEL,FREQ,RESOLUTION);
  //关联GPIO口与LEDC通道
  ledcAttachPin(SERVO,CHANNEL);
}

void loop(){
  for (int i=0;i<=180;i+=10){
    //输出PWM,设置占空比
  ledcWrite(CHANNEL,calculatePWM(i));
  delay(500);
  }
}

ok!明天见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【端云一体化】云函数的使用

前言 为丰富HarmonyOS对云端开发的支持、实现端云联动&#xff0c;DevEco Studio以Cloud Foundation Kit&#xff08;云开发服务&#xff09;为底座、在传统的“端开发”基础上新增“云开发”能力&#xff0c;开发者在创建工程时选择合适的云开发工程模板&#xff0c;即可在De…

行业案例:高德服务单元化方案和架构实践

目录 为什么要做单元化 高德单元化的特点 高德单元化实践 服务单元化架构 就近接入实现方案 路由表设计 路由计算 服务端数据驱动的单元化场景 总结 系列阅读 为什么要做单元化 单机房资源瓶颈 随着业务体量和服务用户群体的增长,单机房或同城双机房无法支持服…

基于单片机的语音控制玩具汽车的设计

语音控制小汽车选用了两个单片机、一个语音识别芯片、两个无线收发模块、一个电机驱动模块、两个电机、一个音频解码模块。语音控制端选用了一个语音识别芯片&#xff0c;实现了将声音信号转换成数字信号&#xff0c;再将数据传输给单片机的功能。小车端选用了单片机来控制电机…

解锁“搭子小程序”开发新机遇,助力企业数字化转型

搭子作为一种新型的社交方式&#xff0c;逐渐进入到了年轻人的生活中&#xff0c;在日常旅游、学习、逛街等&#xff0c;年轻人都可以找到志同道合的“搭子”&#xff0c;提高生活的幸福指数。 随着搭子市场的发展&#xff0c;通过互联网寻找搭子已经成为了年轻人的必备方式。…

Spring Boot 2 学习全攻略

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今快速发展的 Java 后端开发领域&#xff0c;Spring Boot 2 已然成为一股不可忽视的强大力量。它简化了 Spring 应用的初始搭建以及开发过程&#xff0c;让开发者能够更加专注于业务逻辑的实现&am…

31_搭建Redis分片集群

Redis的主从复制模式和哨兵模式可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:海量数据存储问题、高并发写的问题。由于数据量过大,单个master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Red…

IMX6U Qt 开发环境

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、交叉编译 1. 安装通用 ARM 交叉编译工具链 2. 安装 Poky 交叉编译工具链 二、编译出厂源码 1. U-boot 2. 内核和模块 3. 编译出厂 Qt GUI 综合 Demo 前言…

数据结构与算法之链表: LeetCode 92. 反转链表 II (Ts版)

反转链表 II https://leetcode.cn/problems/reverse-linked-list-ii/description/ 描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 示例 1 输入&…

【Uniapp-Vue3】@import导入css样式及scss变量用法与static目录

一、import导入css样式 在项目文件中创建一个common文件夹&#xff0c;下面创建一个css文件夹&#xff0c;里面放上style.css文件&#xff0c;编写的是公共样式&#xff0c;我们现在要在App.vue中引入该样式。 在App.vue中引入该样式&#xff0c;这样就会使样式全局生效&#…

MySQL中的四种表联结

目录 1、联结、关系表 &#xff08;1&#xff09;关系表 &#xff08;2&#xff09;为什么使用联结 2、如何创建联结 &#xff08;1&#xff09;笛卡尔积&#xff08;叉联结&#xff09;--用逗号分隔 &#xff08;2&#xff09;where子句的重要性 &#xff08;3&#xff…

DVWA靶场CSRF漏洞通关教程及源码审计

目录标题 CSRFlow源码审计 medium源码审计 high源码审计 impossible源码审计 CSRF low 先修改密码 看到地址栏 复制在另一个网页打开 成功登录 源码审计 没有任何过滤措施&#xff0c;很危险&#xff0c;并且采用了不安全的md5加密 <?phpif( isset( $_GET[ Change ] )…

JVM之垃圾回收器G1概述的详细解析

G1(并发) G1 特点 G1&#xff08;Garbage-First&#xff09;是一款面向服务端应用的垃圾收集器&#xff0c;应用于新生代和老年代、采用标记-整理算法、软实时、低延迟、可设定目标&#xff08;最大 STW 停顿时间&#xff09;的垃圾回收器&#xff0c;用于代替 CMS&#xff0…

宝塔面板 申请证书后 仍然提示不安全

证书显示有效&#xff0c;但是网站显示不安全 导致的原因是引入静态文件使用的是HTTP&#xff0c;查看方法为F12打开console控制台 可以看到静态文件全部都是HTTP 网站采用wordpress搭建&#xff0c;基于问题解决&#xff0c;其他方式搭建也是一样&#xff0c;处理掉所有的H…

【1】Word:邀请函

目录 题目 文字解析 流程 题目 文字解析 考生文件夹☞Word.docx☞一定要用ms打开&#xff0c;wps打开作答无效☞作答完毕&#xff0c;F12或者手动另存为&#xff08;考生文件夹&#xff1a;路径文件名&#xff09; 注意&#xff1a;一定要检查&#xff0c;很有可能你前面步…

Docker安装和卸载(centos)

Docker安装和卸载 一&#xff0c;已安装Docker&#xff0c;卸载Docker 1.方法一 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine​ 如果出现以下提示就证明没卸载…

JVM:ZGC详解(染色指针,内存管理,算法流程,分代ZGC)

1&#xff0c;ZGC&#xff08;JDK21之前&#xff09; ZGC 的核心是一个并发垃圾收集器&#xff0c;所有繁重的工作都在Java 线程继续执行的同时完成。这极大地降低了垃圾收集对应用程序响应时间的影响。 ZGC为了支持太字节&#xff08;TB&#xff09;级内存&#xff0c;设计了基…

ASP.NET Core - 日志记录系统(二)

ASP.NET Core - 日志记录系统&#xff08;二&#xff09; 2.4 日志提供程序2.4.1 内置日志提供程序2.4.2 源码解析 本篇接着上一篇 ASP.NET Core - 日志记录系统(一) 往下讲&#xff0c;所以目录不是从 1 开始的。 2.4 日志提供程序 2.4.1 内置日志提供程序 ASP.NET Core 包括…

无源器件-电容

电容器件的参数 基本概念由中学大学物理或电路分析内容获得&#xff0c;此处不做过多分析。 电容的产量占全球电子元器件产品的40%以上。 单位&#xff1a;法拉 F&#xff1b;1F10^6uF&#xff1b;电路中常见的104电容就是10*10^4pF100nF0.1uF C为电容&#xff0c;Rp为绝缘电…

云平台一键部署【Video-Background-Removal】视频换背景,无任何限制,随意换

Video-Background-Removal 是一款革命性的视频背景替换工具&#xff0c;旨在让用户轻松实现视频背景的快速更换。无论你是专业创作者还是普通用户&#xff0c;这款软件都能让你在几秒钟内改变背景&#xff0c;完全消除限制&#xff0c;随心所欲&#xff0c;随时随地想换就换&am…

HCIP笔记1--IP路由基础回顾、BFD单臂回声、OSPF基础

1. 路由基础回顾 概念 AS(Aotonomous System): 自治系统&#xff0c;由同一机构管理的路由器集合。LAN(Local Area Network): 局域网&#xff0c;用户所使用的网络WAN(Wideless Area Network): 广域网&#xff0c;运营商网络广播域&#xff1a;一个广播帧能在网络中到达的所有…