You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在nRF52840-DK上配置HM01B0图像传感器并读取帧?

HM01B0与nRF52840-DK裸机图像捕获解决方案

核心问题分析

你当前的GPIO轮询方案无法工作,核心原因是36MHz的PCLK频率远超GPIO软件轮询的响应能力,导致无法同步采样到D0引脚的有效数据,所以一直读到0x00。结合你已实现I2C寄存器读写、逻辑分析仪能看到D0数据的前提,需要通过传感器寄存器配置+硬件外设同步采样来解决。


一、先完成HM01B0的1位模式寄存器配置

必须通过I2C写入寄存器,确保传感器工作在1位数据输出模式:

  • 找到数据接口配置寄存器(参考HM01B0 datasheet,例如地址0x0100),写入对应值启用1位输出(禁用D1-D3)
  • 确认PCLK频率配置为36MHz,帧率30FPS,同时匹配VSYNC/HSYNC的极性(高/低电平有效)
  • 示例代码(需根据实际寄存器地址调整):
void hm01b0_set_1bit_mode(void) {
    // 假设0x24是传感器I2C地址,0x0100是接口配置寄存器
    i2c_write_reg(0x24, 0x0100, 0x00); // 配置为1位输出模式
    // 配置PCLK为36MHz(寄存器地址和值需查官方手册)
    i2c_write_reg(0x24, 0x0102, 0x01);
}

二、nRF52840硬件采样方案(二选一)

方案1:SPIM从机模式(推荐,适配SPI时序)

将HM01B0作为SPIM主机,nRF52840作为从机,利用硬件同步采样:

  • 引脚映射:
    • HM01B0 PCLK → nRF52840 SPIM SCK
    • HM01B0 D0 → nRF52840 SPIM MOSI
    • VSYNC/HSYNC保留为GPIO,用中断标记帧/行起始
  • 配置要点:
    1. SPIM模式设为NRF_SPIM_MODE_0(上升沿采样,匹配PCLK时序)
    2. 启用DMA传输,直接将数据写入帧缓冲区,避免CPU干预
    3. 用VSYNC中断触发帧捕获,HSYNC中断切换行缓冲区

SPIM从机配置代码示例

#define SPIM_INSTANCE 0
static nrf_drv_spim_t m_spim = NRF_DRV_SPIM_INSTANCE(SPIM_INSTANCE);
static volatile bool m_rx_ready = false;

// SPIM事件回调
void spim_event_handler(nrf_drv_spim_evt_t const* p_event, void* p_context) {
    if (p_event->type == NRF_DRV_SPIM_EVT_RX_DONE) {
        m_rx_ready = true;
    }
}

// 初始化SPIM从机
void spim_slave_init(void) {
    nrf_drv_spim_config_t spim_cfg = NRF_DRV_SPIM_DEFAULT_CONFIG;
    spim_cfg.sck_pin = PIN_PCLK;
    spim_cfg.mosi_pin = PIN_D0;
    spim_cfg.mode = NRF_SPIM_MODE_0;
    spim_cfg.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST; // 匹配传感器数据位序
    spim_cfg.role = NRF_SPIM_ROLE_SLAVE;

    ret_code_t err = nrf_drv_spim_init(&m_spim, &spim_cfg, spim_event_handler, NULL);
    APP_ERROR_CHECK(err);
    nrf_drv_spim_enable(&m_spim);
}

方案2:GPIOTE + PPI + DMA(灵活同步采样)

利用nRF52840的硬件联动,无需SPI外设:

  • GPIOTE配置PCLK为上升沿触发事件
  • PPI将PCLK事件链接到GPIOTE读取D0的任务,同时触发DMA写入缓冲区
  • VSYNC/HSYNC中断控制DMA的启动/停止,以及行/帧计数

三、帧捕获逻辑修正(替换GPIO轮询)

改用中断触发+DMA传输,避免CPU轮询:

uint8_t frameBuffer[324][324];
static volatile uint32_t current_row = 0;

// VSYNC中断:帧起始
void vsync_irq_handler(void) {
    nrf_gpio_pin_clear_int(PIN_VSYNC);
    current_row = 0;
    // 启动第一行数据接收
    m_rx_ready = false;
    nrf_drv_spim_rx(&m_spim, frameBuffer[current_row], 324);
}

// HSYNC中断:行切换
void hsync_irq_handler(void) {
    nrf_gpio_pin_clear_int(PIN_HSYNC);
    if (current_row >= 323) return;
    
    current_row++;
    m_rx_ready = false;
    nrf_drv_spim_rx(&m_spim, frameBuffer[current_row], 324);
}

// 初始化GPIO中断
void gpio_irq_init(void) {
    // VSYNC上升沿中断
    nrf_gpio_cfg_input(PIN_VSYNC, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_sense_input(PIN_VSYNC, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
    // HSYNC上升沿中断
    nrf_gpio_cfg_input(PIN_HSYNC, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_sense_input(PIN_HSYNC, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
    
    nrf_gpio_pin_clear_int(PIN_VSYNC);
    nrf_gpio_pin_clear_int(PIN_HSYNC);
    NVIC_EnableIRQ(GPIOTE_IRQn);
}

四、关键排查点

  1. 寄存器配置验证:用I2C读取配置寄存器,确认传感器确实工作在1位模式
  2. 时序匹配:确保SPIM的时钟相位/极性和HM01B0的PCLK时序完全一致
  3. 中断极性:检查VSYNC/HSYNC的有效电平是否与代码配置匹配(比如是高电平还是低电平有效)
  4. DMA缓冲区:确保帧缓冲区大小足够,且内存对齐符合DMA要求

内容的提问来源于stack exchange,提问作者shakingwindow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:55:16