一、dts文件书写
gpio_i2c: gpio_i2c {
status = "okay";
compatible = "gpio_i2c";
gpio_sda = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>;
gpio_scl = <&gpio2 RK_PA3 GPIO_ACTIVE_HIGH>;
};
分别用两个gpio模拟数据线与信号线
二、利用字符设备模拟输入输出
驱动代码
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/err.h>
#include<linux/gpio.h>
#include<linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include<linux/io.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/interrupt.h>
#include<linux/platform_device.h>
#include<linux/delay.h>
#define DELAY_TIME_HXD 100 //设置i2c clk, hxd019大概要求10k左右
static int SDA; /*SDA的引脚号*/
static int SCL; /*SDL的引脚号*/
static int majorNumber;
static const char *CLASS_NAME = "i2c_class";
static const char *DEVICE_NAME = "i2c_device";
static struct cdev gpio_dev;
static dev_t ndev;
static int gpio_status;
static char recv_msg[2000];
static struct class *i2c_gpio_class;
static struct device *i2c_gpio_device;
struct i2c_gpio_info {
int i2c_gpio; /*gpio号*/
int gpio_value; /*电平*/
};
static int i2c_gpio_open(struct inode *node, struct file *file)
{
printk(KERN_INFO "GPIO init\n");
return 0;
}
static ssize_t i2c_gpio_read(struct file *file, char *buf, size_t len, loff_t *offset)
{
int cnt = 0;/*将内核空间的数据copy到用户空间*/
cnt = copy_to_user(buf, &gpio_status, 1);
if (cnt == 0) {
return 0;
} else {
printk(KERN_ALERT "ERROR occur when reading!!\n");
return -EFAULT;
}
return 1;
}
/* I2C起始条件 */
void i2c_start(void)
{
//初始化GPIO口
gpio_direction_output (SDA, 1); //设置SDA方向为输出,设置SDA为高电平
gpio_direction_output (SCL, 1); //设置SCL方向为输出,设置SCL为高电平
udelay(DELAY_TIME_HXD); //延时
//起始条件
gpio_set_value(SDA, 0); //SCL为高电平时,SDA由高变低
udelay(DELAY_TIME_HXD);
}
/* I2C终止条件 */
void i2c_stop(void)
{

文章描述了一种使用GPIO模拟I2C通信的方法,包括dts文件配置、驱动代码实现以及字符设备的操作函数。驱动代码中定义了I2C的起始和终止条件,读写操作,并提供了读写函数。应用层代码展示了如何打开设备文件并写入数据。然而,存在一些问题,如额外的波形和不支持从机发送信号。

3109

被折叠的 条评论
为什么被折叠?



