精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于AP3216C芯片的三合一整合型光感測器設計

電子設計 ? 來源:面板板社區 ? 作者:嵌入式大雜燴 ? 2021-03-26 16:07 ? 次閱讀

1、前言

開發板上有AP3216三合一整合型光感測器,看了看出廠SDK包中并未添加相關驅動。本次我們就一起來學習一下。

2、AP3216簡介

AP3216C 芯片集成了光強傳感器( ALS: Ambient Light Sensor),接近傳感器( PS: Proximity Sensor),還有一個紅外 LED( IR LED)。

這個芯片設計的用途是給手機之類的使用,比如:返回當前環境光強以便調整屏幕亮度;用戶接聽電話時,將手機放置在耳邊后,自動關閉屏幕避免用戶誤觸碰 。

該芯片通過 I2C 接口與主控制器相連, 如:

pIYBAGBdlbOAIL6PAADkkj4qYmo904.png

3、IIC驅動簡介

Linux下IIC有兩種驅動方式:一種是按照字符設備驅動方式來驅動IIC;另一種是走Linux下IIC的框架。按照字符設備驅動的方式可以查閱這一篇文章:Linux IIC 字符設備 驅動例子。

這里我們淺淺地(真的很淺~~)了解學習一下第二種方式,因為找到的AP3216的驅動就是基于IIC驅動框架的,哈哈。

IIC驅動框架圖如

IIC驅動框架可大體分為兩大部分:

① I2C 總線驅動:SOC 的 I2C 控制器驅動,也叫做 I2C 適配器驅動。

② I2C 設備驅動:針對具體的 I2C 設備而編寫的驅動。

其中,訪問抽象層與I2C核心層數據I2C 總線驅動部分;driver驅動層屬于I2C設備驅動部分。

上面框圖對應的代碼調用層次圖如:

下面的AP3216驅動可以對照這張圖來看看。

4、AP3216實驗

我們使用設備樹來描述AP3216設備信息,首先我們沒有在設備樹中添加AP3216相關節點時,我們系統的I2C設備如:

添加I2C pinctrl,板子上AP3216接的是I2C1:

配置寄存器的值都設為0x4001b8b0,這一段是什么意思我們在什么是Pinctrl子系統及GPIO子系統?這篇筆記中也有寫到,就是幾個寄存器及其配置。

接下來在i2c1節點下添加ap3216節點:

編譯設備樹,傳到開發板上,重啟。此時我們系統的I2C設備有:

可見,新增的AP3216 I2C設備名就是我們設備樹里設置的。

下面編寫AP3216驅動(以下代碼來源于網絡):

ap3216.c:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"ap3216creg.h"
/***************************************************************
文件名:ap3216c.c
描述:AP3216C驅動程序
***************************************************************/
#defineAP3216C_CNT1
#defineAP3216C_NAME"ap3216c"

structap3216c_dev{
dev_tdevid;/*設備號*/
structcdevcdev;/*cdev*/
structclass*class;/*類*/
structdevice*device;/*設備*/
structdevice_node*nd;/*設備節點*/
intmajor;/*主設備號*/
void*private_data;/*私有數據*/
unsignedshortir,als,ps;/*三個光傳感器數據*/
};

staticstructap3216c_devap3216cdev;

/*
*@description:從ap3216c讀取多個寄存器數據
*@param-dev:ap3216c設備
*@param-reg:要讀取的寄存器首地址
*@param-val:讀取到的數據
*@param-len:要讀取的數據長度
*@return:操作結果
*/
staticintap3216c_read_regs(structap3216c_dev*dev,u8reg,void*val,intlen)
{
intret;
structi2c_msgmsg[2];
structi2c_client*client=(structi2c_client*)dev->private_data;

/*msg[0]為發送要讀取的首地址*/
msg[0].addr=client->addr;/*ap3216c地址*/
msg[0].flags=0;/*標記為發送數據*/
msg[0].buf=®/*讀取的首地址*/
msg[0].len=1;/*reg長度*/

/*msg[1]讀取數據*/
msg[1].addr=client->addr;/*ap3216c地址*/
msg[1].flags=I2C_M_RD;/*標記為讀取數據*/
msg[1].buf=val;/*讀取數據緩沖區*/
msg[1].len=len;/*要讀取的數據長度*/

ret=i2c_transfer(client->adapter,msg,2);
if(ret==2){
ret=0;
}else{
printk("i2crdfailed=%dreg=%06xlen=%d\n",ret,reg,len);
ret=-EREMOTEIO;
}
returnret;
}

/*
*@description:向ap3216c多個寄存器寫入數據
*@param-dev:ap3216c設備
*@param-reg:要寫入的寄存器首地址
*@param-val:要寫入的數據緩沖區
*@param-len:要寫入的數據長度
*@return:操作結果
*/
statics32ap3216c_write_regs(structap3216c_dev*dev,u8reg,u8*buf,u8len)
{
u8b[256];
structi2c_msgmsg;
structi2c_client*client=(structi2c_client*)dev->private_data;

b[0]=reg;/*寄存器首地址*/
memcpy(&b[1],buf,len);/*將要寫入的數據拷貝到數組b里面*/

msg.addr=client->addr;/*ap3216c地址*/
msg.flags=0;/*標記為寫數據*/

msg.buf=b;/*要寫入的數據緩沖區*/
msg.len=len+1;/*要寫入的數據長度*/

returni2c_transfer(client->adapter,&msg,1);
}

/*
*@description:讀取ap3216c指定寄存器值,讀取一個寄存器
*@param-dev:ap3216c設備
*@param-reg:要讀取的寄存器
*@return:讀取到的寄存器值
*/
staticunsignedcharap3216c_read_reg(structap3216c_dev*dev,u8reg)
{
u8data=0;

ap3216c_read_regs(dev,reg,&data,1);
returndata;

#if0
structi2c_client*client=(structi2c_client*)dev->private_data;
returni2c_smbus_read_byte_data(client,reg);
#endif
}

/*
*@description:向ap3216c指定寄存器寫入指定的值,寫一個寄存器
*@param-dev:ap3216c設備
*@param-reg:要寫的寄存器
*@param-data:要寫入的值
*@return:無
*/
staticvoidap3216c_write_reg(structap3216c_dev*dev,u8reg,u8data)
{
u8buf=0;
buf=data;
ap3216c_write_regs(dev,reg,&buf,1);
}

/*
*@description :讀取AP3216C的數據,讀取原始數據,包括ALS,PS和IR, 注意!
*:如果同時打開ALS,IR+PS的話兩次數據讀取的時間間隔要大于112.5ms
*@param-ir:ir數據
*@param-ps:ps數據
*@param-ps:als數據
*@return :無。
*/
voidap3216c_readdata(structap3216c_dev*dev)
{
unsignedchari=0;
unsignedcharbuf[6];

/*循環讀取所有傳感器數據*/
for(i=0;iir=0;
else/*讀取IR傳感器的數據*/
dev->ir=((unsignedshort)buf[1]<als=((unsignedshort)buf[3]<ps=0;
else/*讀取PS傳感器的數據*/
dev->ps=((unsignedshort)(buf[5]&0X3F)<private_data=&ap3216cdev;

/*初始化AP3216C*/
ap3216c_write_reg(&ap3216cdev,AP3216C_SYSTEMCONG,0x04);/*復位AP3216C*/
mdelay(50);/*AP3216C復位最少10ms*/
ap3216c_write_reg(&ap3216cdev,AP3216C_SYSTEMCONG,0X03);/*開啟ALS、PS+IR*/
return0;
}

/*
*@description:從設備讀取數據
*@param-filp:要打開的設備文件(文件描述符)
*@param-buf:返回給用戶空間的數據緩沖區
*@param-cnt:要讀取的數據長度
*@param-offt:相對于文件首地址的偏移
*@return:讀取的字節數,如果為負值,表示讀取失敗
*/
staticssize_tap3216c_read(structfile*filp,char__user*buf,size_tcnt,loff_t*off)
{
shortdata[3];
longerr=0;

structap3216c_dev*dev=(structap3216c_dev*)filp->private_data;

ap3216c_readdata(dev);

data[0]=dev->ir;
data[1]=dev->als;
data[2]=dev->ps;
err=copy_to_user(buf,data,sizeof(data));
return0;
}

/*
*@description:關閉/釋放設備
*@param-filp:要關閉的設備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintap3216c_release(structinode*inode,structfile*filp)
{
return0;
}

/*AP3216C操作函數*/
staticconststructfile_operationsap3216c_ops={
.owner=THIS_MODULE,
.open=ap3216c_open,
.read=ap3216c_read,
.release=ap3216c_release,
};

/*
*@description:i2c驅動的probe函數,當驅動與
*設備匹配以后此函數就會執行
*@param-client:i2c設備
*@param-id:i2c設備ID
*@return:0,成功;其他負值,失敗
*/
staticintap3216c_probe(structi2c_client*client,conststructi2c_device_id*id)
{
/*1、構建設備號*/
if(ap3216cdev.major){
ap3216cdev.devid=MKDEV(ap3216cdev.major,0);
register_chrdev_region(ap3216cdev.devid,AP3216C_CNT,AP3216C_NAME);
}else{
alloc_chrdev_region(&ap3216cdev.devid,0,AP3216C_CNT,AP3216C_NAME);
ap3216cdev.major=MAJOR(ap3216cdev.devid);
}

/*2、注冊設備*/
cdev_init(&ap3216cdev.cdev,&ap3216c_ops);
cdev_add(&ap3216cdev.cdev,ap3216cdev.devid,AP3216C_CNT);

/*3、創建類*/
ap3216cdev.class=class_create(THIS_MODULE,AP3216C_NAME);
if(IS_ERR(ap3216cdev.class)){
returnPTR_ERR(ap3216cdev.class);
}

/*4、創建設備*/
ap3216cdev.device=device_create(ap3216cdev.class,NULL,ap3216cdev.devid,NULL,AP3216C_NAME);
if(IS_ERR(ap3216cdev.device)){
returnPTR_ERR(ap3216cdev.device);
}

ap3216cdev.private_data=client;

return0;
}

/*
*@description:i2c驅動的remove函數,移除i2c驅動的時候此函數會執行
*@param-client:i2c設備
*@return:0,成功;其他負值,失敗
*/
staticintap3216c_remove(structi2c_client*client)
{
/*刪除設備*/
cdev_del(&ap3216cdev.cdev);
unregister_chrdev_region(ap3216cdev.devid,AP3216C_CNT);

/*注銷掉類和設備*/
device_destroy(ap3216cdev.class,ap3216cdev.devid);
class_destroy(ap3216cdev.class);
return0;
}

/*傳統匹配方式ID列表*/
staticconststructi2c_device_idap3216c_id[]={
{"iot,ap3216c",0},
{}
};

/*設備樹匹配列表*/
staticconststructof_device_idap3216c_of_match[]={
{.compatible="iot,ap3216c"},
{/*Sentinel*/}
};

/*i2c驅動結構體*/
staticstructi2c_driverap3216c_driver={
.probe=ap3216c_probe,
.remove=ap3216c_remove,
.driver={
.owner=THIS_MODULE,
.name="ap3216c",
.of_match_table=ap3216c_of_match,
},
.id_table=ap3216c_id,
};

/*
*@description:驅動入口函數
*@param:無
*@return:無
*/
staticint__initap3216c_init(void)
{
intret=0;

ret=i2c_add_driver(&ap3216c_driver);
returnret;
}

/*
*@description:驅動出口函數
*@param:無
*@return:無
*/
staticvoid__exitap3216c_exit(void)
{
i2c_del_driver(&ap3216c_driver);
}

/*module_i2c_driver(ap3216c_driver)*/

module_init(ap3216c_init);
module_exit(ap3216c_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pjw");

驅動詳解可查閱注釋及配合上訴的I2C驅動框架的框圖及數據手冊理解。

ap3216creg.h:

#ifndefAP3216C_H
#defineAP3216C_H
/***************************************************************
文件名:ap3216creg.h
描述:AP3216C寄存器地址描述頭文件
***************************************************************/
#defineAP3216C_ADDR0X1E/*AP3216C器件地址*/
/*AP3316C寄存器*/
#defineAP3216C_SYSTEMCONG0x00/*配置寄存器*/
#defineAP3216C_INTSTATUS0X01/*中斷狀態寄存器*/
#defineAP3216C_INTCLEAR0X02/*中斷清除寄存器*/
#defineAP3216C_IRDATALOW0x0A/*IR數據低字節*/
#defineAP3216C_IRDATAHIGH0x0B/*IR數據高字節*/
#defineAP3216C_ALSDATALOW0x0C/*ALS數據低字節*/
#defineAP3216C_ALSDATAHIGH0X0D/*ALS數據高字節*/
#defineAP3216C_PSDATALOW0X0E/*PS數據低字節*/
#defineAP3216C_PSDATAHIGH0X0F/*PS數據高字節*/
#endif

ap3216應用:

ap3216cApp.c:

#include"stdio.h"
#include"unistd.h"
#include"sys/types.h"
#include"sys/stat.h"
#include"sys/ioctl.h"
#include"fcntl.h"
#include"stdlib.h"
#include"string.h"
#include
#include
#include
#include
#include
/***************************************************************
文件名:ap3216cApp.c
描述: ap3216c設備測試APP。
使用方法:./ap3216cApp /dev/ap3216c
***************************************************************/

/*
*@description:main主程序
*@param-argc:argv數組元素個數
*@param-argv:具體參數
*@return:0成功;其他失敗
*/
intmain(intargc,char*argv[])
{
intfd;
char*filename;
unsignedshortdatabuf[3];
unsignedshortir,als,ps;
intret=0;

if(argc!=2){
printf("ErrorUsage!\r\n");
return-1;
}

filename=argv[1];
fd=open(filename,O_RDWR);
if(fd

編寫Makefile,從之前的文章=======拷貝過來修改:

KERN_DIR=/home/book/100ask_imx6ull-sdk/Linux-4.9.88

all:
make-C$(KERN_DIR)M=`pwd`modules
$(CROSS_COMPILE)gcc-oap3216cAppap3216cApp.c

clean:
make-C$(KERN_DIR)M=`pwd`modulesclean
rm-rfmodules.order
rm-fap3216cApp

#參考內核源碼drivers/char/ipmi/Makefile
#要想把a.c,b.c編譯成ab.ko,可以這樣指定:
#ab-y:=a.ob.o
#obj-m+=ab.o

obj-m+=ap3216.o

編譯得到ap3216.ko及ap3216cApp,傳到板子上運行:

以上就是本次的實驗分享,如果文章對你有幫助,歡迎轉發,謝謝!

參考資料

1、https://blog.csdn.net/weixin_34032792/article/details/85582751?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&dist_request_id=1328690.367.16165120737124801&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

2、https://blog.csdn.net/p1279030826/article/details/106459333

3、《嵌入式Linux應用開發完全手冊》

編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接近傳感器
    +關注

    關注

    5

    文章

    188

    瀏覽量

    24412
  • I2C
    I2C
    +關注

    關注

    28

    文章

    1481

    瀏覽量

    123304
  • I2C總線
    +關注

    關注

    8

    文章

    388

    瀏覽量

    60830
  • 光感測器
    +關注

    關注

    0

    文章

    5

    瀏覽量

    7131
收藏 人收藏

    評論

    相關推薦

    移動電源方案究竟硬件三合一還是軟件三合一?

    弄清楚。實際上移動電源三合一,分為硬件移動電源三合一和軟件移動電源三合一兩種技術路線。硬件三合一芯片主要存在的問題是:1.發熱嚴重,因為主
    發表于 09-15 22:57

    同步整流 移動電源三合一問題

    事件,真相如何?要解答這個問題,其根本是要把三合一移動電源解決方案不穩定的原因弄清楚。 實際上移動電源三合一,分為硬件移動電源三合一和軟件移動電源三合一兩種技術路線。 硬件
    發表于 09-18 14:32

    移動電源硬件三合一方案和軟件三合一方案對比

    事件,真相如何?要解答這個問題,其根本是要把三合一移動電源解決方案不穩定的原因弄清楚。實際上移動電源三合一,分為硬件移動電源三合一和軟件移動電源三合一兩種技術路線。硬件
    發表于 10-21 10:40

    新人提問:移動電源方案軟件三合一好還是硬件三合一好?

    新人提問:移動電源方案軟件三合一好還是硬件三合一好?剛開始做移動電源這行,時間不長,對于這個移動電源方案軟件三合一還是硬件三合一兩者的把握
    發表于 10-23 14:05

    雞、狗、貓三合一聲光玩具電路圖

    雞、狗、貓三合一聲光玩具電路圖
    發表于 05-21 13:31 ?893次閱讀
    雞、狗、貓<b class='flag-5'>三合一聲光</b>玩具電路圖

    Vishay推出首款三合一環境傳感 VCNL4000

    Vishay推出首款三合一環境傳感 VCNL4000 帶有I2C總線界面的短距離接近/環境傳感
    發表于 09-30 12:05 ?986次閱讀
    Vishay推出首款<b class='flag-5'>三合一</b>環境<b class='flag-5'>光</b>傳感<b class='flag-5'>器</b> VCNL4000

    三合一(溫濕)傳感設計

    本設計采用SHT11溫濕度傳感芯片款集成了ADC的環境傳感MAX9635,實現溫、濕度及光照
    發表于 07-16 10:38 ?4345次閱讀
    <b class='flag-5'>三合一</b>(溫濕<b class='flag-5'>光</b>)傳感<b class='flag-5'>器</b>設計

    環境溫濕度及光照三合一傳感器設計

    設計了基于I 2 C總線接口的全校準數字式相對濕度、溫度傳感和環境三合一傳感器。其具有數字式輸出、免調試、免標定、免外圍電路,提供I 2 C
    發表于 12-07 14:25 ?99次下載
    環境溫濕度及光照<b class='flag-5'>三合一傳感器</b>設計

    移動電源三合一方案解析_移動電源三合一方案的優點介紹

    本文主要介紹移動電源三合一方案解析_移動電源三合一方案的優點介紹。移動電源三合一方案,是指主控芯片移動電源MCU無需外掛DC-DC芯片和充電
    發表于 12-29 15:00 ?9913次閱讀
    移動電源<b class='flag-5'>三合一</b>方案解析_移動電源<b class='flag-5'>三合一</b>方案的優點介紹

    移動電源三合一方案都有哪些_移動電源三合一方案哪種最穩定

    、ZS6288/A三合一同步升壓移動電源專用芯片,ZS6599三合一移動電源專用芯片這幾種方案都是可以的,穩定性有保障。
    發表于 12-29 15:22 ?1.7w次閱讀
    移動電源<b class='flag-5'>三合一</b>方案都有哪些_移動電源<b class='flag-5'>三合一</b>方案哪種最穩定

    MPort 100IE三合一隔離Modbus網關

    電子發燒友網站提供《MPort 100IE三合一隔離Modbus網關.pdf》資料免費下載
    發表于 10-17 09:23 ?0次下載
    MPort 100IE<b class='flag-5'>三合一</b>隔離<b class='flag-5'>型</b>Modbus網關

    三合一智能音箱演示

    三合一智能音箱演示
    發表于 03-15 19:54 ?0次下載
    <b class='flag-5'>三合一</b>智能音箱演示

    AP3216C三合一環境傳感器使用指南

    博主最近在調試 AP3216C 三合一環境傳感,由敦南科技推出的款傳感,支持環境光強度(ALS)、接近距離(PS)和紅外線強度(IR)
    的頭像 發表于 04-17 18:01 ?9409次閱讀
    <b class='flag-5'>AP3216C</b><b class='flag-5'>三合一</b>環境傳感器使用指南

    三合一智能音箱演示

    三合一智能音箱演示
    發表于 07-06 19:03 ?0次下載
    <b class='flag-5'>三合一</b>智能音箱演示

    WH4530A三合一 接近傳感芯片

    由工采網代理的臺灣旺泓-WH4530A是款集成了環境傳感(PS)接近傳感(ALS)和紅外LED燈三合一
    的頭像 發表于 02-26 10:58 ?484次閱讀
    WH4530A<b class='flag-5'>三合一</b><b class='flag-5'>光</b>距<b class='flag-5'>感</b> 接近傳感<b class='flag-5'>芯片</b>