OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4929|回复: 3

i2c子系统 之ap3216c,als和ps不显示,求解决

[复制链接]

4

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2020-4-26
在线时间
9 小时
发表于 2020-5-15 18:00:12 | 显示全部楼层 |阅读模式
3金钱
[root@farsight drv_module]# insmod i2c_driver.ko
------------------i2c_drv_init--------------
------------------ap3216c_drv_probe--------------
------------------i2c_write_byte--------------
------------------i2c_write_byte--------------
[root@farsight drv_module]# ./i2c_test
------------------ap3216c_drv_open--------------
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 11, als = 0, ps = 0
ir = 15, als = 0, ps = 0
ir = 7, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 7, als = 0, ps = 0
ir = 15, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
ir = 3, als = 0, ps = 0
als和ps一直没数据,不知道怎么回事

代码如下:还请大佬指正

int i2c_write_byte(struct i2c_client *client,char *buf,int count){
        printk("------------------%s--------------\n",__FUNCTION__);

        int ret;
        struct i2c_adapter *adapter = client->adapter;
        struct i2c_msg msgs[1];

        msgs[0].addr = client->addr;
        msgs[0].flags = 0;
        msgs[0].len = count;
        msgs[0].buf = buf;
       
        ret = i2c_transfer(adapter, msgs, 1);

        return ret == 1 ? count : ret;
}

int ap3216c_read_reg_byte(struct i2c_client *client,char reg){

        //printk("------------------%s--------------\n",__FUNCTION__);

        int ret;
        struct i2c_adapter *adapter = client->adapter;
        struct i2c_msg msgs[2];
        char rxbuf[1];

        msgs[0].flags = 0;//读之前先写,告诉寄存器准备
        msgs[0].addr = client->addr;
        msgs[0].len = 1;
        msgs[0].buf = ®

        msgs[1].flags = 1;
        msgs[1].addr = client->addr;
        msgs[1].len = 1;
        msgs[1].buf = rxbuf;//读到rxbuf

        ret = i2c_transfer(adapter, msgs, 2);
        if(ret < 0)
                {
                        printk("i2c_transfer read error\n");
                        return ret;
                }

                return rxbuf[0];

}


int ap3216c_drv_open(struct inode *inode, struct file *filep){
        printk("------------------%s--------------\n",__FUNCTION__);

        return 0;
}

ssize_t ap3216c_drv_read(struct file *filep, char __user *buf, size_t count){
        //printk("------------------%s--------------\n",__FUNCTION__);
        union ap3216c_data data;
        short date[3];
        long ret=0;

        //读取ir
        //先通过判断IO_RF位,看数据是否有效,有效在读取数据
        data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) ;
        if(data.ir & 0x80)
                date[0] = 7;
        else{
                data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) | 0x03;
                data.ir |=  ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_HIG)<<2;
                date[0] = data.ir;
        }

       
        //读als  不用判断,直接读取
        data.als = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
        data.als |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
        date[1] = data.als;
       
        //读ps
        //先通过判断IO_RF位,看数据是否有效,有效在读取数据
        data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW);
        if(data.ps & 0x40)
                date[2] = 8;// 为1,则无效
        else{
                data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW) | 0xf;
                data.ps |= (ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_HIG) | 0x3f)<<4;
                date[2] = data.ps;
        }

       
       
        ret = copy_to_user(buf, date, sizeof(data));

        return 0;

}



批注 2020-05-15 175613.jpg

最佳答案

查看完整内容[请看2#楼]

问题找到了:::ret = copy_to_user(buf, date, sizeof(date));date写成了data,,,以后还是定义能容易分辨的变量吧
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2020-4-26
在线时间
9 小时
 楼主| 发表于 2020-5-15 18:00:13 | 显示全部楼层
问题找到了:::ret = copy_to_user(buf, date, sizeof(date));date写成了data,,,以后还是定义能容易分辨的变量吧
回复

使用道具 举报

4

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2020-4-26
在线时间
9 小时
 楼主| 发表于 2020-5-15 18:02:05 | 显示全部楼层
完整代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#include "ap3216c.h"

#define AP3216C_SYSTEM_CONFIG                 0x00    //Control of basic functions
#define AP3216C_INT_STATUS                    0x01        //ALS and PS interrupt status output
#define AP3216C_INT_CLEAR_MANNER    0x02        //Auto/semi clear INT pin selector
#define AP3216C_IR_DATA_LOW                  0X0a        //Lower byte for IR ADC channel output
#define AP3216C_IR_DATA_HIG                 0x0b        //Higher byte for IR ADC channel
#define AP3216C_ALS_DATA_LOW                 0x0c        //Lower byte for ALS ADC channel output
#define AP3216C_ALS_DATA_HIG                 0x0d
#define AP3216C_PS_DATA_LOW                  0x0e        //Lower byte for PS ADC channel output
#define AP3216C_PS_DATA_HIG                  0x0f

struct ap3216c_desc{
        struct class *cls;
        struct device *dev;
        struct i2c_client *client;
        int dev_major;
};
struct ap3216c_desc *pf_ap3216;


int i2c_write_byte(struct i2c_client *client,char *buf,int count){
        printk("------------------%s--------------\n",__FUNCTION__);

        int ret;
        struct i2c_adapter *adapter = client->adapter;
        struct i2c_msg msgs[1];

        msgs[0].addr = client->addr;
        msgs[0].flags = 0;
        msgs[0].len = count;
        msgs[0].buf = buf;
       
        ret = i2c_transfer(adapter, msgs, 1);

        return ret == 1 ? count : ret;
}

int ap3216c_read_reg_byte(struct i2c_client *client,char reg){

        //printk("------------------%s--------------\n",__FUNCTION__);

        int ret;
        struct i2c_adapter *adapter = client->adapter;
        struct i2c_msg msgs[2];
        char rxbuf[1];

        msgs[0].flags = 0;//读之前先写,告诉寄存器准备
        msgs[0].addr = client->addr;
        msgs[0].len = 1;
        msgs[0].buf = &reg;

        msgs[1].flags = 1;
        msgs[1].addr = client->addr;
        msgs[1].len = 1;
        msgs[1].buf = rxbuf;//读到rxbuf

        ret = i2c_transfer(adapter, msgs, 2);
        if(ret < 0)
                {
                        printk("i2c_transfer read error\n");
                        return ret;
                }

                return rxbuf[0];

}


int ap3216c_drv_open(struct inode *inode, struct file *filep){
        printk("------------------%s--------------\n",__FUNCTION__);

        return 0;
}

ssize_t ap3216c_drv_read(struct file *filep, char __user *buf, size_t count){
        //printk("------------------%s--------------\n",__FUNCTION__);
        union ap3216c_data data;
        short date[3];
        long ret=0;

        //读取ir
        //先通过判断IO_RF位,看数据是否有效,有效在读取数据
        data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) ;
        if(data.ir & 0x80)
                date[0] = 7;
        else{
                data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) | 0x03;
                data.ir |=  ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_HIG)<<2;
                date[0] = data.ir;
        }

       
        //读als  不用判断,直接读取
        data.als = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
        data.als |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
        date[1] = data.als;
       
        //读ps
        //先通过判断IO_RF位,看数据是否有效,有效在读取数据
        data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW);
        if(data.ps & 0x40)
                date[2] = 8;// 为1,则无效
        else{
                data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW) | 0xf;
                data.ps |= (ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_HIG) | 0x3f)<<4;
                date[2] = data.ps;
        }

       
       
        ret = copy_to_user(buf, date, sizeof(data));

        return 0;

}

int ap3216c_drv_close(struct inode *inode, struct file *filep){
        printk("------------------%s--------------\n",__FUNCTION__);
        return 0;
}
long ap3216c_drv_ioctl(struct file *filep, unsigned int cmd , unsigned long args){
        printk("------------------%s--------------\n",__FUNCTION__);
/*
        union ap3216c_data data;

        switch(cmd){

                case IOC_GET_ALS :
                        data.als = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
                        data.als |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;

                case IOC_GET_PS :
                        data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW);
                        data.ps |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_HIG)<<8;

                case IOC_GET_LED :
                        data.led = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
                        data.led |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
        }
        */
        return 0;
}



const struct file_operations fops = {
        .open = ap3216c_drv_open,
        .read = ap3216c_drv_read,
        .release = ap3216c_drv_close,
        .unlocked_ioctl = ap3216c_drv_ioctl,

};

int ap3216c_drv_probe(struct i2c_client *client, const struct i2c_device_id *id){

        int ret;
        printk("------------------%s--------------\n",__FUNCTION__);
        pf_ap3216 = kzalloc(sizeof(struct ap3216c_desc), GFP_KERNEL);
        if(pf_ap3216 == NULL){
                printk("kzalloc failed\n");
                return -ENOMEM;
        }

        pf_ap3216->client = client;//client,是在i2c_core.c中和adapter匹配成功后传过来的

        //申请主设备号
        pf_ap3216->dev_major = register_chrdev(0, "i2c_chrdev", &fops);
        if(pf_ap3216->dev_major<0)
        {
                printk(KERN_ERR "regist_chardev error\n");
                ret = -ENODEV;
        }
        //创建设备节点
        pf_ap3216->cls = class_create(THIS_MODULE,"i2c_cls");
        if(IS_ERR(pf_ap3216->cls))
        {
                printk(KERN_ERR "class_create error\n");
                ret=PTR_ERR(pf_ap3216->cls);//将指针出错的具体原因转换成出错码
        }
        pf_ap3216->dev = device_create(pf_ap3216->cls, NULL,
                                                MKDEV(pf_ap3216->dev_major,0), NULL, "ap3216c_sensor");
        if(IS_ERR(pf_ap3216->dev))
        {
                printk(KERN_ERR "device_create error\n");
                ret=PTR_ERR(pf_ap3216->dev);//将指针出错的具体原因转换成出错码
        }
       
        /*初始化i2c从设备*/

        //When the host writes this setting(0x04),
        //the all registers of device will become the default value after 10ms. Please don’t
        //force command during these period of 10ms to avoid abnormal operation
       
        char buf1[2] = {AP3216C_SYSTEM_CONFIG,0x04};//For SW reset (100)
        i2c_write_byte(pf_ap3216->client,buf1,2);
        mdelay(20);//至少延时10ms,否则上一步设置失效
       
        char buf2[2] = {AP3216C_SYSTEM_CONFIG,0x03};
        i2c_write_byte(pf_ap3216->client,buf2,2);//ALS and PS+IR

        return 0;
}
int ap3216c_drv_remove(struct i2c_client *client){

        printk("-----%s----\n", __FUNCTION__);
        device_destroy(pf_ap3216->cls, MKDEV(pf_ap3216->dev_major, 0));
        class_destroy(pf_ap3216->cls);
        unregister_chrdev(pf_ap3216->dev_major, "i2c_chrdev");
        kfree(pf_ap3216);
        return 0;

}
/* 传统匹配方式 ID 列表 */
static const struct i2c_device_id ap3216c_id[] = {
        {"peifeng,ap3216c", 0},
        {}
};

       
const struct of_device_id        of_match_id[] = {
        {.compatible = "peifeng,ap3216c"},//用于和设备树compatible = "peifeng,ap3216c"匹配
        {}
};


struct i2c_driver ap3216c_drv = {
        .probe = ap3216c_drv_probe,
        .remove = ap3216c_drv_remove,
        .driver = {
                .name = "ap3216c_drv_peifeng",
                //.of_match_table = of_match_ptr(of_match_id),//@of_match_table: The open firmware table.
                .of_match_table = of_match_id,
        },
        .id_table = ap3216c_id,
       
};


static int __init i2c_drv_init(void){
        printk("------------------%s--------------\n",__FUNCTION__);
       
        return i2c_add_driver(&ap3216c_drv);
        //i2c_register_driver(THIS_MODULE, &ap3216c_drv);

}

static void __exit i2c_drv_exit(void){
        printk("------------------%s--------------\n",__FUNCTION__);

        i2c_del_driver( &ap3216c_drv);
}





module_init(i2c_drv_init);
module_exit(i2c_drv_exit);
MODULE_LICENSE("GPL");
回复

使用道具 举报

7

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
244
金钱
244
注册时间
2016-4-11
在线时间
54 小时
发表于 2020-9-25 10:04:56 | 显示全部楼层
裸机程序也有问题,ap3216c 没有回复ACK,按照IIC 规范,只读一个字节的话,最后不发送ACK,但是裸机程序卡在NACK的地方
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 16:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表