×
单片机 > 单片机程序设计 > 详情

3.4.2内核下I2C驱动之24CXX实例

发布时间:2020-08-28 发布时间:
|
at24cxx_dev.c部分:
 
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/platform_device.h"
#include "linux/i2c.h"
#include "linux/err.h"
#include "linux/regmap.h"
#include "linux/slab.h"
 
static struct i2c_board_info at24cxx_info = {    
    I2C_BOARD_INFO("at24c08", 0x50),
};
 
static struct i2c_client *at24cxx_client;
 
static int at24cxx_dev_init(void)
{
    struct i2c_adapter *i2c_adap;
 
    i2c_adap = i2c_get_adapter(0);
    at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info);
    i2c_put_adapter(i2c_adap);
    
    return 0;
}
 
static void at24cxx_dev_exit(void)
{
    i2c_unregister_device(at24cxx_client);
}
 
module_init(at24cxx_dev_init);
module_exit(at24cxx_dev_exit);
MODULE_LICENSE("GPL");
 
=================================================================
at24cxx_drv.c部分:
 
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/platform_device.h"
#include "linux/i2c.h"
#include "linux/err.h"
#include "linux/regmap.h"
#include "linux/slab.h"
#include "linux/fs.h"
#include "asm/uaccess.h"
 
static int major;
static struct class *class;
static struct i2c_client *at24cxx_client;
 
// 传入: buf[0] : addr
// 输出: buf[0] : data
//
static ssize_t at24cxx_read(struct file * file, char __user *buf, size_t count, loff_t *off)
{
    unsigned char addr, data;
    
    copy_from_user(&addr, buf, 1);
    data = i2c_smbus_read_byte_data(at24cxx_client, addr);
    copy_to_user(buf, &data, 1);
    return 1;
}
 
// buf[0] : addr
// buf[1] : data
//
static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
    unsigned char ker_buf[2];
    unsigned char addr, data;
 
    copy_from_user(ker_buf, buf, 2);
    addr = ker_buf[0];
    data = ker_buf[1];
 
    printk("addr = 0xx, data = 0xx\n", addr, data);
 
    if (!i2c_smbus_write_byte_data(at24cxx_client, addr, data))
        return 2;
    else
        return -EIO;    
}
 
static struct file_operations at24cxx_fops = {
    .owner = THIS_MODULE,
    .read  = at24cxx_read,
    .write = at24cxx_write,
};
 
static int __devinit at24cxx_probe(struct i2c_client *client,
                  const struct i2c_device_id *id)
{
    at24cxx_client = client;
        
    //printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    major = register_chrdev(0, "at24cxx", &at24cxx_fops);
    class = class_create(THIS_MODULE, "at24cxx");
    device_create(class, NULL, MKDEV(major, 0), NULL, "at24cxx"); // /dev/at24cxx //
    
    return 0;
}
 
static int __devexit at24cxx_remove(struct i2c_client *client)
{
    //printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    device_destroy(class, MKDEV(major, 0));
    class_destroy(class);
    unregister_chrdev(major, "at24cxx");
        
    return 0;
}
 
static const struct i2c_device_id at24cxx_id_table[] = {
    { "at24c08", 0 },
    {}
};
 
 
// 1. 分配/设置i2c_driver //
static struct i2c_driver at24cxx_driver = {
    .driver    = {
        .name    = "100ask",
        .owner   = THIS_MODULE,
    },
    .probe       = at24cxx_probe,
    .remove    = __devexit_p(at24cxx_remove),
    .id_table    = at24cxx_id_table,
};
 
static int at24cxx_drv_init(void)
{
    // 2. 注册i2c_driver //
    i2c_add_driver(&at24cxx_driver);
    
    return 0;
}
 
static void at24cxx_drv_exit(void)
{
    i2c_del_driver(&at24cxx_driver);
}
 
module_init(at24cxx_drv_init);
module_exit(at24cxx_drv_exit);
MODULE_LICENSE("GPL");
 
=================================================================
i2c_test.c测试程序:
 
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
 
// i2c_test r addr
// i2c_test w addr val
 
void print_usage(char *file)
{
    printf("%s r addr\n", file);
    printf("%s w addr val\n", file);
}
 
int main(int argc, char **argv)
{
    int fd;
    unsigned char buf[2];
    
    if ((argc != 3) && (argc != 4))
    {
        print_usage(argv[0]);
        return -1;
    }
 
    fd = open("/dev/at24cxx", O_RDWR);
    if (fd " 0)
    {
        printf("can't open /dev/at24cxx\n");
        return -1;
    }
 
    if (strcmp(argv[1], "r") == 0)
    {
        buf[0] = strtoul(argv[2], NULL, 0);
        read(fd, buf, 1);
        printf("data: %c, %d, 0x%2x\n", buf[0], buf[0], buf[0]);
    }
    else if ((strcmp(argv[1], "w") == 0) && (argc == 4))
    {
        buf[0] = strtoul(argv[2], NULL, 0);
        buf[1] = strtoul(argv[3], NULL, 0);
        if (write(fd, buf, 2) != 2)
            printf("write err, addr = 0xx, data = 0xx\n", buf[0], buf[1]);
    }
    else
    {
        print_usage(argv[0]);
        return -1;
    }
    
    return 0;
}
 
================================================================
Makefile:
 
KERN_DIR = /work/system/linux-3.4.2
 
all:
        make -C $(KERN_DIR) M=`pwd` modules 
 
clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
 
obj-m        += at24cxx_dev.o
obj-m        += at24cxx_drv.o
#obj-m += i2c_bus_s3c2440.o

关键字:3.4.2内核  I2C驱动  24CXX实例

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式