标签: i2c

stm32f4 上的 I2C 从接收器

我尝试在 stm32f4 上实现 i2c 从接收器中断服务例程。这是我的智能代码。

void I2C2_EV_IRQHandler()
  {
    switch (I2C_GetLastEvent(I2C2))
    {
    //The address sent by the master matches the own address of the peripheral
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
        //The slave stretches SCL low until ADDR is
        //cleared and DR filled with the data to be sent
        I2C_ClearFlag(I2C2,I2C_FLAG_ADDR);
        break;

    //The application is expecting a data byte to be received
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
        I2C_ReceiveData(I2C2);
        break;

    //The application is expecting the end of the communication
    //Make sure that both ADDR and STOPF flags are cleared
    //if …
Run Code Online (Sandbox Code Playgroud)

embedded stm32 i2c interrupt-handling slave

5
推荐指数
1
解决办法
2万
查看次数

最佳常见做法 I2C 寄存器映射

只是想知道关于 C 中 I²C 寄存器映射的最佳实践是什么,或者其他人经常/更喜欢使用什么。

到目前为止,我通常做了很多定义,一个用于每个寄存器,一个用于所有位、掩码、移位等。然而,最近我看到一些驱动程序使用(可能是打包的)结构而不是定义。我认为这些是 Linux 内核模块。

反正他们会

struct i2c_sensor_fuu_registers {

    uint8_t  id;
    uint16_t big_register;
    uint8_t  another_register;
    ...

} __attribute__((packed));
Run Code Online (Sandbox Code Playgroud)

然后他们会使用 offsetof(或宏)来获取 i2c 寄存器并使用 sizeof 来读取要读取的字节数。

我发现这两种方法都有其优点:

结构方法:

  • (+) 寄存器偏移量都在逻辑上包含在结构中,而不必在定义中拼写每个寄存器。
  • (+) 条目大小使用适当大小的数据类型明确说明。
  • (-) 这不包括广泛使用的位域
  • (-) 这不考虑非字节映射的寄存器映射(例如 LM75),其中从偏移 n+0x00 读取 2 个字节,但 n+0x01 是另一个寄存器,而不是寄存器 n 的高/低字节+0x00
  • (-) 这并没有考虑到地址空间中的大间隙(例如 0x00、0x01、0x80、0xAA 处的寄存器,没有中间......)并且(我认为?)依赖编译器优化来摆脱结构.

定义方法:

  • (+) 每个寄存器及其位通常定义在一个块中,这使得找到正确的符号变得容易并依赖于命名约定。
  • (+) 透明/不知道地址空间差距。
  • (-) 每个寄存器都必须单独定义,即使没有间隙
  • (-) 因为定义往往是全局的,所以名称通常很长,用几十个长符号名称在源代码中有点乱七八糟。
  • (-) 要读取的数据大小通常是硬编码的幻数或 (end - start + 1) 样式计算,符号名称可能很长。
  • (o) 透明/不知道地图中的数据大小与地址。

基本上,我正在寻找一种更智能的方法来处理这些情况。我经常发现自己为每个寄存器和每个位键入了大量令人痛苦的长符号名称,还可能还有掩码和移位(后两个取决于数据类型),结果只使用其中的几个(但讨厌稍后重新定义丢失的符号,这就是我在一个会话中输入所有内容的原因)。不过,我注意到要读/写的字节大小大多是幻数,通常需要并排阅读数据表和源代码才能理解最基本的交互。

我想知道其他人如何处理这些情况?我在网上找到了一些例子,其中人们还在大标题中费力地输入每个寄存器、位等,但没有什么是确定的......但是,在这一点上,上述两个选项似乎都不太聪明:(

c i2c

5
推荐指数
1
解决办法
3162
查看次数

在 Raspberry Pi 上使用 Python smbus - 与语法混淆

我正在尝试在 Raspberry Pi 上使用 python-smbus 使用 I2C 与 MMA7660 加速度计芯片进行通信。

在下面的代码中,我正在读取芯片的寄存器 0x​​00、0x01、0x02 和 0x03,并且我得到的值完全相同。查看这些值,并倾斜芯片,我可以看到它们都对应于寄存器 0x​​00,即 X 值寄存器。

输出:

...
1 1 1 2
3 3 3 3
1 1 1 1
59 60 60 60
51 51 51 51
58 58 58 58
3 3 3 3
62 62 62 62
58 58 58 58
62 62 62 62
...
Run Code Online (Sandbox Code Playgroud)

代码:

  import smbus
  import time

  bus = smbus.SMBus(1)
  # I2C address for MMA7660                                                     
  addr = 0x4C
  try:
    bus.write_byte_data(addr, 0x07, 0x00) …
Run Code Online (Sandbox Code Playgroud)

python i2c raspberry-pi

5
推荐指数
1
解决办法
7万
查看次数

无硬件 I2C 驱动程序的单元测试 - 如何解释从机的正确值?

我有一个 i2c 驱动程序写入 i2c 总线:

  • 从机(温度传感器)的寄存器地址

  • 必须写入该地址的值

我还对该值进行检查(读回)以确保它是正确的。硬件上一切正常。我在循环环境和单元测试中使用软件,这样我就可以在没有硬件的情况下执行我的代码。为了能够从寄存器读回值,我必须“模拟”数据接收寄存器的内容(从 I2C 从机读回的值)。

因为,我对低级编程不是很有经验,知道在我的情况下如何做到这一点吗?

这是代码片段:

typedef struct
   uint8      address;    // The register address of the slave
   uint8      value;      //The value which have to be writte into the   register 
} MessageStruct;

MessageStruct *pMessage
uint8 Readback = 0;

Write_Toc_I2C( pMessage->address, pMessage->value );   // Function which writes to ic2 bus. For definition see below.

Readback = Read_From_I2c( pMessage->address);         // I store the read back value in a variable Readback. Declaration of Read_From_I2c() below

 if( Readback == …
Run Code Online (Sandbox Code Playgroud)

hardware unit-testing mocking i2c

5
推荐指数
0
解决办法
1113
查看次数

RPI 上的 SMBUS 给出 IOError: [Errno 121] 远程 I/O 错误

我尝试过通过 I2C 在 RPi3 和 stm32 之间进行通信。首先我安装了 i2c-tools 和 python-smbus。总而言之,我在 RPI 上使用了 python 脚本,如下所示:

import smbus
bus = smbus.SMBus(1)
address = 0x0A
data = [1,2,3,4,5,6,7,8]
bus.write_i2c_block_data(address, 0, data)
Run Code Online (Sandbox Code Playgroud)

当我运行脚本时,我可以看到以下错误:

IOError: [Errno 121] Remote I/O error
Run Code Online (Sandbox Code Playgroud)

STM32 配置为 I2C 从机,两个设备连接正确(SDA、SCL 和 GND)。我怎么知道呢?我使用 BCM2835 库编写了程序。C 程序运行正常。C 程序发送缓冲区没有任何错误。STM32也接收到缓冲区,没有任何错误。你能告诉我,我做错了什么吗?

先感谢您。

i2c raspberry-pi3 smbus

5
推荐指数
1
解决办法
3万
查看次数

i2cset 16位寄存器地址

我有一个设备通过 i2c 协议进行通信。设备的寄存器地址是16位,但Linux i2c-tools仅支持8位地址。但我找到了一些东西来处理它。

例如,要读取地址为0x0006的寄存器,我使用以下方法:(假设为busId0并且设备i2c地址为0x48)

i2cset -y 0 0x48 0x00 0x06 # this command sets the register address to 0x0006
i2cget -y 0 0x48 # this command the value 0xBA which is true
Run Code Online (Sandbox Code Playgroud)

当我再次调用该i2cget -y 0 0x48命令时,它返回下一个地址处的值。

写入操作按我的预期进行。但是当我尝试写入同一个寄存器时,我失败了。我尝试以下命令:

i2cset -y 0 0x48 0x00 0x06 0xBA 0x0B i
Run Code Online (Sandbox Code Playgroud)

此命令不会返回错误。但是当我再次读取寄存器时,我看到寄存器没有变化。

我使用的设备是AP0100CS。寄存器地址可写。我不知道 i2cset 有什么问题。

linux i2c

5
推荐指数
0
解决办法
4259
查看次数

STM32F4 I2C 与 DMA 不工作

我正在使用一台 STM32F4,我想与我的 LSM303 加速度计进行通信。为此,我使用 I2C,仅使用 I2C 工作正常,但当我尝试使用 DMA 时,它停止工作。当我使用 HAL_I2C_Master_Transmit_DMA 时,它可以工作,并且我得到了 IRQHandler 和 . 但是之后当我想使用 HAL_I2C_Master_Receive_DMA 时,它说 I2C 的状态尚未准备好...我读到 I2C 与 STM32FX 有点混乱,但我不明白为什么它在没有 DMA 的情况下工作正常。

此外,当它命中 Master_Transmit_DMA 的回调 I2C_DMAXferCplt 时,它表示 I2C_HandleTypeDef 的 CurrentState 仍然等于 HAL_I2C_STATE_BUSY_TX,因此它不会将状态恢复为 READY。这就是为什么当我调用 Master_Receive_DMA 时它没有收到任何东西。

这是我的 I2C 初始化:

    void MX_I2C2_Init(void)
      {
          I2C_ST_INS.Instance = I2C2;
          I2C_ST_INS.Init.ClockSpeed = 400000;
           I2C_ST_INS.Init.DutyCycle = I2C_DUTYCYCLE_2;
           I2C_ST_INS.Init.OwnAddress1 = 0;
          I2C_ST_INS.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
          I2C_ST_INS.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
          I2C_ST_INS.Init.OwnAddress2 = 0;
          I2C_ST_INS.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
          I2C_ST_INS.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

          HAL_I2C_Init(&I2C_ST_INS);

        }

   void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
   {
          GPIO_InitTypeDef GPIO_InitStruct;
          if(i2cHandle->Instance==I2C1) …
Run Code Online (Sandbox Code Playgroud)

stm32 i2c dma

5
推荐指数
2
解决办法
5708
查看次数

USB 转 GPIO/SPI/I2C/UART 适用于常规 Windows 10 PC?类似于 Raspberry Pi 40 针接头

有谁知道有一家公司销售适用于普通非物联网 Windows 10 PC 的 USB 电缆,该电缆可以将 USB 转换为 40 针 Raspberry pi 接头上的所有以下总线?示例:USB->GPIO、I2C、SPI、UART 等。

我能找到的最接近的是:

Digilentinc.com 的数字发现逻辑分析仪

这可以将 PC USB 转换为 GPIO/I2C/SPI 等...除了我正在寻找更小、电线更少的东西...只有 40 针接头或更少...类似于树莓派 40 针接头,除了被驱动从连接到 PC 的 USB 改为...有人见过这种类型的待售产品,它可以通过所有列出的总线从 PC-USB 转换为 40 针接头吗?

另外,我希望能够使用“Windows.Devices”Api 而不是专有驱动程序 DLL API 通过Windows UWP对该 USB 转换设备进行编程...还没有真正找到...示例:

// C# Program GPIO connected to USB dongle of regular PC...
using Windows.Devices.GPIO;
...
private void InitGPIO()
{
    var gpio_ctrl = GpioController.GetDefault();
    // Check GPIO state
    if (gpio_ctrl == null)
    {
        this.pin = null; …
Run Code Online (Sandbox Code Playgroud)

c# windows spi i2c gpio

5
推荐指数
1
解决办法
9578
查看次数

如何用C++在Raspberry Pi上通过i2c将MLX90640热像仪图像数据导入OpenCV?

我正在使用通过 i2c 连接到 Raspberry Pi 3 的Melexix MLX90640 32x24 热像仪传感器。

使用Pimoroni的代码,我可以通过帧缓冲区及其fbuf示例在屏幕上显示带有假颜色的相机数据。

由于它直接显示在帧缓冲区上,而不是视频流或相机设备上,因此我无法在OpenCV中读取它。我想使用Open CV中的视频流来统计房间里的人数,但不知道如何修改fbuf代码以输出视频。

它不需要是视频,只是 OpenCV 可以连续读取的图像流

我尝试过的

我安装了v4l2loopback以在 Pi 上创建虚拟摄像头设备,地址为/dev/video0。然后我使用Gstreamer创建 fbuf 代码将红外相机伪色数据写入的屏幕特定区域的流。这创建了一个可由 OpenCV 读取的流,但它没有更新流中的热图像数据。有时图像数据会部分显示,但可以正常显示 Pi 桌面。它也看起来不优雅且有缺陷,所以我想要一个更可靠的解决方案。

迄今为止的结果

Lepton有一个使用 v4l2loopback 中的ondemandcam示例的传感器工作示例,但这是一个不同的传感器,它使用 SPI 而不是 i2c 进行通信。

我的目标是将此代码与 Pimoroni 的帧捕获代码 fbuf 结合起来,从传感器获取稳定的视频流,以便我可以将其导入 OpenCV。

Lepton 的代码基于 v4l2loopback 中的 ondemandcam 示例。它将自己的传感器代码添加到该grab_frame()函数中。该open_vpipe()功能与 ondemandcam 示例相同。

如果我可以将 fbuf 中的帧缓冲区代码放入该grab_frame()函数中,那么我认为它会起作用。我不确定该怎么做。

fbuf 代码片段

这个 for 循环似乎是我需要放入函数中的内容grab_frame()

for(int y …
Run Code Online (Sandbox Code Playgroud)

c++ opencv i2c raspberry-pi3

5
推荐指数
0
解决办法
5365
查看次数

与 C 相比,为什么在 Python 中写入 I2C 太慢?

我试图找出为什么当我尝试写入 I2C 时,即使我使用 CDLL,Python 中的相同代码的工作速度也比 C 慢 25 倍。下面我将逐步描述我正在做的所有细节。

树莓派版本:Raspberry PI 3 Model B

操作系统:Raspbian Buster Lite 版本:2019 年 7 月

GCC 版本:gcc (Raspbian 8.3.0-6+rpi1) 8.3.0

Python 版本:Python 3.7.3

尽管 I2C,我正在使用的设备是 MCP23017。我所做的就是将 0 和 1 写入引脚 B0。这是我用 C 编写的代码:

// test1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <time.h>


int init() {
    int fd = open("/dev/i2c-1", O_RDWR);
    ioctl(fd, I2C_SLAVE, 0x20);
    return fd;
}


void deinit(int fd) {
    close(fd);
}


void makewrite(int fd, int v) …
Run Code Online (Sandbox Code Playgroud)

python gcc ctypes i2c raspberry-pi

5
推荐指数
0
解决办法
252
查看次数