• 发文章

  • 发资料

  • 发帖

  • 提问

  • 发视频

创作活动
0
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
返回

电子发烧友 电子发烧友

  • 全文搜索
    • 全文搜索
    • 标题搜索
  • 全部时间
    • 全部时间
    • 1小时内
    • 1天内
    • 1周内
    • 1个月内
  • 默认排序
    • 默认排序
    • 按时间排序
  • 全部板块
    • 全部板块
大家还在搜
  • 【瑞萨FPB-RA6E2试用】基础功能使用2

    看门狗 (WDT) 功能体验 前言 在嵌入式开发中,系统稳定性至关重要。本次测评旨在验证瑞萨 FPB-RA6E2 开发板在 Zephyr RTOS 环境下的看门狗功能。通过编写“正常喂狗”与“模拟死机”的测试程序,评估其硬件复位机制的可靠性以及 Zephyr 驱动框架的易用性。 硬件平台:Renesas FPB-RA6E2 软件环境:Zephyr OS v4.2.0 开发工具:VS Code + Zephyr SDK 2. Zephyr WDT 驱动模型解析 不同于裸机开发需要直接操作寄存器,Zephyr 提供了标准化的 Watchdog API (<zephyr/drivers/watchdog.h>)。 设备抽象:通过设备树 (Device Tree) 获取硬件节点,如 DEVICE_DT_GET(DT_NODELABEL(wdt))。 工作模式:支持“窗口模式”和普通超时模式。本次测试使用普通超时模式,配置为超时直接复位 SoC。 3. 关键配置 为了启用 WDT,需要在 prj.conf 中进行如下配置。 CONFIG_WATCHDOG=y#开启看门狗 4. 核心代码逻辑 测试程序设计了两个阶段: 安全期:前 10 次循环,LED 闪烁并按时调用 wdt_feed(),模拟系统正常运行。 死机模拟:停止喂狗,进入死循环,等待 WDT 硬件超时触发复位。 核心代码片段: /* 配置看门狗参数:3000ms 超时,触发 SoC 复位 */ struct wdt_timeout_cfg wdt_config = { .window.max = 3000, .flags = WDT_FLAG_RESET_SOC, .callback = NULL, }; wdt_install_timeout(wdt, &wdt_config); ​ /* 模拟循环 */ while (1) { if (i <= 10) { wdt_feed(wdt, wdt_channel_id); // 正常喂狗 printk(\"System Alive... Feed dog\\\\n\"); } else { printk(\"System Freeze! Stop feeding...\\\\n\"); while(1); // 模拟死机,不再喂狗 } k_msleep(500); } 5. 测试现象与日志分析 将程序烧录至 FPB-RA6E2 后,通过串口助手观察到以下现象: 阶段一(正常运行): 串口持续打印 \"Feeding the dog...\",开发板绿色用户 LED (LED1) 规律闪烁。说明在及时喂狗的情况下,系统运行稳定。 阶段二(触发复位): 当日志打印 \"SIMULATING FREEZE!\" 后,LED 熄灭,输出 Tick Tock。 复位发生: 约 3 秒后,串口突然重新打印 Zephyr 的启动 Banner: RA6E2 的片上 WDT 成功检测到超时,并强制拉低了复位信号,系统实现了自恢复。 6. 测评总结与开发心得 抽象统一:Zephyr 的 API 屏蔽了瑞萨底层寄存器的复杂性,代码可移植性极强。如果以后换成 STM32 或 Nordic 芯片,这套 WDT 代码几乎不用改。 配置灵活:通过 wdt_timeout_cfg 结构体可以非常方便地设置超时时间、窗口范围和回调函数。 FPB-RA6E2 配合 Zephyr 的 Watchdog 子系统,能够以极低的代码量实现高可靠性的系统守护功能。对于需要长期无人值守运行的物联网设备,这是一个必不可少的基础功能模块。 PWM 呼吸灯 前言 硬件:Renesas FPB-RA6E2 开发板 系统 zephyr 4.2.0 目的:测评zephyr对瑞萨系列PWM外设的支持度,以及验证引脚复用子系统的灵活性 硬件与原理 GPT:是一个16位定时器,具备GPT16E × 6通道。通过控制递增计数器、递减计数器或递增/递减计数器,可以生成PWM波形。此外,该定时器还能生成用于控制无刷直流电机的PWM波形,也可用作通用定时器。 LED:开发板拥有两个用户LED,引脚连接如下图所示: 从这个图中可以看出LED的连接引脚为P206和P207,我们需要通过这个引脚输出PWM,实现呼吸灯的效果。 从上图可以看出这两个引脚对应GTOIC5B和GTOIC5A。 核心配置 设备树覆盖 查看开发板的对应的fpb_ra6e2.dts /* * Copyright (c) 2024-2025 Renesas Electronics Corporation * SPDX-License-Identifier: Apache-2.0 */ ​ /dts-v1/; ​ #include <renesas/ra/ra6/r7fa6e2bb3cfm.dtsi> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input-event-codes.h> #include <zephyr/dt-bindings/adc/adc.h> ​ #include \"fpb_ra6e2-pinctrl.dtsi\" ​ / { model = \"Renesas FPB-RA6E2\"; compatible = \"renesas,ra6e2\", \"renesas,ra\"; ​ chosen { zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,entropy = &trng; }; ​ leds { compatible = \"gpio-leds\"; led1: led1 { gpios = <&ioport2 7 GPIO_ACTIVE_HIGH>; label = \"LED1\"; }; led2: led2 { gpios = <&ioport2 6 GPIO_ACTIVE_HIGH>; label = \"LED2\"; }; }; ​ buttons { compatible = \"gpio-keys\"; button0: s1 { gpios = <&ioport3 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = \"Push button switch 1\"; zephyr,code = <INPUT_KEY_0>; }; }; ​ aliases { led0 = &led1; led1 = &led2; sw0 = &button0; watchdog0 = &wdt; }; }; ​ &sci0 { pinctrl-0 = <&sci0_default>; pinctrl-names = \"default\"; status = \"okay\"; uart0: uart { current-speed = <115200>; status = \"okay\"; }; }; ​ &spi0 { pinctrl-0 = <&spi0_default>; pinctrl-names = \"default\"; status = \"okay\"; }; ​ &ioport2 { status = \"okay\"; }; ​ &ioport3 { status = \"okay\"; }; ​ &flash0 { partitions { compatible = \"fixed-partitions\"; #address-cells = <1>; #size-cells = <1>; ​ storage_partition: partition@0 { label = \"storage\"; reg = <0X0 DT_SIZE_K(4)>; }; }; }; ​ &subclk { status = \"okay\"; }; ​ &pll { clocks = <&hoco>; div = <1>; mul = <10 0>; status = \"okay\"; }; ​ &adc0 { status = \"okay\"; pinctrl-0 = <&adc0_default>; pinctrl-names = \"default\"; }; ​ &dac0 { pinctrl-0 = <&dac0_default>; pinctrl-names = \"default\"; status = \"okay\"; }; ​ &port_irq9 { interrupts = <41 12>; status = \"okay\"; }; ​ &pwm1 { pinctrl-0 = <&pwm1_default>; pinctrl-names = \"default\"; interrupts = <63 1>, <64 1>; interrupt-names = \"gtioca\", \"overflow\"; divider = <RA_PWM_SOURCE_DIV_256>; status = \"okay\"; }; ​ &trng { status =\"okay\"; }; ​ &wdt { status = \"okay\"; }; ​ 可以看出这里有关于PWM1的配置,具体引脚位置在fpb_ra6e2-pinctrl.dtsi中查看, pwm1_default: pwm1_default { group1 { /* GTIOC1A GTIOC1B */ psels = <RA_PSEL(RA_PSEL_GPT1, 4, 9)>, <RA_PSEL(RA_PSEL_GPT1, 4, 8)>; }; }; 可以看出这个引脚配置不是我们需要的LED灯,呼吸灯需要使用到GPT5,但这里只有GPT1的配置,所以需要自己在app.overlay里面进行相关配置。 参考这个GPT1的配置,完成的GPT5的配置如下所示 /* app.overlay */ /* 定义 PWM5 的引脚配置 * 通过引用 &pinctrl 来向原有的 pinctrl 节点追加内容 */ #include <zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h> &pinctrl { pwm5_default: pwm5_default { group1 { /* * P206 -> GTIOC5B (Function: GPT5) * P207 -> GTIOC5A (Function: GPT5) */ psels = <RA_PSEL(3, 2, 7)>, <RA_PSEL(3, 2, 6)>; }; }; }; /* 启用 PWM5 设备并应用上面的引脚配置 */ &pwm5 { status = \"okay\"; pinctrl-0 = <&pwm5_default>; pinctrl-names = \"default\"; interrupts = <65 1>, <66 1>; interrupt-names = \"gtioca\", \"overflow\"; /* 分频系数,可根据需要调整,保持和 pwm1 一致 */ divider = <RA_PWM_SOURCE_DIV_256>; }; ​ &led1 { status = \"disabled\"; }; ​ &led2 { status = \"disabled\"; }; 踩坑点:在刚开始配置的时候,直接搬运GPT1的配置进行修改, psels = <RA_PSEL(3, 2, 7)>, <RA_PSEL(3, 2, 6)>; /*上面这个我刚开始直接写成了下面的形式*/ psels = <RA_PSEL(RA_PSEL_GPT5, 2, 7)>, <RA_PSEL(RA_PSEL_GPT5, 2, 6)>; }; 对于上面的修改,编译过程中一直报错,一直不了解为什么,后来进入pinctrl-ra.h一看,没有关于RA_PSEL_GPT5的宏定义,所以要不然就直接写数值,要不然就自己写宏定义。 /* * Copyright (c) 2024-2025 Renesas Electronics Corporation * * SPDX-License-Identifier: Apache-2.0 */ ​ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RA_H__ #define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RA_H__ ​ #define RA_PORT_NUM_POS0 #define RA_PORT_NUM_MASK 0xf ​ #define RA_PIN_NUM_POS4 #define RA_PIN_NUM_MASK 0xf ​ #define RA_PSEL_HIZ_JTAG_SWD 0x0 #define RA_PSEL_ADC 0x0 #define RA_PSEL_DAC 0x0 #define RA_PSEL_ACMPHS 0x0 #define RA_PSEL_AGT 0x1 #define RA_PSEL_GPT00x2 #define RA_PSEL_GPT10x3 #define RA_PSEL_SCI_00x4 #define RA_PSEL_SCI_20x4 #define RA_PSEL_SCI_40x4 #define RA_PSEL_SCI_60x4 #define RA_PSEL_SCI_80x4 #define RA_PSEL_SCI_10x5 #define RA_PSEL_SCI_30x5 #define RA_PSEL_SCI_50x5 #define RA_PSEL_SCI_70x5 #define RA_PSEL_SCI_90x5 #define RA_PSEL_SPI 0x6 #define RA_PSEL_I2C 0x7 #define RA_PSEL_I3C 0x7 #define RA_PSEL_CLKOUT_RTC0x9 #define RA_PSEL_ACMPHS_VCOUT 0x9 #define RA_PSEL_CAC_ADC0xa #define RA_PSEL_CAC_DAC0xa #define RA_PSEL_BUS 0xb #define RA_PSEL_CANFD0x10 #define RA_PSEL_QSPI0x11 #define RA_PSEL_SSIE0x12 #define RA_PSEL_USBFS0x13 #define RA_PSEL_USBHS0x14 #define RA_PSEL_SDHI0x15 #define RA_PSEL_ETH_MII0x16 #define RA_PSEL_ETH_RMII0x17 #define RA_PSEL_GLCDC0x19 #define RA_PSEL_OSPI0x1c ​ #define RA_PSEL_POS8 #define RA_PSEL_MASK 0x1f ​ #define RA_MODE_POS13 #define RA_MODE_MASK 0x1 ​ #define RA_PSEL(psel, port_num, pin_num)\\\\ (1 << RA_MODE_POS | psel << RA_PSEL_POS | port_num << RA_PORT_NUM_POS |\\\\ pin_num << RA_PIN_NUM_POS) ​ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RA_H__ */ 驱动开关 因为使用到了PWM的功能,所以需要开启PWM驱动。 CONFIG_PWM=y 效果测评 配置好PWM后,呼吸灯程序如下所示,通过改变占空比实现呼吸灯的效果。 呼吸灯代码: #include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/drivers/pwm.h> #include <zephyr/sys/printk.h> ​ /* * 获取设备树中的 PWM5 节点 * 对应 overlay 中的 &pwm5 */ static const struct device *pwm5_dev = DEVICE_DT_GET(DT_NODELABEL(pwm5)); ​ /* * 通道定义: * 根据 Renesas GPT 驱动逻辑和 Pinctrl 设置: * P207 (GTIOC5A) -> 通常对应 Channel 0 * P206 (GTIOC5B) -> 通常对应 Channel 1 * *通过修改下面的宏来切换测试引脚 */ #define PWM_CHANNEL0 ​ /* 定义周期为 1 毫秒 (10,000,00 纳秒) -> 频率 1000Hz */ #define PWM_PERIOD_NS1000000 ​ int main(void) { printk(\"Starting PWM5 Test Example\\\\n\"); ​ /* 1. 检查 PWM 设备是否初始化成功 */ if (!device_is_ready(pwm5_dev)) { printk(\"Error: PWM device %s is not ready\\\\n\", pwm5_dev->name); return 0; } ​ printk(\"PWM Device %s is ready on Channel %d\\\\n\", pwm5_dev->name, PWM_CHANNEL); ​ /* 变量用于控制呼吸灯效果 */ uint32_t pulse_width = 0; uint32_t step = PWM_PERIOD_NS / 50; // 每次变化 2% bool dir_up = true; // 亮度增加方向 ​ while (1) { /* * 2. 设置 PWM 输出 * API: pwm_set(设备, 通道, 周期ns, 脉宽ns, 标志位) */ int ret = pwm_set(pwm5_dev, PWM_CHANNEL, PWM_PERIOD_NS, pulse_width, PWM_POLARITY_NORMAL); ​ if (ret != 0) { printk(\"Error: Failed to set PWM (err %d)\\\\n\", ret); break; } ​ /* 3. 更新脉宽 (呼吸灯逻辑) */ if (dir_up) { pulse_width += step; if (pulse_width >= PWM_PERIOD_NS) { pulse_width = PWM_PERIOD_NS; dir_up = false; // 达到最大,开始减小 } } else { if (pulse_width < step) { pulse_width = 0; dir_up = true; // 达到最小,开始增加 } else { pulse_width -= step; } } ​ /* 延时 20ms,让人眼能看到变化*/ k_sleep(K_MSEC(20)); } ​ return 0; } ​ ​ ​ DAC/ADC 性能测评报告 测评目的 验证在 Zephyr RTOS 环境下,FPB-RA6E2 开发板的模拟外设驱动功能。具体目标包括: **验证 **DAC 驱动能否在指定引脚输出准确电压。 **验证 **ADC (Analog-to-Digital Converter)驱动能否准确采集外部电压。 **通过 **DAC -> ADC 回环 (Loopback)方式,评估两者协同工作的精度与稳定性。 硬件环境与连接 由于 FPB-RA6E2 的 Arduino 接口标准定义中不包含 DAC 引脚,本次测试需要使用板载扩展接口进行物理连接。 开发板:Renesas FPB-RA6E2 DAC 输出引脚:P014 (位于板载 J6 扩展排孔左列,需手动接线) ADC 输入引脚:P000 / A0 (位于 Arduino 接口 CN8 排母) 参考电压 (VREF):内部 3.3V 连接方式:使用杜邦线将 P014 短接至 P000 (A0)。 软件配置 开启 ADC 和 DAC 子系统,并启用控制台浮点打印支持。 CONFIG_ADC=y CONFIG_DAC=y CONFIG_PRINTK=y CONFIG_CBPRINTF_FP_SUPPORT=y 测试代码逻辑 测试程序采用轮询机制,逻辑如下: 初始化:分别获取 DAC 和 ADC 设备指针。 配置 (Setup): DAC:配置为 12-bit 分辨率,开启缓冲 (Buffered) 以增强驱动能力。 ADC:配置为 12-bit 分辨率,无增益,内部参考电压。 循环测试: 设定目标电压(0V, 1V, 2V, 3V 循环)。 计算 DAC 数值并写入寄存器。 延时 100ms 等待电压稳定。 触发 ADC 采样序列。 计算差值并通过串口打印报告。 代码: ​ #include <zephyr/kernel.h> #include <zephyr/drivers/dac.h> #include <zephyr/drivers/adc.h> #include <zephyr/sys/printk.h> ​ /* --- 定义与参数 --- */ #define DAC_NODEDT_NODELABEL(dac0) #define ADC_NODEDT_NODELABEL(adc0) ​ /* RA6E2 ADC/DAC 均为 12位 */ #define RESOLUTION12 #define MAX_VAL4095 #define REF_VOLT_MV3300 ​ /* 通道定义 */ #define DAC_CHANNEL_ID0// 对应 P014 #define ADC_CHANNEL_ID0// 对应 P000 (A0) ​ /* 获取设备指针 */ static const struct device *dac_dev = DEVICE_DT_GET(DAC_NODE); static const struct device *adc_dev = DEVICE_DT_GET(ADC_NODE); ​ /* ADC 采样缓冲区 */ static int16_t m_sample_buffer[1]; ​ /* --- DAC 配置结构体--- */ static const struct dac_channel_cfg dac_ch_cfg = { .channel_id = DAC_CHANNEL_ID, .resolution = RESOLUTION, .buffered= true, /* 开启缓冲,增强驱动能力 */ }; ​ /* --- ADC 配置结构体 --- */ static const struct adc_channel_cfg adc_ch_cfg = { .gain = ADC_GAIN_1, .reference= ADC_REF_INTERNAL, .acquisition_time = ADC_ACQ_TIME_DEFAULT, .channel_id = ADC_CHANNEL_ID, }; ​ /* --- ADC 序列结构体 --- */ static const struct adc_sequence adc_seq = { .channels = BIT(ADC_CHANNEL_ID), .buffer= m_sample_buffer, .buffer_size = sizeof(m_sample_buffer), .resolution= RESOLUTION, }; ​ int main(void) { int ret; uint32_t dac_target_mv = 0; // 目标输出电压 (mV) uint32_t dac_raw_val = 0;// DAC 原始寄存器值 ​ k_sleep(K_MSEC(1000)); printk(\"============================================\\\\n\"); printk(\"DAC Output -> ADC Input Loopback Test \\\\n\"); printk(\"============================================\\\\n\"); ​ /* 1. 检查设备就绪 */ if (!device_is_ready(dac_dev) || !device_is_ready(adc_dev)) { printk(\"Error: ADC or DAC device not ready\\\\n\"); return -1; } ​ /* 2. 初始化 DAC 通道 */ ret = dac_channel_setup(dac_dev, &dac_ch_cfg); if (ret != 0) { printk(\"Error: DAC setup failed: %d\\\\n\", ret); return -1; } ​ /* 3. 初始化 ADC 通道 */ ret = adc_channel_setup(adc_dev, &adc_ch_cfg); if (ret != 0) { printk(\"Error: ADC setup failed: %d\\\\n\", ret); return -1; } ​ printk(\"Setup Complete. Connect P014 to A0.\\\\n\\\\n\"); ​ while (1) { /* --- 逻辑: 让电压在 0V -> 1V -> 2V -> 3V 之间循环切换 --- */ dac_target_mv += 1000; if (dac_target_mv > 3000) dac_target_mv = 0; ​ /* 计算 DAC 数值: Value = (mV / 3300) * 4095 */ dac_raw_val = (dac_target_mv * MAX_VAL) / REF_VOLT_MV; ​ /* DAC 输出 */ ret = dac_write_value(dac_dev, DAC_CHANNEL_ID, dac_raw_val); if (ret != 0) { printk(\"DAC write error\\\\n\"); } ​ /* 等待电压稳定 */ k_sleep(K_MSEC(100)); ​ /* ADC 采集 */ ret = adc_read(adc_dev, &adc_seq); if (ret != 0) { printk(\"ADC read error\\\\n\"); } else { int16_t adc_raw = m_sample_buffer[0]; if (adc_raw < 0) adc_raw = 0; ​ /* 计算 ADC 实际读到的电压 */ int32_t adc_mv = (int32_t)adc_raw * REF_VOLT_MV / MAX_VAL; int32_t diff = adc_mv - (int32_t)dac_target_mv; ​ /* 打印对比结果 */ printk(\"DAC Set: %4dmV (Raw:%4d)--->ADC Read: %4dmV (Raw:%4d)| Diff: %d mV\\\\n\", dac_target_mv, dac_raw_val, adc_mv, adc_raw, diff); } ​ k_sleep(K_MSEC(1000)); } return 0; } 结果分析: 线性度良好:在 0V ~ 3.3V 范围内,ADC 采集值紧密跟随 DAC 输出值。 误差范围:最大绝对误差控制在 ±5mV 以内(约 2-3 个 LSB),这对于非精密测量应用来说精度非常高。 结论 功能验证通过:Renesas FPB-RA6E2 在 Zephyr RTOS 下的 ADC 和 DAC 功能完全可用。 精度达标:12位分辨率下的回环测试误差极小,满足一般工控及传感器读取需求。 开发注意: 必须注意 DAC 引脚 (P014) 的物理位置不在 Arduino 标准接口上。

    2025-12-30 17:08

  • 【乾芯QXS320F开发板试用】i2c传感器驱动测试

    介绍 DSP QXS320F280049 DSP芯片集成了一路i2c接口,它的i2c接口符合NXP Semiconductor i2c总线规范: 支持8位格式传输 7位和10位寻址模式 常规调用 START字节模式 支持多个主发送器和从接收器 支持多个从发送器和主接收器 组合主器件发送/接收和接收/发送模式 数据传输速率从10kbps到400kbps(快速模式) 另外,它还具备了增强的数据通信能力: 一个16字节接收FIFO和一个16字节发送FIFO 支持两个ePIE中断&& FIFO中断 模块启用和禁用能力 自由数据格式模式 LM75 LM75温度传感器集成了一个Δ-Σ模数转换器和一个数字式超温检测器。主机可随时通过其i2c接口查询LM75以读取温度值。其开漏极超温输出端(OS)会在可编程温度限制被超过时吸收电流。OS输出可在比较器模式或中断模式两种模式下工作。主机可控制报警触发温度(TOS)及解除报警状态的迟滞温度(THYST)。同时,主机也能读取LM75的TOS和THYST寄存器。通过三个引脚可设置LM75的设备地址,允许多个设备在同一总线上工作。上电默认处于比较器模式,TOS默认值为+80°C,THYST默认值为+75°C。其3.0V至5.5V的供电电压范围、低功耗电流和I²C接口特性,使LM75成为热管理和热保护众多应用的理想选择。 硬件接口 i2c接口对应一组GPIO:GPIO0 -> SDA,GPIO1 -> SCL LM75传感器连接QXS320F280049开发板:GPIO0接SDA,GPIO1接SCL,VCC接3.3V,GND接地 驱动实现 i2c接口支持的复用IO 选项 SDA 引脚 SCL 引脚 SDA 复用定义 SCL 复用定义 选项 0 GPIO_0 GPIO_1 GPIO_0_I2CA_SDA GPIO_1_I2CA_SCL 选项 1 GPIO_10 GPIO_8 GPIO_10_I2CA_SDA GPIO_8_I2CA_SCL 选项 2 GPIO_32 GPIO_33 GPIO_32_I2CA_SDA GPIO_33_I2CA_SCL 选项 3 GPIO_26 GPIO_27 GPIO_26_I2CA_SDA GPIO_27_I2CA_SCL GPIO映射绑定 typedef struct { uint32_t sdaPin; uint32_t sdaPinMux; uint32_t sclPin; uint32_t sclPinMux; } LM75_GpioConfig_t; ​ static const LM75_GpioConfig_t lm75GpioConfig[] = { // Option 0: GPIO_0 (SDA) + GPIO_1 (SCL) - Recommended { .sdaPin = 0, .sdaPinMux = GPIO_0_I2CA_SDA, .sclPin = 1, .sclPinMux = GPIO_1_I2CA_SCL }, // Option 1: GPIO_10 (SDA) + GPIO_8 (SCL) { .sdaPin = 10, .sdaPinMux = GPIO_10_I2CA_SDA, .sclPin = 8, .sclPinMux = GPIO_8_I2CA_SCL }, // Option 2: GPIO_32 (SDA) + GPIO_33 (SCL) { .sdaPin = 32, .sdaPinMux = GPIO_32_I2CA_SDA, .sclPin = 33, .sclPinMux = GPIO_33_I2CA_SCL }, // Option 3: GPIO_26 (SDA) + GPIO_27 (SCL) { .sdaPin = 26, .sdaPinMux = GPIO_26_I2CA_SDA, .sclPin = 27, .sclPinMux = GPIO_27_I2CA_SCL } }; ​ void LM75_gpioInit(uint8_t pinOption) { const LM75_GpioConfig_t *pgpio; ​ ASSERT(pinOption <= LM75_I2C_PIN_OPTION_3); ​ pgpio = &lm75GpioConfig[pinOption]; ​ // Configure SDA pin GPIO_setPadConfig(pgpio->sdaPin, GPIO_PIN_TYPE_OD);// Open-drain output GPIO_setQualificationMode(pgpio->sdaPin, GPIO_QUAL_ASYNC);// Async qualification GPIO_setPinConfig(pgpio->sdaPinMux);// Set pin mux to I2C SDA ​ // Configure SCL pin GPIO_setPadConfig(pgpio->sclPin, GPIO_PIN_TYPE_OD);// Open-drain output GPIO_setQualificationMode(pgpio->sclPin, GPIO_QUAL_ASYNC);// Async qualification GPIO_setPinConfig(pgpio->sclPinMux);// Set pin mux to I2C SCL } 读写i2c寄存器接口封装 uint16_t LM75_readRegister(LM75_Handle *handle, uint8_t regAddr, uint16_t *regValue) { uint32_t base = handle->i2cBase; uint32_t timeout = LM75_I2C_TIMEOUT; uint16_t status; ​ ASSERT(handle != 0); ASSERT(regValue != 0); ​ // Wait until the STOP bit is cleared from any previous communication timeout = LM75_I2C_TIMEOUT; while (I2C_getStopConditionStatus(base) && timeout--) ; if (timeout == 0) { return LM75_STATUS_STOP_NOT_READY; } ​ // Check if bus is busy and wait for it to be free timeout = LM75_I2C_TIMEOUT; while (I2C_isBusBusy(base) && timeout--) ; if (timeout == 0) { return LM75_STATUS_BUS_BUSY; } ​ // Set controller as transmitter in repeat mode I2C_setConfig(base, I2C_CONTROLLER_SEND_MODE | I2C_REPEAT_MODE); // Set 7-bit address mode (LM75 uses 7-bit addressing, fixed address 0x48) I2C_setAddressMode(base, I2C_ADDR_MODE_7BITS); I2C_setTargetAddress(base, LM75_I2C_ADDRESS); ​ // Send start condition I2C_sendStartCondition(base); ​ // Send register address (no need to wait for REG_ACCESS_RDY, just send data) I2C_putData(base, regAddr); timeout = LM75_I2C_TIMEOUT; // Wait for data to be copied from DXR to shift register (TX_DATA_RDY cleared) while (((I2C_getStatus(base) & I2C_STS_TX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ // Switch to receiver mode I2C_setConfig(base, I2C_CONTROLLER_RECEIVE_MODE); ​ // Set data count to 2 bytes (16-bit register) I2C_setDataCount(base, 2); ​ // Send restart condition (no need to wait for REG_ACCESS_RDY) I2C_sendStartCondition(base); ​ // Read high byte (MSB) timeout = LM75_I2C_TIMEOUT; while ((!(I2C_getStatus(base) & I2C_STS_RX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ *regValue = (uint16_t)(I2C_getData(base) << 8); I2C_clearStatus(base, I2C_STS_RX_DATA_RDY); ​ // Read low byte (LSB) timeout = LM75_I2C_TIMEOUT; while ((!(I2C_getStatus(base) & I2C_STS_RX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ *regValue |= I2C_getData(base); I2C_clearStatus(base, I2C_STS_RX_DATA_RDY); ​ // Send stop condition I2C_sendStopCondition(base); ​ return LM75_STATUS_SUCCESS; } ​ uint16_t LM75_writeRegister(LM75_Handle *handle, uint8_t regAddr, uint16_t regValue) { uint32_t base = handle->i2cBase; uint32_t timeout = LM75_I2C_TIMEOUT; uint16_t status; ​ ASSERT(handle != 0); ​ // Wait until the STOP bit is cleared from any previous communication timeout = LM75_I2C_TIMEOUT; while (I2C_getStopConditionStatus(base) && timeout--) ; if (timeout == 0) { return LM75_STATUS_STOP_NOT_READY; } ​ // Check if bus is busy and wait for it to be free timeout = LM75_I2C_TIMEOUT; while (I2C_isBusBusy(base) && timeout--) ; if (timeout == 0) { return LM75_STATUS_BUS_BUSY; } ​ // Set controller as transmitter I2C_setConfig(base, I2C_CONTROLLER_SEND_MODE | I2C_REPEAT_MODE); // Set 7-bit address mode (LM75 uses 7-bit addressing, fixed address 0x48) I2C_setAddressMode(base, I2C_ADDR_MODE_7BITS); I2C_setTargetAddress(base, LM75_I2C_ADDRESS); ​ // Send start condition I2C_sendStartCondition(base); ​ // Send register address (no need to wait for REG_ACCESS_RDY, just send data) I2C_putData(base, regAddr); timeout = LM75_I2C_TIMEOUT; // Wait for data to be copied from DXR to shift register (TX_DATA_RDY cleared) while (((I2C_getStatus(base) & I2C_STS_TX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ // Send high byte (MSB) I2C_putData(base, (regValue >> 8) & 0xFFU); timeout = LM75_I2C_TIMEOUT; // Wait for data to be copied from DXR to shift register (TX_DATA_RDY cleared) while (((I2C_getStatus(base) & I2C_STS_TX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ // Send low byte (LSB) I2C_putData(base, regValue & 0xFFU); timeout = LM75_I2C_TIMEOUT; // Wait for data to be copied from DXR to shift register (TX_DATA_RDY cleared) while (((I2C_getStatus(base) & I2C_STS_TX_DATA_RDY)) && timeout--) ; ​ if (timeout == 0) { I2C_sendStopCondition(base); return LM75_STATUS_TIMEOUT; } ​ // Send stop condition I2C_sendStopCondition(base); ​ return LM75_STATUS_SUCCESS; } 采用轮询poll的方式读取并解析i2c传感器温度数值 uint16_t LM75_readRawTemperature(LM75_Handle *handle, uint16_t *rawTemp) { return LM75_readRegister(handle, LM75_REG_TEMP, rawTemp); } ​ uint16_t LM75_readTemperature(LM75_Handle *handle, float *temperature) { uint16_t rawTemp; uint16_t status; ​ ASSERT(temperature != 0); ​ status = LM75_readRawTemperature(handle, &rawTemp); if (status == LM75_STATUS_SUCCESS) { *temperature = LM75_rawToCelsius(rawTemp); } ​ return status; } ​ int main(void) { LM75_Handle lm75; float temperature; uint16_t status; ​ // 初始化设备 Device_init(); Interrupt_initVectorTable(); ​ // // Uncomment the following statement if to use DSP core 1 // //SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CPU1); ​ // 使能I2C外设时钟 SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2CA); ​ // 初始化I2C GPIO引脚:使用 GPIO_0 (SDA) + GPIO_1 (SCL) LM75_gpioInit(LM75_I2C_PIN_OPTION_0); ​ // 初始化I2C控制器 I2C_disableModule(I2CA_BASE); I2C_disableLoopback(I2CA_BASE); I2C_initController(I2CA_BASE, DEVICE_SYSCLK_FREQ, 400000, I2C_DUTYCYCLE_50); I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8); I2C_setAddressMode(I2CA_BASE, I2C_ADDR_MODE_7BITS); I2C_disableFIFO(I2CA_BASE); I2C_enableModule(I2CA_BASE); ​ // 等待I2C模块稳定 DEVICE_DELAY_US(10000);// 延时10ms ​ // 初始化LM75温度传感器 LM75_init(&lm75, I2CA_BASE); ​ printf(\"LM75 Temperature Sensor Test\\\\r\\\\n\"); printf(\"I2C Address: 0x48\\\\r\\\\n\"); printf(\"GPIO: SDA=GPIO_0, SCL=GPIO_1\\\\r\\\\n\"); printf(\"--------------------------------\\\\r\\\\n\"); ​ // 主循环:读取温度 while(1) { status = LM75_readTemperature(&lm75, &temperature); if (status == LM75_STATUS_SUCCESS) { printf(\"Temperature: %.2f C\\\\r\\\\n\", temperature); } else { printf(\"Error: Failed to read temperature, status=0x%04X\\\\r\\\\n\", status); } ​ // 延时1秒后再次读取 DEVICE_DELAY_US(1000000); } ​ return 0; } 实验效果 实时读取环境的温度

    2025-12-30 16:02

  • HT1001EK音视频编码器——高清传输.稳定无忧,全场景音视频解决方案

    一、精简版产品宣传单页文案(适合线下派发/线上传播) 标题:HT1001EK音视频编码器——高清传输·稳定无忧,全场景音视频解决方案 ✅ 核心亮点:4K输入+1080P输出,海思芯片7x24小时稳定运行 ✅ 传输黑科技:光纤20km/网线250m远距离传输,无中继不卡顿 ✅ 全能适配:直播推流/安防监控/会议教学,多场景无缝切换 ✅ 简易操作:WEB+键鼠+串口三重控制,5分钟快速部署 ? 咨询热线:XXX-XXXX-XXXX | 批量采购享专属折扣 核心参数速览 • 编码:H.264/H.265,主码流1080P/子码流720P • 音频:8K-48K采样,立体声输入输出 • 协议:RTMP/RTSP,支持推流拉流 • 接口:HDMI/光纤/网口/RS232,全能适配 1. 针对直播机构/传媒团队 “您做网络直播最担心高清信号卡顿、推流延时吧?咱们这款编码器用华为海思芯片,H.265编码能省50%带宽,4K输入+1080P推流,抖音、快手等平台直接适配,光纤20公里远距离传输都不丢帧。而且支持RTMP推流,WEB界面一键配置,不用专业技术也能快速上手,7x24小时连续直播都稳定,完全满足您的直播时效和画质需求。” 2. 针对安防企业/物业单位 “安防监控最看重稳定和远距离传输,咱们这款设备支持网线250米、光纤20公里传输,不用额外加中继器,小区、工厂园区的远程监控都能覆盖。海思芯片+ESD静电保护,7x24小时不间断运行不出故障,还能通过RS232串口远程控制,配合NVR存储,主码流1080P高清录像,子码流远程查看,兼顾画质和传输效率,比普通编码器稳定性高30%,部署成本还更低。” 3. 针对教育机构/政企单位 “多媒体教学、跨地域会议最怕设备复杂、调试麻烦吧?咱们这款编码器HDMI即插即用,键鼠直接连接就能配置参数,老师、行政人员都能操作。支持音频分离和独立输入,线上课程录播、会议发言都清晰,1080P高清画面+低延时传输,拼接屏、投影机都能适配。而且兼容RTSP协议,VLC播放器直接拉流,不管是教室、会议室还是远程培训,一台设备就能搞定所有音视频传输需求。”

    2025-12-30 15:26

  • HT1000网络视频延长器的详细使用说明和注意事项

    HT1000 网络延长器使用说明书一、产品概述HT1000 网络延长器(多媒体节点)是一款基于网络系统架构的高清音视频传输设备,采用模块化设计与纯硬件架构,支持通过单根网线长距离传输高清音视频信号,可实现 1 路高清信号经交换机后多路显示。产品具备传输距离远、使用成本低、安装便捷、兼容性强等优势,核心采用嵌入式 Linux 方案保障系统稳定,适用于能源电力、司法监狱、智慧城市、多媒体教学、家庭影院等多领域的音视频传输需求。 二、核心参数速览(一)基础性能 视频分辨率:最高支持 1080P@60Hz,无降帧处理,色彩还原度高 传输距离:6 类网线环境下最远可达 200 米(网口传输);高清接口输入 / 输出距离建议≤5 米(1080P@60Hz 时) 传输延时:≤0.2 秒,无拖影、无失真 音视频支持:双向音视频输入 / 输出,流媒体格式保障传输流畅性 (二)硬件规格 接口类型:高清信号输入 / 输出接口、DC 5V 电源接口、RJ45 网线接口(10M/100M)、Reset 复位按钮 像素带宽:165MHz(全数字),总接口带宽 1.5Gbps 电源参数:DC 5V 电源适配器,最大功耗 2W 工作环境:温度 - 5℃~+70℃,湿度 5%~90% 外形尺寸:12×13×3cm 三、安装与配置步骤(一)设备清单核对开箱后请确认包含以下组件,缺失请及时联系售后: HT-1000 延长器发射器 1 台、接收器 1 台 电源适配器 2 个 用户手册 1 本 (二)硬件连接流程 信号源连接:将高清信号源(机顶盒、NVR 监控主机、电脑、DVD 等)通过高清线接入发射器(TX)的 HD IN 口。 显示设备连接:将接收器(RX)通过高清线连接至显示终端(高清电视、拼接屏、投影机、LED 点阵屏等)。 网络连接:使用 6 类网线连接发射器与接收器的 LAN 接口;若需 1 对多显示,需在发射器与多个接收器之间接入交换机,实现信号分流。 供电启动:分别为发射器和接收器连接 DC 5V 电源适配器,接通电源后,指示灯正常亮起即表示系统启动成功。 (三)网络与 IP 配置 IP 网段设置:将操作电脑的 IP 地址与设备 IP 设置在同一网段(默认设备 IP:192.168.1.168)。 WEB 平台登录:打开 IE 浏览器,输入设备 IP,在登录界面输入默认用户名(admin)和默认密码(admin),鉴权通过后进入操作平台。 IP 参数修改:在 WEB 平台点击 “设备管理”-“IP 配置”,输入自定义的 IP 地址、子网掩码、默认网关,点击 “保存” 后生效,后续需使用新 IP 登录平台。 四、功能操作指南(一)信号管理 单设备登录 WEB 平台后,点击 “设备信息” 可查看 CPU 使用率、内存占用、模块运行状态等实时数据,点击 “刷新” 更新信息。 支持任意输入信号的共享、选择与显示,可通过平台自定义输入输出参数,实现 1080P@60Hz 点对点传输。 (二)设备维护 复位操作:按下设备上的 Reset 物理按键,可快速恢复设备默认设置(复位后 IP、用户名密码将恢复初始值)。 应用升级:在 WEB 平台 “设备管理”-“应用升级” 中,点击 “选择文件” 导入升级包,上传完成后点击 “重启”,设备将自动完成升级并重启。 用户管理:通过 WEB 平台 “用户管理” 功能,可修改登录用户名和密码,提升设备安全性。 (三)多模式使用 1 对 1 连接:发射器直接通过网线连接接收器,实现单个信号源对应单个显示设备的传输。 1 对多连接:发射器连接交换机,多个接收器通过网线接入同一交换机,实现单个信号源同时输出至多个显示终端。 五、注意事项(一)安装与环境要求 网线建议使用 6 类及以上标准网线,非标准网线可能导致传输距离缩短、信号不稳定。 高清输入 / 输出线长度需控制在 5 米内,超过该长度可能出现画质模糊、信号衰减。 设备需安装在通风、干燥环境,避免阳光直射、高温潮湿或粉尘较多的位置,远离强电磁干扰源(如大功率电机、变频器等)。 电源适配器需使用原装 DC 5V 规格,禁止使用电压不符或劣质适配器,以免损坏设备。 (二)使用安全规范 设备内置 ESD 静电保护模块,但仍需避免在干燥环境中频繁插拔接口,防止静电击穿元器件。 插拔网线、高清线前,建议先关闭设备电源,避免热插拔导致接口损坏。 禁止私自拆卸设备外壳,拆机后将失去保修资格,故障需由专业人员处理。 工作温度超出 - 5℃~+70℃范围时,设备可能自动停机保护,需及时调整使用环境温度。 (三)常见问题排查 无法登录 WEB 平台:检查电脑与设备是否在同一网段;确认 IP 地址输入正确(初始 IP:192.168.1.168);若已修改 IP,需使用新 IP 登录;排查网线连接是否正常。 画面有拖影 / 失真:检查网线是否为 6 类标准,传输距离是否超过 200 米;确认高清线长度≤5 米;检查信号源分辨率是否超过 1080P@60Hz(设备不支持更高分辨率)。 无音视频输出:检查电源是否接通,指示灯是否正常亮起;确认信号源已开机且输出正常;核对高清线、网线是否插紧,接口是否插错(发射器接 HD IN,接收器接显示设备)。 设备频繁离线:检查供电是否稳定;排查网络环境是否存在干扰;查看设备工作温度是否超标,必要时改善通风条件。 六、售后保障 产品享有 1 年免费保修服务,保修期内非人为损坏的故障可免费维修或更换配件。 超出保修期后提供终生维护服务,维修仅收取配件成本费。 如遇设备故障或使用疑问,可联系官方售后渠道,提供设备型号、故障现象等信息,获取专业技术支持。

    2025-12-30 14:46

  • DP4391频率范围:300 - 480 MHz 兼容CMT2220LY

    DP4391 是一款低功耗、高性能、即插即用型 OOK 射频接收器,该芯片具有 2.5V - 5.5V 较宽的输入电压范围,灵敏度高达到-112dBm,工作频段为 300 - 480 MHz,支持 1 - 5 Kbps 的数据率传输。采用 SOP-8 封装类型,应用时仅需天线端阻抗匹配网络、VDD 退耦电容、CTH 和AGC 滤波电容,VDD 电路上无需增加防过冲电阻,从而降低应用成本。  频率范围:300 - 480 MHz  接收灵敏度:-112 dBm(1 Kbps)  数据率范围: 1 - 5 Kbps  电压范围:2.5V - 5.5V  低功耗:5.3 mA @ 3.3V(315 MHz)  SOP8 封装版本

    2025-12-30 14:29

  • NRF24L01——2.4GHz无线通信

    对于学习嵌入式中的通信,可能会用到这个模块,该模块应用的是si24r1芯片。 一、si24r1简介: Si24R1 是一颗工作在 2.4GHz ISM 频段,专为低功耗无线场合设计,集成嵌入式 ARQ 基带协议引擎的无线收发器芯片。工作频率范围为 2400MHz-2525MHz,共有 126 个 1MHz 带宽的信道。 Si24R1 采用 GFSK/FSK 数字调制与解调技术。数据传输速率与 PA 输出功率都可以调节,支持 2Mbps,1Mbps,250Kbps 三种数据速率。高的数据速率可以在更短的时间完成同样的数据收发,因此可以具有更低的功耗。 Si24R1 针对低功耗应用场合进行了特别优化,在关断模式下,所有寄存器值与 FIFO 值保持不变,关断电流小于 0.7uA;在待机模式下,时钟保持工作,电流小于 15uA,并且可以在不到 130uS 时间内开始数据的收发。 Si24R1 操作方式非常方便, 只需要微控制器(MCU)通过 SPI 接口对芯片少数几个寄存器配置即可以实现数据的收发通信。嵌入式 ARQ 基带引擎基于包通信原理,支持多种通信模式,可以手动或全自动 ARQ 协议操作。内部集成收发FIFO,可以保证芯片与 MCU 数据连续传输,增强型 ARQ 基带协议引擎能处理所有高速操作,因此大大降低了 MCU 的系统消耗。 Si24R1 具有非常低的系统应用成本,只需要一个 MCU 和少量外围无源器件即可以组成一个无线数据收发系统。内部集成高 PSRR 的 LDO 电源,保证 1.9-3.6V宽电源范围内稳定工作;数字 IO 兼容 3.3V/5V 两种电压,可以与各种 MCU 接口。 二、工作模式:状态转换图Si24R1 芯片内部有状态机,控制着芯片在不同工作模式之间的转换。Si24R1 可配置为 Shutdown、Standby、Idle-TX、TX 和 RX 五种工作模式。 Shutdown 工作模式 在 Shutdown 工作模式下,Si24R1 所有收发功能模块关闭,芯片停止工作,消耗电流最小,但所有内部寄存器值和 FIFO 值保持不变,仍可通过 SPI 实现对寄存器的读写。设置 CONFIG 寄存器的 PWR_UP 位的值为 0,芯片立即返回到Shutdown 工作模式。Standby 工作模式。 在 Standby 工作模式,只有晶体振荡器电路工作,保证了芯片在消耗较少电流的同时能够快速启动。设置 CONFIG 寄存器下的 PWR_UP 位的值为 1,芯片待时钟稳定后进入 Standby 模式。芯片的时钟稳定时间一般为 1.5~2ms,与晶振的性能有关。当引脚 CE=1 时,芯片将由 Standby 模式进入到 Idle-TX 或 RX 模式,当 CE=0 时,芯片将由 Idle-TX、TX 或 RX 模式返回到 Standby 模式。Idle-TX 工作模式 在 Idle-TX 工作模式下,晶体振荡器电路及时钟电路工作。相比于 Standby模式,芯片消耗更多的电流。当发送端 TX FIFO 寄存器为空,并且引脚 CE=1时,芯片进入到 Idle-TX 模式。在该模式下,如果有新的数据包被送到 TX FIFO中,芯片内部的电路将立即启动,切换到 TX 模式将数据包发送。在 Standby 和 Idle-TX 工作模式下,所有内部寄存器值和 FIFO 值保持不变,仍可通过 SPI 实现对寄存器的读写。TX 工作模式 当需要发送数据时,需要切换到 TX 工作模式。芯片进入到 TX 工作模式的条件为:TX FIFO 中有数据, CONFIG 寄存器的 PWR_UP 位的值为 1,PRIM_RX位的值为 0,同时要求引脚 CE 上有一个至少持续 10us 的高脉冲。芯片不会直接由 Standby 模式直接切换到 TX 模式,而是先立即切换到 Idle-TX 模式,再由Idle-TX 模式自动切换到 TX 模式。Idle-TX 模式切换到 TX 模式的时间为120us~130us 之间,但不会超过 130us。单包数据发送完成后,如果 CE=1, 则由TX FIFO 的状态来决定芯片所处的工作模式,当 TX FIFO 还有数据,芯片继续保持在TX工作模式,并发送下一包数据;当TX FIFO没有数据,芯片返回Idle-TX模式;如果 CE=0,立即返回 Standby 模式。数据发射完成后,芯片产生数据发射完成中断。RX 工作模式当需要接收数据时,需要切换到 RX 工作模式。芯片进入到 RX 工作模式的条件为:设置寄存器 CONFIG 的 PWR_UP 位的值为 1,PRIM_RX 位的值为 1,并且引脚 CE=1。芯片由 Standby 模式切换到 RX 模式的时间为 120~130us。当接收到数据包的地址与芯片的地址相同,并且 CRC 检查正确时,数据会自动存入RX FIFO,并产生数据接收中断。芯片最多可以同时存三个有效数据包,当 FIFO已满,接收到的数据包被自动丢掉。在接收模式下,可以通过 RSSI 寄存器检测接收信号功率。当接收到的信号强度大于-60dBm 时,RSSI 寄存器的 RSSI 位的值将被设置为 1。否则,RSSI=0。RSSI 寄存器的更新方法有两种:当接收到有效的数据包后,RSSI 会自动更新,此外,将芯片从 RX 模式换到 Standby 模式时 RSSI 也会自动更新。RSSI 的值会随温度的变化而变化,范围在±5dBm 以内三、数据包处理协议 Si24R1 基于包通信,支持停等式 ARQ 协议。芯片内部 ARQ 协议基带处理引擎,可以不需要外部微控制器干预下,自动实现 ACK 和 NO_ACK 数据包的处理。ARQ 协议基带处理单元支持 1 到 32 字节动态数据长度,数据长度在数据包内。也可以采用固定数据长度,通过寄存器指定;基带处理单元完成数据的自动解包、打包、自动回复 ACK 确认信号以及自动重发。该处理单元内部有 6 个通信管道,可以直接支持 1:6 星型网络。ARQ 包格式 一个完整的 ARQ 数据包包括前导码、地址、包控制字、负载数据以及 CRC。 前导码字段主要用于接收数据同步,发射时芯片自动附上,接收时芯片自动去掉,对用户不可见。 地址字段为接收数据方地址,只有当该地址与芯片的地址寄存器中地址相同时才会接收。地址长度可以通过配置寄存器 AW 配置为 3、或 4、或 5 字节。ARQ 通信模式 在 TX 模式下,发送端自动将前导码、地址、包控制字、负载数据、CRC 打包。通过射频模块将信号调制通过天线发射。在 RX 模式下,接收端在接收到的解调信号中不断侦测有效地址,一旦侦测到地址与接收地址相同,开始接收数据,如果接收到的数据有效,则将负载数据部分存放入 RX FIFO 中,并产生中断通知 MCU。MCU 通过 SPI 接口可随时访问RX FIFO 寄存器,进行数据读取。ACK 模式 当用 W_TX_PAYLOAD 命令对发送端 TX FIFO 写数据时,将数据打包后,数据包中包控制字段 NO_ACK 标志位复位。接收端接收到一帧有效数据后, 产生RX_DR 中断后,会自动发送一帧 ACK 信号,发送端接收到 ACK 信号,则自动清除 TX FIFO 数据并产生 TX_DS 发射中断,表明此次通信成功。接收端在发送 ACK 信号时,取接收管道地址作为目标地址来发送 ACK 信号,所以发送端需要设置接收管道 0 地址与自身发送地址相同,以便接收 ACK 信号。如果发送端在 ARD 时间内没有接收到 ACK 信号,则重新发送上一帧数据。当重发次数达到最大,仍没有收到确认信号时,发送端产生 MAX_RT 中断。MAX_RT 中断在清除之前不能进行下一步的数据发送。所有中断通过对状态寄存器进行写操作来清除。PLOS_CNT 寄存器在每产生一个 MAX_RT 中断后加 1,用来记录当前频段下,丢失的数据包的数量。ARC_CNT 寄存器记录当前数据重发的次数,在发送一包新数据时使其复位。最大重发次数与 ARD 时间通过SETUP_RETR 寄存器来进行配置。接收端开启自动回复 ACK 信号由 EN_AA 寄存器来控制。 模式一:ACK 通信//发射方配置: spi_rw_reg(SETUP_AW, 0x03); // 设置地址宽度为 5bytes spi_write_buf(TX_ADDR, TX_ADDRESS, 5); // 写入发送地址,5 字节 spi_write_buf(RX_ADDR_P0, TX_ADDRESS, 5); //接收通道 0 地址和发射地址相同 spi_write_buf(W_TX_PAYLOAD, buf, TX_PLOAD_WIDTH); // 写 TX FIFO spi_rw_reg(FEATURE, 0x04); //使能动态负载长度 spi_rw_reg(DYNPD, 0x01); //开启 DPL_P0 spi_rw_reg(SETUP_RETR, 0x15); //自动重发延时等待 500us,自动重发 5 次 spi_rw_reg(RF_CH, 0x40); // 选择射频信道 spi_rw_reg(RF_SETUP, 0x0e); // 数据传输率 2Mbps 及功率 spi_rw_reg(CONFIG, 0x0e); //配置为发射模式、CRC、可屏蔽中断 CE = 1; //接收方配置: spi_write_buf(RX_ADDR_P0, TX_ADDRESS, 5); //接收通道 0 地址和发射地址相同 spi_rw_reg(EN_RXADDR, 0x01); // 使能接收通道 0 spi_rw_reg(RF_CH, 0x40); // 选择射频信道 spi_rw_reg(RX_PW_P0, TX_PLOAD_WIDTH); //设置负载长度,使用 PIPE0 接收 spi_rw_reg(SETUP_AW, 0x03); // 设置地址宽度为 5bytes spi_rw_reg( FEATURE, 0x04); //使能动态负载 spi_rw_reg(DYNPD, 0x01); //开启 DPL_P0 spi_rw_reg(RF_SETUP, 0x0e); // 数据传输率 2Mbps 及功率 spi_rw_reg(CONFIG, 0x0f; //配置为发射模式、CRC、可屏蔽中断 CE = 1;AI写代码模式二:NOACK 通信//发射方配置: spi_write_buf( TX_ADDR, TX_ADDRESS, 5); // 写入发送地址 spi_rw_reg( FEATURE, 0x01); // 使能 W_TX_PAYLOAD_NOACK 命令 spi_write_buf(W_TX_PAYLOAD_NOACK, buf, TX_PLOAD_WIDTH); // 写 FIFO spi_rw_reg(SETUP_AW, 0x03); // 5 byte Address width spi_rw_reg( RF_CH, 0x40); // 选择射频通道 0x40 spi_rw_reg(RF_SETUP, 0x08); // 数据传输率 2Mbps spi_rw_reg( CONFIG, 0x0e); //配置为发射模式、CRC 为 2Bytes CE = 1; //接收方配置: spi_write_buf( RX_ADDR_P0, TX_ADDRESS, 5); // 接收地址 spi_rw_reg( EN_RXADDR, 0x01); // 使能接收通道 0 spi_rw_reg( RF_CH, 0x40); // 选择射频信道 spi_rw_reg( RX_PW_P0, TX_PLOAD_WIDTH); //设置接收通道 0 负载数据宽度 spi_rw_reg( RF_SETUP, 0x08); // 数据传输率 2Mbps,-18dbm TX power spi_rw_reg( CONFIG, 0x0f); // 配置为接收方、CRC 为 2Bytes CE = 1;AI写代码模式三:接收方开启多个通道//动态负载: spi_rw_reg(FEATURE, 0x04); spi_rw_reg(DYNPD, 0x3F) ; //开启所有通道动态负载长度 spi_rw_reg(EN_RXADDR, 0x3F); //开启所有通道 spi_rw_reg(RF_CH, 0x40); // 选择射频通道 0x40 spi_rw_reg(SETUP_AW, 0x03); // 5 byte Address width spi_rw_reg(CONFIG, 0x0B); //配置为接收方 CE = 1; //静态负载: spi_rw_reg(RX_PW_P0, 0x20); //设置通道 0 接收数据宽度 spi_rw_reg(RX_PW_P1, 0x20); spi_rw_reg(RX_PW_P2, 0x20); spi_rw_reg(RX_PW_P3, 0x20); spi_rw_reg(RX_PW_P4, 0x20); spi_rw_reg(RX_PW_P5, 0x20); spi_rw_reg(EN_RXADDR, 0x3F); //开启所有通道 spi_rw_reg(RF_CH, 0x40); // 选择射频通道 0x40 spi_rw_reg(SETUP_AW, 0x03); // 设置地址宽度 spi_rw_reg(CONFIG, 0x0F); //配置为接收方 CE = 1;

    2025-12-30 14:08

  • DP4390工作频段为 300 - 480 MHz 兼容CMT2220L开发资料

    DP4390 是一款低功耗、高性能、即插即用型 OOK 射频接收器,该芯片具有 2.5V - 5.5V 较宽的输入电压范围,灵敏度高达到-109dBm,工作频段为 300 - 480 MHz,支持 1 - 5 Kbps 的数据率传输。采用 SOP-8 封装类型,应用时仅需天线端阻抗匹配网络、VDD 退耦电容和 AGC 滤波电容,VDD 电路上无需增加防过冲电阻,从而降低应用成本。  频率范围:300 - 480 MHz  接收灵敏度:-109 dBm(1 Kbps)  数据率范围: 1 - 5 Kbps  电压范围:2.5V - 5.5V  低功耗:5.3 mA @ 3.3V(315 MHz)  SOP8 封装

    2025-12-30 14:07

  • 给烧录工程师的 checklist:新批次芯片上线前的“三道保险”

    前言: 各位产线的朋友,你们是否经历过这样的场景:产线一切就绪,新料盘上机,然后编程器就开始“噼里啪啦”报错,或者烧录顺利但测试大面积FAIL?问题往往就出在“新批次”这三个字上。今天不聊理论,直接分享我们车间总结的、可落地的新批次芯片上线检查清单。第一道保险:来料确认(IQC环节)核对标签与实物: 检查料盘标签上的完整型号、批次号(Lot Code)、日期码。取样读取ID: 随机抽取3-5颗芯片,使用离线编程器或在线烧录头的调试模式,读取其内部的唯一器件ID(如Silicon ID, Revision ID)。对比数据库: 将读取的ID与编程器软件支持的器件列表,或公司内部维护的“合格芯片ID清单”进行比对。重点看编程器软件中自动识别出的具体子型号/版本号是否与预期一致。 第二道保险:工程文件准备(工艺/NPI环节)更新烧录工程: 如果确认硅版本有变,立即在烧录工程配置中,明确选择对应的新版本型号,切勿使用“自动”或默认选项。执行对比烧录验证: 使用新旧两个版本的烧录工程文件(仅芯片型号版本不同),对同一颗新批次芯片进行烧录,并完整读出数据进行二进制比对。确保编程器使用的算法文件(Algorithm)和配置(如时钟、电压)已同步更新。小批量烧录与功能测试: 用更新后的工程文件,烧录10-20颗新批次芯片,制作成样板,进行完整的烧录后验证(Verify) 和核心功能测试,并与旧批次样板进行数据对比。 第三道保险:量产前哨战(试产环节)首件确认(FAI): 在正式量产线的第一个工位,烧录首件后,不直接流入下道工序。应由工艺或质检人员,使用独立的测试工装或仪器,对该首件板进行加严测试。过程监控: 试产初期,提高烧录成功率的监控频率,并关注烧录日志中是否有异常警告(如校验和微小差异、编程时间变化等)。文档更新: 所有验证通过后,将新的烧录工程文件、芯片批次信息、验证报告,同步更新至生产执行系统(MES)和标准化作业指导书(SOP)中。 结语:这三道保险,核心思想就一个——“慢就是快”。前期多花半小时验证,避免的是后面产线停线数小时的巨大损失。把不确定性挡在量产线之外,是我们价值的体现。你们车间有没有自己独特的“防呆”流程?或者对这份清单有什么补充?欢迎同行们一起交流,把我们的护城河筑得更牢!

    2025-12-30 14:00

  • bk3633 usb 设备如何读取主机向端点0 发送数据包

    bk3633 usb 设备如何读取主机向端点0 发送数据包

    2025-12-30 13:03

  • 核磁检测同步光调节治疗

    各位坛友好! 我们正在推进核磁(MRI)检测同步光调节治疗的项目,核心设备是 LED 阵列头帽+驱动控制板,目前卡在核磁兼容这一关键难题上。 需要实现的目标:设备既不干扰 MRI成像,又能在强磁场环境下稳定 工作,同时规避磁性材料、电磁辐射等安全隐患。 恳请有相关经验的大神指点思路或案例,方案若能落地,必有诚意答 谢。 细节可私信沟通,感谢!

    2025-12-30 11:01