YuanHub 源码分析【五】速度模式举例通过 Mavlink 协议配置过

STM32F0 USART 常用配置,DMA不定长接收,pingpong接收,硬件流控制,过采样,接收超时中断和空闲中断 STM32F0 USART 通信 1.DMA不定长接收 2.硬件流控制 3.过采样率 4. 阅读详情

一、UART2 的初始化

1.1 MX_USART2_UART_Init()

使用 CubeMX 初始化 uart2:

int main(void)
{

  ...
  MX_USART2_UART_Init();
  ...

}
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 921600;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_RS485Ex_Init(&huart2, UART_DE_POLARITY_HIGH, 0, 0) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}
分类参数项目配置值功能说明

基础通信

波特率 (BaudRate)921600高速通信速率(921.6 kbps),适合传输大量或高频数据

数据位宽 (WordLength)8 Bits每帧包含 8 位有效数据,最常用的标准配置

停止位 (StopBits)1 Bit帧结尾使用 1 个停止位标识数据结束

校验位 (Parity)无校验 (None)不添加奇偶校验位,节省带宽

工作模式 (Mode)收发使能 (TX_RX)同时开启发送 (TX) 和接收 (RX) 功能

时钟与采样

时钟分频 (ClockPrescaler)不分频 (DIV1)串口内核外设时钟等于系统分配的基础时钟频率

过采样率 (OverSampling)16 倍 (16)16倍过采样(相对8倍而言),对时钟偏差容忍度更高,接收更稳定

时钟与采样

单比特采样 (OneBitSampling)禁用 (Disable)采用多数投票机制(对中间3个采样点取多数)判定电平,抗噪能力更强

高级控制

硬件流控 (HwFlowCtl)无 (None)不使用 RTS/CTS 硬件流控引脚

RS-485模式

RS485 驱动使能 (DE)开启使用 HAL_RS485Ex_Init,通过硬件自动控制发送使能(DE)引脚方向

DE 极性 (DE Polarity)高电平 (High)极性为高电平有效(发送时拉高 DE 引脚,接收时自动拉低)

FIFO 控制

FIFO 模式禁用 (Disable)关闭了硬件 FIFO 功能(注:代码中虽配置了1/8阈值,但紧接着被 DisableFifoMode 禁用了)

在别的地方为 uart2 开启了 DMA 中断: 

    // 启动调试软件通讯
    __HAL_UART_CLEAR_IDLEFLAG(&HOST_UART_HANDLE);
    HAL_UART_Receive_DMA(&HOST_UART_HANDLE, mavlink_rx_buff, MAVLINK_RECV_BUFF_SIZE);
    __HAL_UART_ENABLE_IT(&HOST_UART_HANDLE, UART_IT_IDLE);

二、解析 Mavlink 协议

2.1 串口中断函数

uart2 宏定义:

#define HOST_UART_IRQ_TASK          USART2_IRQHandler

下面为 uart2 中断,没什么好说的:

/**
 * @brief 上位机通讯UART中断任务
 * 该函数用于处理UART中断事件,主要用于处理IDLE空闲中断
 * 当检测到UART空闲状态时,会停止DMA传输,处理接收到的数据,然后重新启动DMA接收
 */
void HOST_UART_IRQ_TASK(void)
{
    HAL_UART_IRQHandler(&HOST_UART_HANDLE); // 调用HAL库的UART中断处理函数

    if (__HAL_UART_GET_FLAG(&HOST_UART_HANDLE, UART_FLAG_IDLE))
    {
        __HAL_UART_CLEAR_IDLEFLAG(&HOST_UART_HANDLE);

        HAL_UART_DMAStop(&HOST_UART_HANDLE);

        // 调用Mavlink数据接收回调函数,处理接收到的数据
        // 参数为接收缓冲区和实际接收到的数据长度
#ifndef USE_CAN_MAVLINK_HOST
        MavlinkRecvCallback(&kAxis, &kAxisDw, mavlink_rx_buff, MAVLINK_RECV_BUFF_SIZE - __HAL_DMA_GET_COUNTER(HOST_UART_HANDLE.hdmarx));
#endif /* USE_CAN_MAVLINK_HOST */
        // 重新启动DMA接收,准备接收下一批数据
        HAL_UART_Receive_DMA(&HOST_UART_HANDLE, mavlink_rx_buff, MAVLINK_RECV_BUFF_SIZE);
    }

    // 及时检查溢出错误(ORE),清除错误标志并重新启动DMA接收
    if (__HAL_UART_GET_FLAG(&HOST_UART_HANDLE, UART_FLAG_ORE))
    {
        __HAL_UART_CLEAR_FLAG(&HOST_UART_HANDLE, UART_FLAG_ORE);
        HAL_UART_DMAStop(&HOST_UART_HANDLE);
        HAL_UART_Receive_DMA(&HOST_UART_HANDLE, mavlink_rx_buff, MAVLINK_RECV_BUFF_SIZE);
    }
}

2.2 Mavlink 解析函数

进入 MavlinkRecvCallback 解析的状态机:

void MavlinkRecvCallback(Axis *axis, AxisDw *axis_dw, uint8_t rx_data[], uint32_t len)
{
    // 逐字节送入 MAVLink 状态机解析
    for (int i = 0; i < len; i++) {
        if (mavlink_parse_char(MAVLINK_COMM_0, rx_data[i], &msg, &status)) {
            mavlink_flag = 1;
            break;
        }
    }
    ...
}

mavlink_parse_char() 是 MAVLink 协议栈的标准函数,它维护一个内部状态机,逐字节处理:

当一帧完整消息解析成功后,返回成功,msg 结构体中包含了 msgid 和 payload。

if (msg.msgid == MAVLINK_MSG_ID_READ_PARAM) {
    // ★ 读请求:根据 struct_id 读取对应数据并回传
    mavlink_msg_read_param_decode(&msg, &read_param);
    switch (read_param.struct_id) {
        case MAVLINK_MSG_ID_AppControlWord:
            // 打包当前控制字回传
            ...
        case MAVLINK_MSG_ID_AppMotionParam:
            // 打包当前运动参数回传
            ...
    }
} else {
    // ★ 写请求:根据 msgid 解码数据并写入对应参数
    switch (msg.msgid) {
        case MAVLINK_MSG_ID_AppControlWord:   // 写控制字
        case MAVLINK_MSG_ID_AppOpMode:        // 写运行模式
        case MAVLINK_MSG_ID_AppMotionParam:   // 写运动参数
        case MAVLINK_MSG_ID_PosSpeedCtlConfig:// 写位置速度环配置
        ...
    }
}

三、速度模式的三个配置函数

3.1 概述

上位机通过 Mavlink 协议发送速度模式命令在 MavlinkRecvCallback() 中会触发三个

3.2 set_app_Modes_of_operation()

set_app_Modes_of_operation() 函数的作用是给系统切换各种模式,如从位置模式切换到速度模式。

在 MavlinkRecvCallback() 函数中这里调用:

case MAVLINK_MSG_ID_AppOpMode:
    mavlink_msg_appopmode_decode(&msg, (mavlink_appopmode_t *)&app_op_mode_t);
    if(get_app_Comm_control_authority() == COMM_CONTROL_HOST)    {set_app_Modes_of_operation(app_op_mode_t.Modes_of_operation);}
    app_op_mode_t.Modes_of_operation = get_app_Modes_of_operation();
    mavlink_msg_appopmode_encode(sys_id, comp_id, &send_msg, (mavlink_appopmode_t     *)&app_op_mode_t);
 break;

set_app_Modes_of_operation() 函数内部结构:

uint32_t set_app_Modes_of_operation(int8_t val)
{
    /* USER CODE BEGIN set_app_Modes_of_operation 0 */
    if (val == get_app_Modes_of_operation_display())
    {
        return APP_PARAM_SUCCESS;
    }
    /* USER CODE END set_app_Modes_of_operation 0 */
    kAppOpMode.Modes_of_operation = val;
    /* USER CODE BEGIN set_app_Modes_of_operation 1 */
    if (callback_registry.set_app_callback == NULL)
    {
        return APP_PARAM_OUT_OF_RANGE;
    }
    switch (kAppOpMode.Modes_of_operation)
    {
    case MOTOR_CTL_SM_MODE_POSITION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_POSITION;
        callback_registry.set_app_callback(APP_PP_MODE);
        break;
    case MOTOR_CTL_SM_MODE_SPEED:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_SPEED;
        callback_registry.set_app_callback(APP_PV_MODE);
        break;
    case MOTOR_CTL_SM_MODE_TORQUE:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_TORQUE;
        callback_registry.set_app_callback(APP_PT_MODE);
        break;
    case MOTOR_CTL_SM_MODE_MIT:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_MIT;
        callback_registry.set_app_callback(APP_MIT_MODE);
        break;
    case MOTOR_CTL_SM_MODE_HOMING: // 回零模式实际使用速度模式
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_SPEED;
        callback_registry.set_app_callback(APP_HM_MODE);
        break;
    case MOTOR_CTL_SM_MODE_CSP:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_POSITION;
        callback_registry.set_app_callback(APP_CSP_MODE);
        break;
    case MOTOR_CTL_SM_MODE_CSV:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_SPEED;
        callback_registry.set_app_callback(APP_CSV_MODE);
        break;
    case MOTOR_CTL_SM_MODE_CST:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_TORQUE;
        callback_registry.set_app_callback(APP_CST_MODE);
        break;
    case MOTOR_CTL_SM_MODE_DIRECTION_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_DIRECTION_IDENTIFICATION;
        callback_registry.set_app_callback(APP_DIR_ID_MODE);
        break;
    case MOTOR_CTL_SM_MODE_ELECTRIC_ANGLE_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_ELECTRIC_ANGLE_IDENTIFICATION;
        callback_registry.set_app_callback(APP_ELEC_ANGLE_ID_MODE);
        break;
    case MOTOR_CTL_SM_MODE_ELECTRIC_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_ELECTRIC_IDENTIFICATION;
        callback_registry.set_app_callback(APP_ELEC_ID_MODE);
        break;
    case MOTOR_CTL_SM_MODE_MECHANICAL_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_MECHANICAL_IDENTIFICATION;
        callback_registry.set_app_callback(APP_MEC_ID_MODE);
        break;
    case MOTOR_CTL_SM_MODE_POLE_PAIRS_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_POLE_PAIRS_IDENTIFICATION;
        callback_registry.set_app_callback(APP_POLE_PAIRS_ID_MODE);
        break;
    case MOTOR_CTL_SM_MODE_TQ_FRICTION_IDENTIFICATION:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_TQ_FRICTION_IDENTIFICATION;
        callback_registry.set_app_callback(APP_TQ_FC_ID_MODE);
        break;
    default:
        axis->motor_ctl_sm_config.mode = MOTOR_CTL_SM_MODE_IDLE;
        break;
    }
    /* USER CODE END set_app_Modes_of_operation 1 */
    return APP_PARAM_SUCCESS;
}

3.3 set_app_Target_velocity()

set_app_Target_velocity() 函数的作用是设置并更新电机的目标速度值。它接收上位机 (通过 MAVLink) 发送过来的目标速度值。在 Profile Velocity (PV) 速度模式下,这个值代表了电机最终希望达到的稳定转速。

在 MavlinkRecvCallback() 函数中这里调用:

case MAVLINK_MSG_ID_AppMotionParam:
...
{set_app_Target_velocity(app_motion_param_t.Target_velocity);}
...
break;

set_app_Target_velocity() 函数内部结构:

uint32_t set_app_Target_velocity(float val)
{
    /* USER CODE BEGIN set_app_Target_velocity 0 */
    if (MATH_ABS(val) > kAppRestrictParam.Max_profile_velocity)
    {
        return APP_PARAM_OUT_OF_RANGE;
    }

    /* USER CODE END set_app_Target_velocity 0 */
    kAppMotionParam.Target_velocity = val;
    /* USER CODE BEGIN set_app_Target_velocity 1 */
    /* USER CODE END set_app_Target_velocity 1 */
    return APP_PARAM_SUCCESS;
}

3.4 set_app_Controlword()

set_app_Controlword() 是控制电机的函数。上位机的所有动作意图(启动、停止、复位、急停)都必须编码成这个 16 位的数值,通过此函数注入系统,进而影响 PDS_FSA_Run() 状态机的走向。

在 MavlinkRecvCallback() 函数中这里调用:

case MAVLINK_MSG_ID_AppControlWord:
    mavlink_msg_appcontrolword_decode(&msg, (mavlink_appcontrolword_t *)&app_control_word_t);
    if(get_app_Comm_control_authority() == COMM_CONTROL_HOST)    {set_app_Controlword(app_control_word_t.Controlword);}
    app_control_word_t.Controlword = get_app_Controlword();
    if(get_app_Comm_control_authority() == COMM_CONTROL_HOST)    {set_app_Halt_running_cmd(app_control_word_t.Halt_running_cmd);}
    app_control_word_t.Halt_running_cmd = get_app_Halt_running_cmd();
    mavlink_msg_appcontrolword_encode(sys_id, comp_id, &send_msg, (mavlink_appcontrolword_t *)&app_control_word_t);
break;

set_app_Controlword() 函数内部结构:

uint32_t set_app_Controlword(uint16_t val)
{
    if (val < 0)
        return APP_PARAM_OUT_OF_RANGE;
    if (val > 3)
        return APP_PARAM_OUT_OF_RANGE;

    /* USER CODE BEGIN set_app_Controlword 0 */
    // 切换到控制层控制后,应用层控制字不再生效
    if (get_app_Internal_control_authority() == INTERNAL_CONTROL_CTRL)
    {
        return APP_PARAM_READ_ONLY;
    }
    /* USER CODE END set_app_Controlword 0 */
    kAppControlWord.Controlword = val;
    /* USER CODE BEGIN set_app_Controlword 1 */
    axis->motor_ctl_sm_input.motor_enable = val;
    /* USER CODE END set_app_Controlword 1 */
    return APP_PARAM_SUCCESS;
}

stm32f429-discovery +cubemx + USB转虚拟串口 研究 小玩stm32f429 cubemx VCP 阅读详情

相关推荐

情系淮思:五款车规MCU横向对比与VCU选型

本文对比五款车规MCU中的S32K312与S32K324,聚焦核心架构、存储、通信及安全特性。S32K324为双核160MHz Cortex-M7,内存、外设(如以太网、QuadSPI、SAI)全面升级,支持高实时并行处理与复杂应用;而S32K312为单核120MHz,适用于中端车身控制。两者均满足ASIL B功能安全,具备完整安全引擎。选型建议:中端用S32K312,高端复杂系统优选S32K324。

本不平凡 312

CUBEMX配置RS485

使用Cube配置RS485的一些体验

lue_app的博客 1217

GD32F130之USART自带的RS485方向切换功能

关于RS485收发器的基本使用 在使用单片机实现串口RS485通信时,需要外接一个TTL转RS485的收发器芯片,例如SP3485和MAX3485。由于RS485使用的是单数据通道,差分信号传输方式,所以是半双工通信,即收发不能同时进行。 那么就需要用一个信号控制RS485的收发器芯片的数据传输方向。 拿SP3485举例:此芯片内部由接收器(receiver)和发送器(或者叫驱动器,driver)组成。如下图所示。RE引脚控制接收器的使能,低电平时使能接收器;DE引脚控制发送器的使能,高电平时使能发送器

luliplus的博客 9109

STM32F10x uart初始化以及寄存器说明

USART(Universal Synchronous Asynchronous Receiver Transmitter) 也就是通用同步异步收发。它根据NRZ非同步串行数据工业标准,提供了灵活的全双工数据交换功能。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及硬件控制操作(需要增加两个管脚,分别是CTS/RTS)。

hong 3353

21 硬件工程师笔面试高频考点真题解析——单片机

本文系统介绍了单片机的核心概念与应用知识,包括:单片机定义与选型要点(性能、存储、外设等);核心参数(主频、I/O、通信接口等);最小系统组成(电源、复位、晶振、BOOT);常见外设(GPIO、ADC、定时器等);GPIO工作模式(输入/输出);死机原因分析(硬件干扰、软件错误等);上电故障排查流程(电源、时钟、程序等);与DSP、FPGA的对比(控制vs运算vs可编程);常用通信总线特点(UART、I2C、SPI、CAN);看门狗功能(超时复位防死机)。内容涵盖单片机硬件设计关键要点,适合嵌入式开发者参考

XU157303764的博客 1314

NV MCU与SoC的交互

MCU通过IST_REQ信号触发SoC执行IST,由IST_DONE_N通知完成,SOC_RESET_N由MCU控制。MCU与SoC间通过通信通道(如以太网)传输IST结果。热/电压监测通过I2C实现,阈值由MCU初始设置、SoC动态更新,异常可中止IST。客户应用可在检测严重错误时通过IST管理器中止IST,相关原因与状态将被记录。

liu-yonggang的专栏 55

__HAL_TIM_SET_CAPTUREPOLARITY的巨坑

本人在写输入捕获实验的时候使用HAL库中的函数__HAL_TIM_SET_CAPTUREPOLARITY试图切换捕获极性,keil一直报错error: expected ‘:’ error: expected expression。原以为__HAL_TIM_SET_CAPTUREPOLARITY没有函数实体,但是又发现在stm32f1xx_hal_tim.h中这是个宏定义。于是乎发现TIM_RE...

老白 5833

【TensorRT】TensorRT C# API 项目介绍:基于C#与TensorRT部署深度学习模型(上篇)

开发了TensorRT C# API 2.0版本,该版本在开发时充分考虑了上一版本应用时出现的问题,并进行了改进。同时在本版本中,我们对接口进行了优化,使用起来更加简单,并同时提供了相关的应用案例,方便开发者进行使用。

grape_yan的博客 3039

基本定时器(TIM6/TIM7)

基本定时器最简单,就干一件事:到点了触发中断。定时器本质就是计数器,每个时钟脉冲加1,数到ARR就溢出、产生中断、清0重来。三个核心寄存器:PSC(预分频器):对输入时钟分频CNT(计数器):从0往上数ARR(自动重装载值):数到这个值就溢出,CNT清0,产生更新中断公式:  定时周期 = (PSC+1) × (ARR+1) / 定时器时钟  更新事件频率 = 定时器时钟 / ((PSC+1) × (ARR+1)) 例:TIM6时钟84MHz,要定时0.5秒(2

2401_89890233的博客 260

SAP HR模块配置假期日历和缺勤类型

SAP的HR模块。业务顾问在实施时一般会配置未来10年的假期日历,到期后再进行配置。同时,增加请假类型(缺勤信息类型)。记录这一过程。

福来阁86号技师的妖孽日常 5525

从空调温控到信号降噪:一阶RC低通滤波器在Arduino和STM32上的C语言实现指南

本文详细介绍了如何在Arduino和STM32平台上使用C语言实现一阶RC低通滤波器,涵盖从基础理论到实际应用的完整流程。通过具体代码示例和优化技巧,帮助开发者有效处理传感器噪声、信号平滑等问题,提升嵌入式系统的信号处理能力。

weixin_30565199的博客 502

7-2 按键控制LED流水灯(SDCC + Notepad++ + STC-ISP/普中ISP)

本节基于上节定时器T0设计,实现按键控制LED流水灯。通过配置12MHz晶振下16位定时器模式,初值设为64536(0xFC18),每1毫秒溢出一次,替代原有Delay方法。启用定时器中断,设置TR0启动,TF0标志自动置位触发中断,配合外部按键控制流水灯状态,提升系统实时性与效率。

xunyan6234的博客 81

Ollama内网离线部署大模型实战:从模型文件到私有化服务

本文详细介绍了如何在内网离线环境下,利用Ollama部署私有化大模型服务。内容涵盖从获取GGUF格式模型文件、手动安装Ollama、编写核心Modelfile配置文件,到创建运行模型、性能调优及安全加固的全流程实战指南,旨在帮助企业安全、可控地构建内部AI能力。

weixin_29209805的博客 215

TMS320F28335 学习笔记(二):系统时钟、PLL 与看门狗

本文系统介绍F28335的时钟架构与看门狗应用,涵盖外部晶振、PLL倍频生成系统时钟(SYSCLKOUT)、高速/低速外设时钟分频配置,以及看门狗的启用、关闭与喂狗机制。强调时钟配置准确性对延时、PWM、通信等外设的重要性,指出常见错误如晶振不匹配、未等待PLL锁定、随意修改PLL或喂狗周期过长等问题,并提供初始化框架与验证方法,帮助开发者正确配置时钟系统,确保程序稳定运行。

2403_83044722的博客 367

Jev模型入门:从API接入到本地部署的完整实践指南

大模型的应用方式正从单一聊天窗口转向复杂的自动化工作流,而推理模型因具备指令跟随与结构化输出能力,成为构建Agent和数据处理管线的关键组件。Jev作为面向通用场景的推理模型,不仅提供了OpenAI兼容的API接口,还支持本地量化部署,兼顾隐私、可控性与长期成本。本文从模型定位出发,明确Jev与基座模型的差异,随后介绍密钥管理、API调用、参数调优,并深入演示基于Ollama与llama.cpp的本地部署流程,包括GGUF模型文件与chat template的匹配要点。针对实践中的常见问题,如密钥泄露、ma

weixin_29057237的博客 359

【Dify】PPT生成工具应用

本文介绍了一款自动化PPT生成工具,通过智能接口将文本内容高效转化为结构化演示文档。该系统采用三阶段工作流(内容输入、HTTP请求上传、文件输出),无需复杂操作即可生成专业PPT。工具适用于教学课件、产品发布、企业培训等场景,能显著提升内容表达效率,特别适合初学者快速制作演示材料。文章详细说明了核心节点、应用场景及开发资源,为文本到PPT的自动化转换提供了实用解决方案。

Mr数据杨 1218

代码小白笔记:江科大 51 单片机 LCD1602 课程详解

本文为单片机新手梳理江科大51课程中LCD1602的驱动逻辑,聚焦“看懂代码”而非深究寄存器。通过解析接线、底层函数(延时、写命令/数据)、初始化流程及光标定位,详解字符、字符串、数字(十进制、十六进制、二进制)的显示原理,核心在于理解“RS控制指令/数据”、“地址映射规则”及“数字转字符”的位运算技巧,帮助读者快速上手并自定义显示内容。

2301_81429079的博客 338

华为OD面试手撕真题 - 最大数

华为OD面试手撕真题 最大的数 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 343

MCU 启动流程解析:从 SRAM 到 DDR

MCU 的性能瓶颈通常不在 DDR 带宽,而在访问延迟与确定性。因此,关键代码、中断向量、栈以及功能安全数据应放在片内 SRAM;大块传感器数据缓冲、堆和冷数据则放在 DDR。启动流程的核心可以概括为三步:Boot ROM 搬运、Remap 切换、SRAM 执行。

Where there is life, there is hope. 290

Python从0到100(二):Python语言介绍及第一个Pyhon程序

Python从0到100(二):Python语言介绍及第一个Pyhon程序。与C和Java比,Python的学习成本和难度曲线不是低一点,更适合新手入门,自底向上的技术攀爬路线。

拥有百余位万粉技术博主、200余位可合作代发博主,私域技术社群规模达千人,商务合作私信 5440

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

XZ6273H 100V低功耗高压LDO硬件设计与实测体验

这款LDO提供SOT23-3、SOT89-3和TO92三种通用封装,不同场景下可以灵活选择:做小型化的PCB节点时用SOT23-3,板卡面积能控制得非常小;常规工业板卡选SOT89-3,贴片焊接方便,自带的焊盘也能提供基础散热能力;从实际落地的情况来看,它最适配两类场景:一类是汽车电子里的休眠值守子模块,车辆熄火后仍能保持极低的待机功耗,不会过度消耗电瓶电量;另一类是户外无人值守的通信远端节点,长期运行下的低功耗表现能大幅降低设备的供电维护成本。

koce13544100678的博客 231

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

MCU的ADC采样怎么配

一块采集板,室温下读电池电压挺准,一上高低温箱就差出0.3V。软件反复查了三遍,没改一行代码,最后发现是参考电压选错了——电源纹波直接灌进了测量基准。ADC这东西,代码就那么几行,坑全在配置里。这篇拿ATmega16当例子,把采样链路从头讲清:参考电压怎么选、时钟为什么卡在50到200kHz、结果为什么要讲究读取顺序。这些规则不只对AVR成立,换成车规MCU,思路一样。

qq_43241255的博客 194

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

HAL库基本定时器框架分析

这部分是在main.c里面调用的,使能定时器外设和中断位。实时真正干活的操作在中断处理函数里进行。流程1 定时器外设初始化和中断配置。流程2 使能定时器中断相关位。流程3 中断处理函数。

tecoes的博客 22

PHY内部环回通过,能证明网口整条链路正常吗?

PHY内部环回通过,只能证明该测试路径在记录条件下工作正常,不能直接证明变压器、RJ45、网线和对端组成的整条链路正常。采购收到“环回合格”报告时,应先确认数据从哪里发出、在哪里折返、又在哪里检查。

Voohu_Elsa的博客 189

从FT 93k测试机角度看如何测试芯片的VOH/VOL/VIH/VIL,通俗易懂的方式介绍

FT 93k测试中,VIH/VIL与VOH/VOL的核心是验证芯片“听清”与“说清”的能力。VIH/VIL测试芯片输入灵敏度,通过施加边界电压并观察功能响应;VOH/VOL则在负载下测量输出电平,模拟真实工作状态。测试需严格遵循规格书的负载电流条件,确保信号可靠传输,避免灰色地带干扰。本质是精准复现测试条件,实现“听话的对话者”与“挑剔的听众”的双重角色。

Wang20122013的博客 227

Arduino-MEGA-ESP单片机理论课笔记-06温湿度-07时间-延时定时-2026

本文解析了DHT11温湿度传感器的Arduino代码,逐行讲解了库引入、引脚定义、传感器初始化及数据读取流程。重点说明了delay(1000)导致阻塞的问题,并提出使用millis()实现非阻塞定时,将采样间隔改为2秒,提升程序响应性。同时建议增加isnan()错误检测、优化串口输出格式,确保数据稳定可靠。

zhangrelay的专栏 363
上一篇: YuanHub 源码分析【二】全局变量与调试
下一篇: YuanHub 源码分析【四】位置速度
崔佳宇_
崔佳宇_ 优质创作者: 嵌入式与硬件开发技术领域 优质创作者: 嵌入式与硬件开发技术领域
博客等级 码龄10年 1万+粉丝 173原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值