使用GPIO 模拟出I2C控制器:

使用GPIO模拟I2C控制器需要按照以下步骤进行:

1、模拟出I2C控制器需要2个GPIO引脚,即SCL和SDA;

2、首先需要确定GPIO是否可用;

	1、cat /sys/kernel/debug/gpio  //查看当前gpio信息,无法查看到gpio10的信息
	2、echo 10 > /sys/class/gpio/export //export需要设置的gpio10
	3、cat /sys/kernel/debug/gpio  //查看当前gpio信息,可以查看到gpio10的信息
	4、echo out > /sys/class/gpio/gpio10/direction //设置gpio位输出模式
	5、cat /sys/class/gpio/gpio10/value //查看gpio10的值
	6、echo 1 > /sys/class/gpio/gpio10/value //设置gpio10输出值位高电平
	7、cat /sys/class/gpio/gpio10/value //查看gpio10的值
	8、cat /sys/kernel/debug/gpio  //查看当前gpio信息
	9、echo 10 > /sys/class/gpio/unexport //unexport需要设置的gpio10
	10、cat /sys/kernel/debug/gpio  //查看当前gpio信息

3、配置GPIO引脚:将GPIO引脚配置为输出模式,用于产生I2C控制器的SCL(串行时钟)和SDA(串行数据)信号;

4、产生起始条件:在需要开始数据传输时,将SDA引脚设置为高电平,然后在SCL引脚上产生一个高电平脉冲,以产生起始条件;

5、发送数据:在SCL信号的上升沿将数据写入SDA引脚,以发送一个字节的数据。在每个字节发送完毕后,需要在SCL信号的下降沿产生一个停止条件;

6、接收数据:在SCL信号的上升沿读取SDA引脚上的数据,以接收一个字节的数据。在每个字节接收完毕后,需要在SCL信号的下降沿产生一个停止条件;

7、产生停止条件:在数据传输完成后,将SDA引脚设置为低电平,然后在SCL引脚上产生一个高电平脉冲,以产生停止条件。

需要注意的是,使用GPIO模拟I2C控制器可能会受到硬件噪声和其他因素的影响,导致数据传输的可靠性降低。因此,在实际应用中,建议使用专门的I2C控制器芯片来保证数据传输的稳定性和可靠性

下图为I2C控制器波形图:
在这里插入图片描述
怎么解析DTS文件中的gpio引脚

旧GPIO接口写法:

       struct device *dev,
       struct device_node *np = dev->of_node;
       int gpio_pin = of_get_named_gpio_flags(np, "dts-name", 0, &flag);                         //解析设备树节点的属性信息,函数可以获取到GPIO引脚的配置信息,并将其存储在标志flag中
       lcd_en_gpio =of_get_named_gpio(np, "dts-name", 0); //解析设备树节点的属性信息,函数可以获取到GPIO引脚的编号,并将其返回给调用者。
       gpio_request(gpio_pin, "gpio_name");    //通过gpio号申请gpio
       gpio_direction_output(gpio_pin, 1);     //设置gpio_pin为输出引脚,同时初始值为1
       gpio_set_value(gpio_pin, 0);            //设置gpio_pin值为0
       gpio_free(gpio_pin);                    //gpio_pin不再使用后应当释放
       of_gpio_count(np);                     //多个gpio引脚解析

新GPIO接口写法:

      struct i2c_client *i2c;
       devm_gpiod_get(&i2c->dev,
					       "spk-con",
					       GPIOD_OUT_LOW));    //通过gpio号申请gpio
       gpiod_direction_output(gpio_pin, 1);     //设置gpio_pin为输出引脚,同时初始值为1
       gpiod_direction_input(gpio_pin, 1);     //设置gpio_pin为输出引脚,同时初始值为1
       gpiod_set_value(gpio_pin, 0);            //设置gpio_pin值为0
       gpiod_free(gpio_pin);                  //gpio_pin不再使用后应当释放
       gpiod_put(gpio_pin);                   //gpio_pin不再使用后应当释放

获取IRQ:
在probe函数中获取中断,调用中断处理函数
1、request_irq是Linux内核中用于注册中断服务函数的函数。当设备产生中断时,系统会调用这个函数来处理中断。

函数的原型如下:

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *), unsigned long irqflags, const char *devname, void *dev_id);//函数原型

	struct i2c_client *client = sd1513->client;
	ret = request_irq(client->irq , sd1513_rx_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED, "sd1513_det_gpio", client);
	printk("%s >>> sd1513 >>> %s >>> %d  ret >>> %d >>> client->irq %d",__FILE__,__FUNCTION__,__LINE__,ret,client->irq);
	if (ret < 0) {
		free_irq(client->irq, sd1513);
	}

参数说明:

irq:中断号,即设备的中断向量。
handler:中断处理程序,系统会在中断发生时调用这个函数来处理中断。
irqflags:中断标志位,用于指定中断的属性、触发方式等。
devname:设备名称,用于在内核日志中标识中断来源。
dev_id:设备标识符,用于在多个设备共享同一个中断号时区分不同的设备。
函数返回值为0表示注册成功,否则表示注册失败。

需要注意的是,request_irq函数需要在设备驱动程序中调用,而且需要在设备初始化之前完成中断的注册。

2、devm_request_irq是内核设备模型中用于申请中断的函数,它的功能与request_irq类似,但申请的是内核“managed”的资源。它与request_irq的区别在于,devm_request_irq申请的中断号不需要在出错的地方处理,也不需要在remove()接口里面显式释放。

static inline int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) //函数原型

struct i2c_client *i2c
ret = devm_request_irq(&i2c->dev, rt5651->irq, rt5651_irq,
			       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
			       | IRQF_ONESHOT, "rt5651", rt5651);
if (ret == 0) {
	/* Gets re-enabled by rt5651_set_jack() */
	disable_irq(rt5651->irq);
} else {
	dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n",
		 rt5651->irq, ret);
	rt5651->irq = -ENXIO;
}

参数说明:

dev:指向设备对象的指针。
irq:中断号。
handler:中断处理函数。
irqflags:中断标志,用于指定中断触发模式。
devname:中断名称,用于方便调试。
dev_id:设备标识符,通常是设备结构体或设备私有数据的指针。
其中,irqflags参数可以是以下值的按位或:

IRQF_SHARED:允许多个设备共享同一个中断号。
IRQF_TRIGGER_NONE:禁用中断触发。
IRQF_TRIGGER_RISING:上升沿触发。
需要注意的是,在使用devm_request_irq函数时,需要确保已经正确初始化了设备对象和中断处理函数。同时,当不再需要使用中断时,需要使用free_irq函数显式释放中断号。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值