4294
- 收藏
- 点赞
- 分享
- 举报
hi3516 adc源码
hi3516夜视功能中,需要使用3516的adc功能,但官方SDK中并未提供相应的用例。于是,自己编写了一个,提供给大家参考学习。其中包含adc驱动和测试代码。
[code]/* hi_adc.c
*[code]#include
#include
#include
#include
#include
#define OSDRV_MODULE_VERSION_STRING "HISI_adc @HiMPP"
extern int adc_init(void);
extern void adc_exit(void);
extern unsigned int adc_irq;
extern volatile void *pAdcRegBase;
static int hi_adc_probe(struct platform_device *pdev)
{
struct resource *mem;
adc_irq = platform_get_irq(pdev, 0);
if (adc_irq <= 0) {
dev_err(&pdev->dev, "cannot find adc IRQ\n");
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* 物理地址映射为虚拟地址 */
pAdcRegBase = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR((const void*)pAdcRegBase))
{
return PTR_ERR((const void*)pAdcRegBase);
}
return adc_init();
}
static int hi_adc_remove(struct platform_device *pdev)
{
adc_exit();
return 0;
}
static const struct of_device_id hi_adc_match[] = {
{ .compatible = "hisilicon,hi_adc" },
{},
};
static struct platform_driver hi_adc_driver = {
.probe = hi_adc_probe,
.remove = hi_adc_remove,
.driver = { .name = "hi_adc",
.of_match_table = hi_adc_match,
},
};
module_platform_driver(hi_adc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hisilicon/Cmiot");
MODULE_DESCRIPTION("Hisilicon Infrared remoter(HIIR11) Device Driver");
MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING);
[code]#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv)
{
int fd = -1;
const char *dev_name = "/dev/adc";
int len;
char buffer[4]= {0};
fd = open("/dev/adc", 0);
if (fd < 0)
{
perror("open ADC device:");
return -1;
}
for(;;)
{
len = read(fd, buffer, sizeof(buffer));
if (len > 0)
{
buffer[len] = '\0';
int value = -1;
sscanf(buffer, "%d", &value);
printf("ADC Value: %d\n", value);
}
else
{
perror("read ADC device:");
return 1;
}
usleep(500* 1000);
}
close(fd);
return 0;
}
[/code][/code]
* Copyright (c) 2012 Hisilicon Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* History:
* 2012.05.15 create this file <[email]pengkang@huawei.com[/email]>
* 2012.11.20 add temp select method <[email]sunny.liucan@huawei.com[/email]>
*/
#include "hi_osal.h"
#include
#include
#include
#include
#define HIADC_DEVICE_NAME "adc"
//#define HIDEBUG
#define ADC_IRQ (19)
#ifndef NULL
#define NULL ((void *)0)
#endif
#define ADC_TIME_OUT HZ * 5 // 队列等待时间
#define OSDRV_MODULE_VERSION_STRING "HISI_ADC @Hi3516CV100"
#define LSADC_REG_BASE_ADDR 0x120E0000
#define LSADC_CTRL0 0x0000
#define LSADC_CTRL4 0x0010 /* 中断控制寄存器 */
#define LSADC_CTRL5 0x0014 /* 中断状态寄存器 */
#define LSADC_CTRL6 0x0018 /* 中断清除寄存器 */
#define LSADC_CTRL7 0x001C /* start配置寄存器 */
#define LSADC_CTRL9 0x0024 /* 精度控制寄存器,初始值为3ff,10位 */
#define LSADC_CTRL11 0x002C /* LSADC数据保存寄存器1 */
static osal_spinlock_t adc_spin_lock;
static osal_mutex_t hiadc_lock;
static osal_dev_t *adc_dev = 0;
static int flag = 0;
volatile void *pAdcRegBase = NULL;
unsigned int adc_irq = 0;
osal_wait_t adc_irq_wait;
#define HIADC_REG(x) (LSADC_REG_BASE_ADDR + (x))
#define IO_ADC_ADDRESS(x) ((unsigned long)(pAdcRegBase) + ((x)-(LSADC_REG_BASE_ADDR)))
#define hiadc_readl(x) osal_readl(IO_ADC_ADDRESS(HIADC_REG(x)))
#define hiadc_writel(v,x) osal_writel(v, IO_ADC_ADDRESS(HIADC_REG(x)))
static int hi_adc_open(void *private_data)
{
osal_wait_init(&adc_irq_wait);
/* 设置扫描精度10位,单通道 */
hiadc_writel(0xff0201ff, LSADC_CTRL0);
/* 使能中断adc中断 */
hiadc_writel(0x1, LSADC_CTRL4);
return 0;
}
static int hi_adc_close(void *private_data)
{
osal_wait_destory(&adc_irq_wait);
return 0;
}
int hiadc_WaitConditionCallBack(void *pParam)
{
return (flag == 1);
}
static int hi_adc_read(char *buf, int count, long *f_pos, void *private_data)
{
int adc_value = 0;
int result = 0;
int len = 0;
char adc_str[20];
/* 开始转换 */
hiadc_writel(0xf, LSADC_CTRL7);
/* 等待转换完成 */
result = osal_wait_event(&adc_irq_wait,hiadc_WaitConditionCallBack, NULL);
if (result != 0)
{
osal_printk("convert timeout. \n");
return -EFAULT;
}
/* 读取保存adc结果 */
adc_value = hiadc_readl(LSADC_CTRL11);
osal_printk("adc value is:%d.\n", adc_value);
len = sprintf(adc_str, "%d\n", adc_value);
osal_memcpy((void*)buf, (void*)adc_str, len);
/* 清中断 */
hiadc_writel(0x1, LSADC_CTRL6);
flag = 0;
return len;
}
static struct osal_fileops hi_adc_fops =
{
.read = hi_adc_read,
.open = hi_adc_open,
.release = hi_adc_close,
};
static int sar_adc_interrupt(int irq, void *dev_id)
{
/* 读取一次中断标志 */
flag = hiadc_readl(LSADC_CTRL5) | (1 << 0);
osal_printk("adc convert finish,flag is %d. \n", flag);
/* 清中断 */
hiadc_writel(0x1, LSADC_CTRL6);
/* 唤醒读操作 */
osal_wakeup(&adc_irq_wait);
return OSAL_IRQ_HANDLED;
}
int adc_init(void)
{
int ret = 0;
/* 如果未定义中断号,直接使用默认LSADC中断 */
if (adc_irq <= 0)
{
adc_irq = ADC_IRQ;
}
/* 如果未设置物理地址,则直接映射IO端口 */
if (pAdcRegBase == NULL)
{
pAdcRegBase = (volatile void *)osal_ioremap_nocache(LSADC_REG_BASE_ADDR, 0x100);
if (!pAdcRegBase)
{
osal_printk("osal_ioremap_nocache err. \n");
return -1;
}
}
ret = osal_spin_lock_init(&adc_spin_lock);
if (0 != ret)
{
osal_printk("failed to init spin lock.\n");
return -1;
}
ret = osal_mutex_init(&hiadc_lock);
if (0 != ret)
{
osal_printk("failed to init mutex.\n");
goto ADC_INIT_FAIL0;
}
/* 分配设备节点内存 */
adc_dev = osal_createdev(HIADC_DEVICE_NAME);
if (NULL == adc_dev)
{
osal_printk("cretate adc device failed.\n");
goto ADC_INIT_FAIL1;
}
/* 注册设备 */
adc_dev->fops = &hi_adc_fops;
adc_dev->minor = 255;
ret = osal_registerdevice(adc_dev);
if (0 != ret)
{
osal_printk("adc device register failed!\n");
goto ADC_INIT_FAIL2;
}
/* 申请adc中断 */
ret = osal_request_irq(adc_irq, sar_adc_interrupt, NULL, HIADC_DEVICE_NAME, &sar_adc_interrupt);
if (ret != 0)
{
osal_printk("hi3516CV300 adc: failed to register irq %d, (ret %d)\n", adc_irq, ret);
goto ADC_INIT_FAIL3;
}
osal_printk("hi_adc init sucess, adc irq is:%d\n", adc_irq);
return 0;
ADC_INIT_FAIL3:
osal_deregisterdevice(adc_dev);
ADC_INIT_FAIL2:
osal_destroydev(adc_dev);
ADC_INIT_FAIL1:
osal_mutex_destory(&hiadc_lock);
ADC_INIT_FAIL0:
osal_spin_lock_destory(&adc_spin_lock);
return -1;
}
void adc_exit(void)
{
osal_free_irq(adc_irq, &sar_adc_interrupt);
osal_deregisterdevice(adc_dev);
osal_destroydev(adc_dev);
osal_mutex_destory(&hiadc_lock);
osal_spin_lock_destory(&adc_spin_lock);
osal_printk("hi_adc exit sucess.\n");
return;
}
[/code]
[code]/* hi_adc.c
*[code]#include
#include
#include
#include
#include
#define OSDRV_MODULE_VERSION_STRING "HISI_adc @HiMPP"
extern int adc_init(void);
extern void adc_exit(void);
extern unsigned int adc_irq;
extern volatile void *pAdcRegBase;
static int hi_adc_probe(struct platform_device *pdev)
{
struct resource *mem;
adc_irq = platform_get_irq(pdev, 0);
if (adc_irq <= 0) {
dev_err(&pdev->dev, "cannot find adc IRQ\n");
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* 物理地址映射为虚拟地址 */
pAdcRegBase = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR((const void*)pAdcRegBase))
{
return PTR_ERR((const void*)pAdcRegBase);
}
return adc_init();
}
static int hi_adc_remove(struct platform_device *pdev)
{
adc_exit();
return 0;
}
static const struct of_device_id hi_adc_match[] = {
{ .compatible = "hisilicon,hi_adc" },
{},
};
static struct platform_driver hi_adc_driver = {
.probe = hi_adc_probe,
.remove = hi_adc_remove,
.driver = { .name = "hi_adc",
.of_match_table = hi_adc_match,
},
};
module_platform_driver(hi_adc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hisilicon/Cmiot");
MODULE_DESCRIPTION("Hisilicon Infrared remoter(HIIR11) Device Driver");
MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING);
[code]#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv)
{
int fd = -1;
const char *dev_name = "/dev/adc";
int len;
char buffer[4]= {0};
fd = open("/dev/adc", 0);
if (fd < 0)
{
perror("open ADC device:");
return -1;
}
for(;;)
{
len = read(fd, buffer, sizeof(buffer));
if (len > 0)
{
buffer[len] = '\0';
int value = -1;
sscanf(buffer, "%d", &value);
printf("ADC Value: %d\n", value);
}
else
{
perror("read ADC device:");
return 1;
}
usleep(500* 1000);
}
close(fd);
return 0;
}
[/code][/code]
* Copyright (c) 2012 Hisilicon Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* History:
* 2012.05.15 create this file <[email]pengkang@huawei.com[/email]>
* 2012.11.20 add temp select method <[email]sunny.liucan@huawei.com[/email]>
*/
#include "hi_osal.h"
#include
#include
#include
#include
#define HIADC_DEVICE_NAME "adc"
//#define HIDEBUG
#define ADC_IRQ (19)
#ifndef NULL
#define NULL ((void *)0)
#endif
#define ADC_TIME_OUT HZ * 5 // 队列等待时间
#define OSDRV_MODULE_VERSION_STRING "HISI_ADC @Hi3516CV100"
#define LSADC_REG_BASE_ADDR 0x120E0000
#define LSADC_CTRL0 0x0000
#define LSADC_CTRL4 0x0010 /* 中断控制寄存器 */
#define LSADC_CTRL5 0x0014 /* 中断状态寄存器 */
#define LSADC_CTRL6 0x0018 /* 中断清除寄存器 */
#define LSADC_CTRL7 0x001C /* start配置寄存器 */
#define LSADC_CTRL9 0x0024 /* 精度控制寄存器,初始值为3ff,10位 */
#define LSADC_CTRL11 0x002C /* LSADC数据保存寄存器1 */
static osal_spinlock_t adc_spin_lock;
static osal_mutex_t hiadc_lock;
static osal_dev_t *adc_dev = 0;
static int flag = 0;
volatile void *pAdcRegBase = NULL;
unsigned int adc_irq = 0;
osal_wait_t adc_irq_wait;
#define HIADC_REG(x) (LSADC_REG_BASE_ADDR + (x))
#define IO_ADC_ADDRESS(x) ((unsigned long)(pAdcRegBase) + ((x)-(LSADC_REG_BASE_ADDR)))
#define hiadc_readl(x) osal_readl(IO_ADC_ADDRESS(HIADC_REG(x)))
#define hiadc_writel(v,x) osal_writel(v, IO_ADC_ADDRESS(HIADC_REG(x)))
static int hi_adc_open(void *private_data)
{
osal_wait_init(&adc_irq_wait);
/* 设置扫描精度10位,单通道 */
hiadc_writel(0xff0201ff, LSADC_CTRL0);
/* 使能中断adc中断 */
hiadc_writel(0x1, LSADC_CTRL4);
return 0;
}
static int hi_adc_close(void *private_data)
{
osal_wait_destory(&adc_irq_wait);
return 0;
}
int hiadc_WaitConditionCallBack(void *pParam)
{
return (flag == 1);
}
static int hi_adc_read(char *buf, int count, long *f_pos, void *private_data)
{
int adc_value = 0;
int result = 0;
int len = 0;
char adc_str[20];
/* 开始转换 */
hiadc_writel(0xf, LSADC_CTRL7);
/* 等待转换完成 */
result = osal_wait_event(&adc_irq_wait,hiadc_WaitConditionCallBack, NULL);
if (result != 0)
{
osal_printk("convert timeout. \n");
return -EFAULT;
}
/* 读取保存adc结果 */
adc_value = hiadc_readl(LSADC_CTRL11);
osal_printk("adc value is:%d.\n", adc_value);
len = sprintf(adc_str, "%d\n", adc_value);
osal_memcpy((void*)buf, (void*)adc_str, len);
/* 清中断 */
hiadc_writel(0x1, LSADC_CTRL6);
flag = 0;
return len;
}
static struct osal_fileops hi_adc_fops =
{
.read = hi_adc_read,
.open = hi_adc_open,
.release = hi_adc_close,
};
static int sar_adc_interrupt(int irq, void *dev_id)
{
/* 读取一次中断标志 */
flag = hiadc_readl(LSADC_CTRL5) | (1 << 0);
osal_printk("adc convert finish,flag is %d. \n", flag);
/* 清中断 */
hiadc_writel(0x1, LSADC_CTRL6);
/* 唤醒读操作 */
osal_wakeup(&adc_irq_wait);
return OSAL_IRQ_HANDLED;
}
int adc_init(void)
{
int ret = 0;
/* 如果未定义中断号,直接使用默认LSADC中断 */
if (adc_irq <= 0)
{
adc_irq = ADC_IRQ;
}
/* 如果未设置物理地址,则直接映射IO端口 */
if (pAdcRegBase == NULL)
{
pAdcRegBase = (volatile void *)osal_ioremap_nocache(LSADC_REG_BASE_ADDR, 0x100);
if (!pAdcRegBase)
{
osal_printk("osal_ioremap_nocache err. \n");
return -1;
}
}
ret = osal_spin_lock_init(&adc_spin_lock);
if (0 != ret)
{
osal_printk("failed to init spin lock.\n");
return -1;
}
ret = osal_mutex_init(&hiadc_lock);
if (0 != ret)
{
osal_printk("failed to init mutex.\n");
goto ADC_INIT_FAIL0;
}
/* 分配设备节点内存 */
adc_dev = osal_createdev(HIADC_DEVICE_NAME);
if (NULL == adc_dev)
{
osal_printk("cretate adc device failed.\n");
goto ADC_INIT_FAIL1;
}
/* 注册设备 */
adc_dev->fops = &hi_adc_fops;
adc_dev->minor = 255;
ret = osal_registerdevice(adc_dev);
if (0 != ret)
{
osal_printk("adc device register failed!\n");
goto ADC_INIT_FAIL2;
}
/* 申请adc中断 */
ret = osal_request_irq(adc_irq, sar_adc_interrupt, NULL, HIADC_DEVICE_NAME, &sar_adc_interrupt);
if (ret != 0)
{
osal_printk("hi3516CV300 adc: failed to register irq %d, (ret %d)\n", adc_irq, ret);
goto ADC_INIT_FAIL3;
}
osal_printk("hi_adc init sucess, adc irq is:%d\n", adc_irq);
return 0;
ADC_INIT_FAIL3:
osal_deregisterdevice(adc_dev);
ADC_INIT_FAIL2:
osal_destroydev(adc_dev);
ADC_INIT_FAIL1:
osal_mutex_destory(&hiadc_lock);
ADC_INIT_FAIL0:
osal_spin_lock_destory(&adc_spin_lock);
return -1;
}
void adc_exit(void)
{
osal_free_irq(adc_irq, &sar_adc_interrupt);
osal_deregisterdevice(adc_dev);
osal_destroydev(adc_dev);
osal_mutex_destory(&hiadc_lock);
osal_spin_lock_destory(&adc_spin_lock);
osal_printk("hi_adc exit sucess.\n");
return;
}
[/code]
我来回答
回答5个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2018-04-10 10:46:18
-
2017-09-22 10:03:20
-
2018-12-12 09:40:02
-
102019-05-22 09:55:10
-
2019-05-23 17:28:50
-
2018-06-05 17:08:09
-
2019-05-22 09:47:35
-
102017-09-01 09:57:48
-
202015-01-09 11:46:38
-
2019-05-23 17:33:22
-
2015-08-17 18:06:31
-
2019-06-05 10:08:59
-
2018-09-15 15:25:08
-
2016-10-17 15:04:17
-
2017-11-21 22:38:24
-
2019-08-16 10:40:16
-
2015-12-11 11:06:24
-
2018-11-02 15:19:41
-
2019-08-30 11:40:43
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认