【ESP32学习-4】外设

  1. 背景

    编程指南基于4.4.2版本
    代码基于4.4.1版本

  2. 外设的驱动逻辑

    外设包括:定时器、I2C、SPI、UART、RTC、ADC、DAC等等。由于每块芯片的外设都有所不同(地址、功能等),所以驱动代码天然需要进行功能分层。一方面保证驱动的逻辑性,一方面可以将代码功能进行解耦(如下表目录所示,新增芯片时只需新增LowLevel层的文件)。
    分层如下:

    1. Low Level (LL) Layer
    2. Hardware Abstraction Layer (HAL)
    3. Driver Layers
    分层功能目录
    Low Level与硬件打交道的最底层,向HAL层提供服务component\hal\esp32\include\hal
    HAL基于ll层,将ll层进行逻辑封装,向Driver层提供服务component\hal
    Driver向上层应用提供服务componnet\driver

    举例:
    driver层timer.c 提供定时器的操作接口:timer_init
    timer_init会调用hal层的定时器接口:timer_hal_reset_periph
    timer_hal_reset_periph会调用ll层的接口:timer_ll_intr_disable

  3. PCNT-- pulse counter 统计上升和下降沿的个数

    esp32包含多个 pcnt unit,每个pcnt unit包含一个16bit计数器两个channel,每个channel接入两个信号:ctrl、sig
    在这里插入图片描述

    学习中对于ctrl信号的模式(keep、inverse、hold)比较困惑,下边结合官方示例说明:

    • 官方示例1
      examples\peripherals\pcnt\pulse_count_event\main\pcnt_event_example_main.c
      该例子通过IO18产生PWM波形(1HZ),IO4作为PCNT的sig输入与IO18短接,IO5作为PCNT的ctrl输入接地

      	// sig信号的计数模式
          .pos_mode = PCNT_COUNT_INC,   // 上升沿增加计数器
          .neg_mode = PCNT_COUNT_DIS,   // 下降沿不操作计数器
      
      	// ctrl信号的控制模式
          .lctrl_mode = PCNT_MODE_REVERSE, // 反转模式:当ctrl为低电平,pos_mode配置为增加计数时,那么上升沿到来时减少计数器
          								 //			 当ctrl为低电平,pos_mode配置为减少计数时,那么上升沿到来时增加计数器		
          								 //			 当ctrl为低电平,neg_mode配置为增加计数时,那么上升沿到来时减少计数器		
          								 //			 当ctrl为低电平,neg_mode配置为减少计数时,那么上升沿到来时增加计数器	
          .hctrl_mode = PCNT_MODE_KEEP,    // 保持模式:当ctrl为高电平时,保持原有的上升下降计数模式
      

      综上,由于IO5接地,所以ctrl的信号控制模式固定为翻转模式。所以每隔1s读到计数器值在递减,达到边界值后,计数器恢复0后继续减1递减

      // 样例输出
      Current counter value :-1
      Current counter value :-2
      Current counter value :-3
      Current counter value :-4
      Event PCNT unit[0]; cnt: -5
      THRES0 EVT
      Current counter value :-5
      Current counter value :-6
      Current counter value :-7
      Current counter value :-8
      Current counter value :-9
      Event PCNT unit[0]; cnt: 0
      L_LIM EVT
      ZERO EVT
      Current counter value :0
      Current counter value :-1
      
    • 官方示例2
      examples\peripherals\pcnt\rotary_encoder\main\rotary_encoder_example_main.c
      该用例使用EC11(旋转编码器)作为PCNT的输入 (旋转编码器原理),将旋钮的物理选转转化为正负数。PCNT两个通道的关键配置罗列如下

          // Configure channel 0
          pcnt_config_t dev_config1 = {
              .pulse_gpio_num = GPIO14,						// channel 0/1 输入颠倒
              .ctrl_gpio_num = GPIO15,
              .channel = PCNT_CHANNEL_0,						// channel 0/1 
              .pos_mode = PCNT_COUNT_DEC,						// channel 0/1 配置相反
              .neg_mode = PCNT_COUNT_INC,						// channel 0/1 配置相反
              .lctrl_mode = PCNT_MODE_REVERSE,
              .hctrl_mode = PCNT_MODE_KEEP,
          };
          pcnt_config_t dev_config2 = {
              .pulse_gpio_num = GPIO14,
              .ctrl_gpio_num = GPIO15,
              .channel = PCNT_CHANNEL_1,
              .pos_mode = PCNT_COUNT_INC,
              .neg_mode = PCNT_COUNT_DEC,
              .lctrl_mode = PCNT_MODE_REVERSE,
              .hctrl_mode = PCNT_MODE_KEEP,
          };
      

      当顺时针旋转EC11时,IO14领先IO15相位90度(参见后边的棘轮定位基准点图,实际应该小于90°),波形如下

      在这里插入图片描述
      t0时刻:channel0配置生效,IO14作为sig信号是上升沿(PCNT_COUNT_DEC),此时IO15作为ctrl信号为低电平(PCNT_MODE_REVERSE),因此此时增加计数器

      t1时刻:channel1配置生效,IO15作为sig信号是上升沿(PCNT_COUNT_INC),测试IO14作为Ctrl信号为高电平(PCNT_MODE_KEEP),因此此时增加计数器

      t2时刻:channel0配置生效,IO14作为sig信号是下降沿(PCNT_COUNT_INC),此时IO15作为ctrl信号为高电平(PCNT_MODE_KEEP),因此此时增加计数器

      t3时刻:channel1配置生效,IO15作为sig信号为下降沿(PCNT_COUNT_DEC),此时IO15作为ctrl信号为低电平(PCNT_MODE_REVERSE),因此此时增加计数器

      逆时针旋转EC11时,每次上升或下降沿都是递减计数器

      疑问来了 为何是以4为单位进行计数。示例打印如下

      I (181323) example: Encoder value: 0
      I (182323) example: Encoder value: 0
      I (183323) example: Encoder value: -12
      I (184323) example: Encoder value: -18
      I (185323) example: Encoder value: -24
      I (188323) example: Encoder value: 4
      I (189323) example: Encoder value: 8

      查看ec11某款产品参数:定位数(旋钮棘轮个数)为脉冲数(脉冲个数/360°)的两倍,因此计数器的最小增长单位应该是2才对,这点理解不了。(可能样例使用的是定位数=脉冲数的选转编码器)
      在这里插入图片描述
      此外说明书中也没有明确指出定位基准点(棘轮卡位处)与B signal上升下降沿完全对齐。
      在这里插入图片描述

  4. MCPWM - motor control pulse width module 电机脉宽调制
    该外设学习使用的示例1为有刷电机控制: examples\peripherals\mcpwm\mcpwm_brushed_dc_control
    1)需要对PID(proportional integral differential 百分比 积分 微分)控制模式有基本的了解 此外两种数字处理方式(增量、位置)的推导也很简单
    该示例通过将马达与旋转编码器(EC11)相连,旋转编码器与PCNT相连,来感知马达的转速;通过PID的控制模式,利用MCPWM将马达调整至期望转速。
    在这里插入图片描述

该外设学习使用的示例2为无刷电机控制: examples\peripherals\mcpwm\mcpwm_bldc_hall_control
需掌握:
1 无刷电机(brushless direct current motor)的基本原理
2 无刷电机与霍尔传感器的配合
3 死区的概念 避免桥驱动的过程中出现上桥和下桥同时打开的情况

PS:航模中使用的无刷电机有3根接线,并无3根霍尔传感器的输出线是为什么?
利用反电动势原理(楞次定律)无刷电机的转子转动时,会在定子的线圈中产生反电动势,电调通过检测反电动势来识别定子的位置,从而控制定子线圈的通电顺序。

Q&A:

  • 全局变量 TIMERG0 的定义未找到

    \esp-idf-v4.4.1\components\soc\esp32\include\soc\timer_group_struct.htimer_group_struct.h

    extern timg_dev_t TIMERG0;
    extern timg_dev_t TIMERG1;
    

    根据该变量的使用,可以通过它控制定时器。
    其实该变量的定义在ld文件 esp32.peripherals.ld 中:
    在这里插入图片描述
    属于外设地址范围
    在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值