jxr@localhost:~/ros2-projects$ sudo docker rm ros-container
Error response from daemon: No such container: ros-container
jxr@localhost:~/ros2-projects$ sudo docker rm ros-dev
Error response from daemon: cannot remove container "ros-dev": container is running: stop the container before removing or force remove
jxr@localhost:~/ros2-projects$ sudo docker rm ros-dev
Error response from daemon: cannot remove container "ros-dev": container is running: stop the container before removing or force remove
jxr@localhost:~/ros2-projects$

1.git log 一定要在想查看的文档的目录下,可查看修改日期 按q退出

2.windows + r 然后cmd,输入wsl就可以进入wsl系统

3.Linux 命令

windows + 空格   切换输入法 

根目录
cd /workspaces/ros2-develop 
用户目录
cd ~/workspaces/ros2-develop 

判断是否是可执行文件 输入ls 

绿色是可执行文件,白色是不可执行文件

colcon build 

#!/usr/bin/python3
###注意加了此前缀后,如果是可执行文件,该文件运行时有两种方法

print("hello world")


#一种是 python hello_world.py
#另一种是./hello_world.py 


终端运行
chmod a+x hello_world.py  
可以将该文件转为可执行文件


#终端运行
#chmod a+x hello_world.py  可以将该文件转为可执行文件
 

1.python 运行

python hello_world.py

2.c++ 运行

g++ hello_world.cpp
./a.out

1.printenv | grep AMENT

2.pwd--------------查看当前目录

3.ctrl + c 打断施法

can通信

这段代码是一个名为 LED_Control 的C语言函数,它的功能是根据一个8位的输入数据(一个字节)来控制8个LED灯的亮灭状态

我们来分模块逐行解析它。

1. 函数的定义

code C
downloadcontent_copy
expand_less
    void LED_Control(uint8_t data)
{
    // ... 函数体 ...
}
  
  • void LED_Control(...): 定义了一个函数,名字叫 LED_Control。void 表示这个函数执行完后不返回任何结果。

  • uint8_t data: 这是函数的输入参数。

    • uint8_t 是一种数据类型,表示一个8位的无符号整数(也就是一个字节,范围是 0 到 255)。

    • data 是这个参数的名字。

    • 核心思想: 这个 data 字节的8个位(bit)将分别对应8个LED灯。

2. 函数体:控制8个LED灯

函数体由8行相似的代码组成,每一行控制一个LED。我们以第一行为例来详细分析:

code C
downloadcontent_copy
expand_less
    //          端口    引脚号                                   引脚状态
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, ((data & 1) == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  

这一行代码做了三件事:

第一件事:选择要控制的引脚

  • HAL_GPIO_WritePin(...): 这是STM32 HAL库中用于控制GPIO(通用输入/输出)引脚电平的函数。

  • GPIOG: 指定了要操作的是 G端口

  • GPIO_PIN_1: 指定了要操作的是G端口的 1号引脚

第二件事:位运算(Bitwise Operation)

  • data & 1: 这是理解这段代码的关键,它是一个**按位与(AND)**运算。

    • 数字 1 的二进制是 0000 0001。

    • data & 1 的作用是只保留 data 这个字节的最低位(第0位),其他位全部清零。

    • 举例:

      • 如果 data 是 0101 0101,那么 data & 1 的结果是 0000 0001 (十进制的1)。

      • 如果 data 是 0101 0100,那么 data & 1 的结果是 0000 0000 (十进制的0)。

第三件事:三元运算符(Ternary Operator)

  • ((data & 1) == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET
    ((数据 & 1) == 0) ?GPIO_PIN_SET : GPIO_PIN_RESET

  • 这是一个紧凑的 if-else 语句,格式是: (条件) ? (条件为真时的值) : (条件为假时的值)。

  • 我们来分析这个逻辑:

    • 如果 data 的第0位是 0:

      • data & 1 的结果是 0。

      • 条件 (0 == 0) 为

      • 整个表达式的值为 GPIO_PIN_SET,引脚输出高电平。通常高电平会让LED灯熄灭

    • 如果 data 的第0位是 1:

      • data & 1 的结果是 1。

      • 条件 (1 == 0) 为

      • 整个表达式的值为 GPIO_PIN_RESET,引脚输出低电平。通常低电平会让LED灯点亮

结论: data 的第0位是 1,则1号引脚的LED亮;是 0,则灭。


3. 其他7行代码

后面的7行代码逻辑完全相同,只是检查的 data 的位和控制的引脚不同。

  • ((data & 2) == 0): 2 的二进制是 0000 0010,所以 data & 2 是在检查第1位,用来控制 2号引脚 的LED。

  • ((data & 4) == 0): 4 的二进制是 0000 0100,所以 data & 4 是在检查第2位,用来控制 3号引脚 的LED。

  • ...以此类推...

  • ((data & 128) == 0): 128 的二进制是 1000 0000,所以 data & 128 是在检查最高位(第7位),用来控制 8号引脚 的LED。

总结与应用场景

如果 data 的...那么它会控制...逻辑
第0位 (最低位)GPIO_PIN_11 = 亮, 0 = 灭
第1位GPIO_PIN_21 = 亮, 0 = 灭
第2位GPIO_PIN_31 = 亮, 0 = 灭
.........
第7位 (最高位)GPIO_PIN_81 = 亮, 0 = 灭

这个函数有什么用?

从你截图的左侧PPT标题“4 CAN通信的软件配置工程方式”和代码下方的HAL_CAN_RxFifo1MsgPendingCallback(CAN接收中断回调函数)可以推断出这个函数的应用场景:

  1. STM32的CAN总线接收到了一个数据包。

  2. 这个数据包里包含了一个字节的数据。

  3. 在CAN接收中断服务程序中,程序会提取出这个字节的数据。

  4. 然后调用 LED_Control() 函数,并将这个字节作为参数 data 传进去。

  5. 最终,8个LED灯的状态就会实时地显示出接收到的这个字节的二进制形式。

例如: 如果CAN总线收到的数据是 90(十六进制为0x5A,二进制为01011010),那么调用LED_Control(90)后,LED的亮灭状态会是:

灭-亮-灭-亮-亮-灭-亮-灭 (从第8个灯到第1个灯)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐