25/1/12 嵌入式笔记 学习esp32
了解了一下位选线和段选线的知识:
位选线:
作用:用于选择数码管的某一位,例如4位数码管的第1位,第2位)
通过控制位选线的电平(高低电平),决定当前哪一位数码管处于激活状态。
示例:
假设有4位数码管,位选线分别位D1,D2,D3,D4.
如果要显示第2位,设置D2 = LOW或D2 = HIGH,其他位选线设置位相反电平。
段选线:
作用:用于控制数码管上某一位显示的具体数字或字符。
数码管的每一段(如a,b,c,d,e,f,g,dp)对应一个段选线。
对于共阴极数码管:
将某一段的段选线设置为高电平HIHG,该段点亮,设置位LOW,熄灭
对于共阳则相反。
示例,要显示数字7,需要点亮段a,b,c.
对于共阴极数码管,设置a = HIGH,b=HIGH.c = HIGH,其他位LOW。
意思就是位选线是切换数码管的位,段就是一位数码管的那一小段。
为什么分阴阳极?
1.电路设计灵活,不同的电路设计可能需要不同的电平逻辑。
2.电源和接地方便性,在某些电路中,可能更容易提供高电平或低电平。
3.驱动芯片的兼容性,不同的驱动芯片可能支持不同的电平逻辑。
动态扫描:
数码管上的数字显示都是通过动态扫描完成的。
// 定义位选线引脚
int seg_1 = 5;
int seg_2 = 18;
int seg_3 = 19;
int seg_4 = 21;
// 定义位选线数组
int seg_array[4] = {seg_1, seg_2, seg_3, seg_4};
// 定义段选线引脚
int a = 32;
int b = 25;
int c = 27;
int d = 12;
int e = 13;
int f = 33;
int g = 26;
int dp = 14;
// 定义段选线数组
int led_array[8] = {a, b, c, d, e, f, g, dp};
// 定义数字显示逻辑的二维数组(共阴极数码管)
int number_array[10][8] = {
{1, 1, 1, 1, 1, 1, 0, 0}, // 0
{0, 1, 1, 0, 0, 0, 0, 0}, // 1
{1, 1, 0, 1, 1, 0, 1, 0}, // 2
{1, 1, 1, 1, 0, 0, 1, 0}, // 3
{0, 1, 1, 0, 0, 1, 1, 0}, // 4
{1, 0, 1, 1, 0, 1, 1, 0}, // 5
{1, 0, 1, 1, 1, 1, 1, 0}, // 6
{1, 1, 1, 0, 0, 0, 0, 0}, // 7
{1, 1, 1, 1, 1, 1, 1, 0}, // 8
{1, 1, 1, 1, 0, 1, 1, 0} // 9
};
// 清屏函数
void clear() {
// 关闭所有位选线
for (int i = 0; i < 4; i++) {
digitalWrite(seg_array[i], HIGH);
}
// 关闭所有段选线
for (int i = 0; i < 8; i++) {
digitalWrite(led_array[i], LOW);
}
}
// 显示数字的函数
void display_number(int order, int number) {
// 清屏
clear();
// 将对应位选线的电平拉低
digitalWrite(seg_array[order], LOW);
// 显示数字
for (int i = 0; i < 8; i++) {
digitalWrite(led_array[i], number_array[number][i]);
}
}
// 4位数码管显示函数
void display_4_number(int number) {
// 确保数字在 0 到 9999 之间
if (number >= 0 && number < 10000) {
// 获取每一位对应的数字
int digits[4];
for (int i = 3; i >= 0; i--) {
digits[i] = number % 10;
number /= 10;
}
// 显示4位数
for (int i = 0; i < 4; i++) {
display_number(i, digits[i]);
delay(5); // 短暂延时,避免闪烁
}
}
}
void setup() {
// 设置所有位选线引脚为输出模式,并初始化为高电平(关闭)
for (int i = 0; i < 4; i++) {
pinMode(seg_array[i], OUTPUT);
digitalWrite(seg_array[i], HIGH);
}
// 设置所有段选线引脚为输出模式,并初始化为低电平(关闭)
for (int i = 0; i < 8; i++) {
pinMode(led_array[i], OUTPUT);
digitalWrite(led_array[i], LOW);
}
}
void loop() {
// 显示数字 34
display_4_number(34);
}
按键实验
//定义开关引脚
int led_pin = 2;
int button_pin = 14;
//记录led状态是否更改过的值
bool status = false;
int led_logic = 0; // LED 的当前状态
void setup(){
//配置引脚模式
pinMode(led_pin,OUTPUT);
pinMode(button_pin,INPUT_PULLDOWN);
}
void loop(){
//按键消抖
//如果当前按钮与上次不同,说明按钮发生了变化
if(digitalRead(button_pin)){
//睡眠10ms,如果依然是高电平,说明是按下并非抖动
delay(500);
if(digitalRead(button_pin)&& !status){
led_logic = !led_logic;
digitalWrite(led_pin,led_logic);
//修改status
status = !status;
}else if(digitalRead(button_pin)){
status = false;
}
}
}
INPUT_PULLDOWN表示启用内部下拉电阻。
status:用于记录按钮是否已经触发过状态切换,避免按钮按下时多次出发LED状态的切换。
按钮消抖逻辑,状态切换:status作用时确保每次按钮按下只触发一次状态切换。切换LED状态后,将status设置位true,避免重复触发。
宏定义与变量定义的区别:
PWM呼吸灯
占空比:一个周期内高电平出现时间占总的比例
频率:1秒内信号从高电平到低电平再回到高电平的次数,一秒钟PWM的周期次数
PWM主要通过输出不同频率,占空比的方波,实现固定频率或平均电压输出,,频率固定,改变占空比可改变输出电压。
analogWrite函数:在指定的引脚上输出一个PWM信号,通过改变PWM信号的占空比,控制输出电平的平均值,从而实现对LED亮度、电机速度等的调整。
函数实现呼吸灯
#define LED_PIN 12
void setup(){
//配置GPIO输出
pinMode(LED_PIN,OUTPUT);
}
void loop(){
//实现渐亮效果
for(int i=0;i<256;i++){
analogWrite(LED_PIN,i);
delay(10);
}
//实现渐灭效果
for(int i=255;i>=0;i--){
analogWrite(LED_PIN,i);
delay(10);
}
}
普通实现
#define FREQ 2000 // PWM 频率
#define CHANNEL 0 // PWM 通道
#define RESOLUTION 8 // PWM 分辨率(8 位 = 0~255)
#define LED 12 // LED 引脚
void setup() {
// 配置 LEDC 通道
ledcSetup(CHANNEL, FREQ, RESOLUTION);
// 将 LEDC 通道绑定到指定引脚
ledcAttachPin(LED, CHANNEL);
}
void loop() {
// 实现渐亮效果
for (int i = 0; i < (1 << RESOLUTION); i++) {
ledcWrite(CHANNEL, i); // 设置 PWM 占空比
delay(10); // 延迟 10ms
}
// 实现渐灭效果
for (int i = (1 << RESOLUTION) - 1; i >= 0; i--) {
ledcWrite(CHANNEL, i); // 设置 PWM 占空比
delay(10); // 延迟 10ms
}
}
ADC模数转换器
串口监视器是 Arduino IDE 提供的一个工具,用于通过串口通信与开发板(如 Arduino、ESP32 等)进行数据交互。它的主要作用是:1调试和监控程序运行,2.发送数据到开发板,3.实时查看传感器数据。4.交互式控制。
串口通信(Serial Communication)是一种通过串行接口逐位传输数据的通信方式。与并行通信(同时传输多个位)不同,串口通信一次只传输一个位,适合长距离传输和减少硬件复杂性。
波特率是串口通信中数据传输速率的度量,表示每秒传输的符号数(Symbols per second)。每个符号可以代表一个或多个位。
#define POT 26 // 定义电位计连接的引脚
int pot_value; // 用于存储电位计的模拟输入值
void setup() {
// 设置串口通信波特率
Serial.begin(9600);
// 设置引脚为输入模式(可选)
pinMode(POT, INPUT);
}
void loop() {
// 读取电位计的模拟输入值
pot_value = analogRead(POT);
// 打印模拟输入值到串口监视器
Serial.println(pot_value);
// 延迟 50 毫秒
delay(50);
}