Linux I2C例程应用层读写

Linux应用——I2C通信例程

背景需求

两块板子通过I2C连接,其中一块为Master角色,一块为Slave角色,可以实现双方的相互通信,包括传输文件。

本文描述Master角色的编码。

需求:

  • 可以指定Slave地址
  • 可以指定传输文件块大小
  • 可以指定传输每个数据块间隔
  • 可以指定I2C的端口名称

实现设计

  • 读取命令行参数
  • 初始化参数后,依照参数向I2C设备写入数据,并尝试读取一段定长的数据

文件组织

文件名 文件描述 备注
main.c 判断传入参数,并实现调用I2C读写接口
i2c.c I2C初始化、读写接口实现
util.c 其他接口
typedef.h 数据类型定义
log.h 日志接口头文件

代码

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

#include "i2c.h"
#include "util.h"

static void usage(const char *program)
{
   
    if (NULL == program) {
   
        return;
    }

	printf("Usage: %s [OPTION]\n"
            "\n"
			"  -h, --help\n"
			"  -f, --file        file to send\n"
			"  -a, --address     i2c slave address (0x%02X by default)\n"
			"  -b, --block       transfer block size (%dB by default)\n"
			"  -d, --delay       transfer delay us (%dus by default)\n"
			"  -p, --port        i2c port name (%s by default)\n",
            program, DFT_I2C_SLAVE_ADDR, MAX_DFU_PKT, DFT_I2C_INTERVAL, DFT_I2C_PORT);
}

static bool read_dfu_file(char *optarg, DFU *dfu)
{
   
    if (NULL == optarg || NULL == dfu) {
   
        return false;
    }

    dfu->file = fopen(optarg, "rb");
    if (NULL == dfu->file) {
   
        print("fail to open %s", optarg);
        return false;
    }

    if (fseek(dfu->file, 0L, SEEK_END)) {
   
        goto error;
    }

    dfu->total = dfu->toload = ftell(dfu->file);
    if (fseek(dfu->file, 0L, SEEK_SET)) {
   
        goto error;
    }

    return true;

error:
    fclose(dfu->file);
    return false;
}

static void check_param(I2C_CTX *i2c, DFU *dfu)
{
   
    if (NULL == i2c || NULL == dfu) {
   
        return;
    }

    if (NULL == dfu->file) {
   
        print("No file to transfer...");
        exit(EXIT_FAILURE);
    }

    if (dfu->blk_size < 1 || dfu->blk_size > MAX_DFU_PKT) {
   
        dfu->blk_size = MAX_DFU_PKT;
    }

    if (dfu->delay_us < 1 || dfu->delay_us > (DFT_I2C_INTERVAL << 2)) {
   
        dfu->delay_us = DFT_I2C_INTERVAL;
    }

    if (i2c->port[0] == '\0') {
   
        strncpy(i2c->port, DFT_I2C_PORT, FILE_SIZE);
    }

    if (i2c->slave_addr == 0x00) {
   
        i2c->slave_addr = DFT_I2C_SLAVE_ADDR;
    }

    /* master ----> slave, address right shift */
    i2c->slave_addr >>= 1;

    i2c->fd = i2c_dev_init(i2c);
    if (i2c->fd <= 0) {
   
        print("fail to init i2c device:%s", i2c->port);
        exit(EXIT_FAILURE);
    }

    print("\n\nI2C port:%s\nslave address:0x%02X\nblock size:%d B\ninterval:%d us\n",
            i2c->port, i2c->slave_addr, dfu->blk_size, dfu->delay_us);
}

static void init(int argc, char *argv[], I2C_CTX *i2c, DFU *dfu)
{
   
    int opt = 0;
    int opt_idx = 0;
    const char *short_opts = "ha:p:f:b:d:";
    const struct option long_opts[] = {
   
        {
   "help", no_argument, 0, 'h'},
        {
   "address", required_argument, 0, 'a'},
        
  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: STM32F446是意法半导体(STMicroelectronics)推出的一款基于ARM Cortex-M4内核的高性能微控制器。它具有丰富的外设资源,其中包括一种被广泛应用的串行通信接口I2C(Inter-Integrated Circuit)。下面是关于STM32F446的I2C例程的简要介绍。 STM32F446的I2C例程是基于I2C外设的软件库函数的示例代码。该例程演示了如何使用I2C进行数据传输和通信。 一般而言,使用I2C进行数据传输主要包括以下几个步骤: 1. 设置I2C外设的参数:配置I2C总线速率、模式等,可以使用STM32提供的I2C库函数进行设置。 2. 初始化I2C外设:初始化I2C的硬件资源,包括引脚和时钟等,可以使用STM32提供的I2C库函数进行初始化。 3. 配置I2C从设备:设置I2C从设备的地址和其他相关参数,以便I2C主设备能够与其进行通信。 4. 发送数据:使用I2C主设备发送数据到从设备。可以使用STM32提供的I2C库函数完成。 5. 接收数据:使用I2C主设备接收从设备发送的数据。同样可以使用STM32提供的I2C库函数完成。 6. 处理数据:根据具体应用需求对接收到的数据进行处理,例如解析、转换等。 7. 关闭I2C外设:在完成数据传输后,关闭I2C外设以释放相关资源,可以使用STM32提供的I2C库函数进行关闭。 以上步骤仅是一个基本的流程,在实际应用中可能会根据需求进行更多的配置和处理。 总的来说,STM32F446的I2C例程提供了一个示例,展示了如何使用STM32提供的库函数来实现I2C通信的基本操作。这些例程可以作为开发者学习和使用I2C的参考,帮助他们快速上手和开发自己的应用。 ### 回答2: 在STM32F446微控制器上使用I2C(Inter-Integrated Circuit)总线进行通信的例程如下: 1. 首先,需要在STM32CubeMX软件中选择I2C总线的引脚,并使能I2C外设。具体选择哪些引脚以及使能外设的操作可以根据硬件连接和需求来确定。 2. 在代码中,首先需要包含相应的头文件,例如stm32f4xx_hal.h和stm32f4xx_hal_i2c.h。 3. 然后,需要对I2C外设进行初始化。可以使用HAL_I2C_Init()函数来完成初始化操作。在初始化过程中,需要设置I2C的时钟频率、I2C模式、地址模式等参数。 4. 接下来,可以使用HAL_I2C_Master_Transmit()函数进行主设备的发送数据操作。该函数的参数包括I2C外设的句柄、从设备地址、待发送的数据缓冲区和数据长度。 5. 若要接收数据,可以使用HAL_I2C_Master_Receive()函数进行主设备的接收数据操作。该函数的参数和HAL_I2C_Master_Transmit()函数类似。 6. 如果要进行高级的I2C操作,例如使用DMA进行数据传输或者使用中断机制,可以查阅相关的参考文档和例程,并进行相应的配置和编程。 7. 最后,在使用完成I2C总线后,需要调用HAL_I2C_DeInit()函数来关闭I2C外设。 以上是使用STM32F446微控制器进行I2C通信的简要步骤和说明。具体的实现代码可以根据具体应用和使用的开发环境进行编写。 ### 回答3: STM32F446是意法半导体(STMicroelectronics)推出的一款高性能32位内核的微控制器系列。它具有丰富的外设接口,包括多个I2C总线接口。下面我将简要介绍STM32F446的I2C例程I2C(Inter-Integrated Circuit)是一种串行通信接口,可用于多个器件之间的通信。STM32F446的I2C控制器由硬件支持,可以通过配置寄存器来实现不同模式的通信。 在编写STM32F446的I2C例程时,我们需要进行如下步骤: 1. 初始化I2C控制器:通过设置I2C相关寄存器,如I2C_CR1、I2C_CR2等,来配置I2C的工作模式、时钟频率等参数。 2. 选择I2C模式:STM32F446的I2C控制器支持主模式和从模式。主模式用于发送命令和读取数据,从模式用于接收命令和发送数据。 3. 配置设备地址和寄存器地址:在主模式下,我们需要配置要通信的从设备地址和要访问的寄存器地址。 4. 发送和接收数据:根据需要,我们可以通过调用适当的函数来发送和接收数据。例如,使用I2C_TransmitData()函数发送数据,使用I2C_ReceiveData()函数接收数据。 5. 处理中断和错误:在I2C通信过程中,可能出现中断和错误。我们需要正确处理这些中断和错误,以确保通信的完整性和准确性。 总之,编写STM32F446的I2C例程需要配置I2C控制器、选择模式、配置地址、发送和接收数据,并处理中断和错误。在理解了I2C的基本原理和STM32F446的硬件架构后,我们可以根据具体的应用需求,编写出适用的I2C例程
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值