tvp5150的iic配置-应用程序实现。
其实内核是支持tvp5150的驱动,但是驱动安装后,又不知道如何进行iic控制。(才疏学浅,被自己的浅薄给难住了),然后换了思路,要不用应用层来控制得了,反正就是iic的设置。
平台:ls2k1000
系统:linux3.10+中标文件系统。
连接:iic0
tvp的iic设备地址是0xBA或者0xB8,这里根据原理图,确认是0xBA(D7引脚接上拉)
程序运行的方法:
./tvp5150_test w 用于配置指定寄存器(默认使用tvp5150_reg.cfg)
./tvp5150_test w tvp5150_reg.cfg 用于配置指定寄存器(由文件指定寄存器及值)
./tvp5150_test r 用于读取指定寄存器(默认使用tvp5150_reg.cfg)
./tvp5150_test r tvp5150_reg.cfg 用于读取指定寄存器(由文件指定寄存器)
[root@localhost tvp5150]# ./tvp5150_test w
1. Set register 0:
val 0 (0)
2. Set register 0x1:
val 21 (0x15)
3. Set register 0x2:
val 0 (0)
4. Set register 0x3:
val 1 (0x1)
5. Set register 0x6:
val 16 (0x10)
6. Set register 0x7:
val 96 (0x60)
7. Set register 0x8:
val 0 (0)
8. Set register 0x9:
val 128 (0x80)
9. Set register 0xa:
val 128 (0x80)
10. Set register 0xb:
val 0 (0)
11. Set register 0xc:
val 128 (0x80)
12. Set register 0xd:
val 71 (0x47)
13. Set register 0xe:
val 0 (0)
14. Set register 0xf:
val 8 (0x8)
15. Set register 0x11:
val 0 (0)
16. Set register 0x12:
val 0 (0)
17. Set register 0x13:
val 0 (0)
18. Set register 0x14:
val 0 (0)
19. Set register 0x15:
val 1 (0x1)
20. Set register 0x16:
val 128 (0x80)
21. Set register 0x18:
val 0 (0)
22. Set register 0x19:
val 0 (0)
23. Set register 0x1a:
val 12 (0xc)
24. Set register 0x1b:
val 20 (0x14)
25. Set register 0x1c:
val 0 (0)
26. Set register 0x1d:
val 0 (0)
27. Set register 0x1e:
val 0 (0)
28. Set register 0x28:
val 0 (0)
29. Set register 0x2e:
val 15 (0xf)
30. Set register 0x2f:
val 1 (0x1)
31. Set register 0xbb:
val 0 (0)
32. Set register 0xc0:
val 0 (0)
33. Set register 0xc1:
val 0 (0)
34. Set register 0xc2:
val 4 (0x4)
35. Set register 0xc8:
val 128 (0x80)
36. Set register 0xc9:
val 0 (0)
37. Set register 0xca:
val 0 (0)
38. Set register 0xcb:
val 78 (0x4e)
39. Set register 0xcc:
val 0 (0)
40. Set register 0xcd:
val 1 (0x1)
41. Set register 0xcf:
val 0 (0)
42. Set register 0xd0:
val 0 (0)
43. Set register 0xfc:
val 127 (0x7f)
end
源码贴出,直接gcc编译即可
/*
* @Author: dazhi
* @Date: 2022-05-17 10:57:01
* @Last Modified by: dazhi
* @Last Modified time: 2022-05-18 09:51:32
*/#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h> #define FILENAME "tvp5150_reg.cfg"
#define I2C_FILE_NAME "/dev/i2c-0"
#define IIC_DEV_ADDR 0x5d //iic的设备地址static int set_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char value) { unsigned char outbuf[2]; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[1]; messages[0].addr = addr; messages[0].flags = 0; messages[0].len = sizeof(outbuf); messages[0].buf = outbuf; /* The first byte indicates which register we'll write */ outbuf[0] = reg; /* * The second byte indicates the value to write. Note that for many * devices, we can write multiple, sequential registers at once by * simply making outbuf bigger. */ outbuf[1] = value; /* Transfer the i2c packets to the kernel and verify it worked */ packets.msgs = messages; packets.nmsgs = 1; if(ioctl(file, I2C_RDWR, &packets) < 0) { perror("Unable to send data"); return 1; } return 0;
} static int get_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char *val) { unsigned char inbuf, outbuf; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; /* * In order to read a register, we first do a "dummy write" by writing * 0 bytes to the register we want to read from. This is similar to * the packet in set_i2c_register, except it's 1 byte rather than 2. */ outbuf = reg; messages[0].addr = addr; messages[0].flags = 0; messages[0].len = sizeof(outbuf); messages[0].buf = &outbuf; /* The data will get returned in this structure */ messages[1].addr = addr; messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/; messages[1].len = sizeof(inbuf); messages[1].buf = &inbuf; /* Send the request to the kernel and get the result back */ packets.msgs = messages; packets.nmsgs = 2; if(ioctl(file, I2C_RDWR, &packets) < 0) { perror("Unable to send data"); return 1; } *val = inbuf; return 0;
} int main(int argc, char **argv) { FILE* fp;char * filenamep = FILENAME;char buf[128];char buf1[8];int len;int reg;unsigned char val;char *p;char rw = 0; //1表示读,2表示写char rw_flag = 0; //用于写寄存器的时候的标志位,1表示获取寄存器正确,0表示获取寄存器错int count = 0;int i2c_file; if(argc != 3 && argc != 2){printf("Usage: %s r | w [regfile.cfg]\n",argv[0]);printf("r 的意思是读寄存器的值,读哪些寄存器由regfile.cfg的寄存器区域指定\n");printf("w 的意思是写寄存器的值,写哪些寄存器由regfile.cfg的寄存器区域指定\n");printf(" 写入寄存器值由regfile.cfg的值区域指定\n");printf("参数不指定regfile.cfg文件,将使用默认配置文件tvp5150_reg.cfg\n");}else //只有两个参数的时候{if(strcmp(argv[1], "r") == 0)rw = 1;else if(strcmp(argv[1], "w") == 0)rw = 2;if(rw!=1 && rw != 2){printf("参数1 rw 指定错误,请重新输入\n");printf("Usage: %s r [regfile.cfg] 表示读寄存器\n",argv[0]);printf("Usage: %s w [regfile.cfg] 表示写寄存器\n",argv[0]);return -1;}if(argc == 3) {filenamep = argv[2];}//打开文件fp = fopen(filenamep,"r");if(fp == NULL){printf("文件%s打开失败!!\n",filenamep);printf("使用方法: %s r | w regfile.cfg\n",argv[0]);printf("r 的意思是读寄存器的值,读哪些寄存器由tvp5150_reg.cfg的寄存器区域指定\n");printf("w 的意思是写寄存器的值,写哪些寄存器由tvp5150_reg.cfg的寄存器区域指定\n");printf(" 写入寄存器值由tvp5150_reg.cfg的值区域指定\n");return -1;}}// Open a connection to the I2C userspace control file. if ((i2c_file = open(I2C_FILE_NAME, O_RDWR)) < 0) { perror("Unable to open i2c control file");fclose(fp); exit(1); } //一行一行读while(1){if(feof(fp)) //文件结尾break;if(NULL == fgets(buf, sizeof buf, fp)) //读文件失败,或者读到文件结尾break;//读出来了len = strlen(buf);if(len > 255 || len < 5) //不可能读出这么多数据,长度不合理continue;if(buf[0] == '#') //# 号开头直接跳过continue;//printf("buf = %s",buf);p = strtok(buf,","); //使用逗号分割。reg = strtol(p, NULL, 0); //进行16进制解析snprintf(buf1,sizeof buf1,"0x%02hhx",reg);if(strncmp(p,buf1,strlen(buf1)) == 0){// printf("reg get\n");if(reg == 0xff) //最后一个寄存器,跳出break;if(rw == 1) //读寄存器{if(get_i2c_register(i2c_file, IIC_DEV_ADDR, reg, &val)) { printf("Unable to get register!\n"); } else { printf("%d. Register %#x: \n\tval %d (%#x)\n", count+1,reg, (int)val, (int)val); } }else if(rw == 2){rw_flag = 1; }}if(rw == 2) //写寄存器的时候,才需要值{ p = strtok(NULL,","); //使用逗号分割。if(p == NULL)continue;val = strtol(p, NULL, 0);snprintf(buf1,sizeof buf1,"0x%02hhx",val);if(strncmp(p,buf1,strlen(buf1)) == 0) //转换的值与之前的值相等{// printf("val get\n");if(rw_flag == 1){if(set_i2c_register(i2c_file, IIC_DEV_ADDR, reg, val)) { printf("Unable to get register!\n"); } else { printf("%d. Set register %#x: \n\tval %d (%#x)\n",count+1, reg, val, val); } rw_flag = 0; //标志位清0}}}count ++;}fclose(fp);close(i2c_file);printf("end\n");return 0;
}
配置文件示例:(这是驱动中截出来的!!!)
# 井号开头表示注释,程序不解析
# 数据只有两个字节,用逗号隔开,第一个数据表示寄存器地址(称为寄存器区域),第二个表示需要设置的值(称为值区域)
# /*TVP5150_VD_IN_SRC_SEL_1*/
0x00,0x00
# /*TVP5150_ANAL_CHL_CTL*/
0x01,0x15
# /*TVP5150_OP_MODE_CTL*/
0x02,0x00
# /*TVP5150_MISC_CTL*/
0x03,0x01
# /*TVP5150_COLOR_KIL_THSH_CTL*/
0x06,0x10
# /*TVP5150_LUMA_PROC_CTL_1*/
0x07,0x60
# /*TVP5150_LUMA_PROC_CTL_2*/
0x08,0x00
# /*TVP5150_BRIGHT_CTL*/
0x09,0x80
# /*TVP5150_SATURATION_CTL*/
0x0a,0x80
# /*TVP5150_HUE_CTL*/
0x0b,0x00
# /*TVP5150_CONTRAST_CTL*/
0x0c,0x80
# /*TVP5150_DATA_RATE_SEL*/
0x0d,0x47
# /*TVP5150_LUMA_PROC_CTL_3*/
0x0e,0x00
# /*TVP5150_CONF_SHARED_PIN*/
0x0f,0x08
# /*TVP5150_ACT_VD_CROP_ST_MSB*/
0x11,0x00
# /*TVP5150_ACT_VD_CROP_ST_LSB*/
0x12,0x00
# /*TVP5150_ACT_VD_CROP_STP_MSB*/
0x13,0x00
# /*TVP5150_ACT_VD_CROP_STP_LSB*/
0x14,0x00
# /*TVP5150_GENLOCK*/
0x15,0x01
# /*TVP5150_HORIZ_SYNC_START*/
0x16,0x80
# /*TVP5150_VERT_BLANKING_START*/
0x18,0x00
# /*TVP5150_VERT_BLANKING_STOP*/
0x19,0x00
# /*TVP5150_CHROMA_PROC_CTL_1*/
0x1a,0x0c
# /*TVP5150_CHROMA_PROC_CTL_2*/
0x1b,0x14
# /*TVP5150_INT_RESET_REG_B*/
0x1c,0x00
# /*TVP5150_INT_ENABLE_REG_B*/
0x1d,0x00
# /*TVP5150_INTT_CONFIG_REG_B*/
0x1e,0x00
# /*TVP5150_VIDEO_STD*/
0x28,0x00
# /*TVP5150_MACROVISION_ON_CTR*/
0x2e,0x0f
# /*TVP5150_MACROVISION_OFF_CTR*/
0x2f,0x01
# /*TVP5150_TELETEXT_FIL_ENA*/
0xbb,0x00
# /*TVP5150_INT_STATUS_REG_A*/
0xc0,0x00
# /*TVP5150_INT_ENABLE_REG_A*/
0xc1,0x00
# /*TVP5150_INT_CONF*/
0xc2,0x04
# /*TVP5150_FIFO_INT_THRESHOLD*/
0xc8,0x80
# /*TVP5150_FIFO_RESET*/
0xc9,0x00
# /*TVP5150_LINE_NUMBER_INT*/
0xca,0x00
# /*TVP5150_PIX_ALIGN_REG_LOW*/
0xcb,0x4e
# /*TVP5150_PIX_ALIGN_REG_HIGH*/
0xcc,0x00
# /*TVP5150_FIFO_OUT_CTRL*/
0xcd,0x01
# /*TVP5150_FULL_FIELD_ENA*/
0xcf,0x00
# /*TVP5150_LINE_MODE_INI*/
0xd0,0x00
# /*TVP5150_FULL_FIELD_MODE_REG*/
0xfc,0x7f
# /* end of data */
0xff,0xff
# 0xff为最后一个寄存器,之后的所有寄存器都不再解析和设置
目前通信测试正常,功能没有测试,因为没有对应的视频信号及接口。
这只是一个通信的例子,请根据实际情况修改。
tvp5150的iic配置-应用程序实现。相关推荐
- RStudio配置R程序包的默认下载源
RStudio配置R程序包的默认下载源 # 进入RStudio主页,并点击tools下拉菜单,选择最后面的Global Options选项: # 点击packages按钮: # 选择和自己当前位置叫 ...
- ASP.NET Core 配置 - 创建自定义配置提供程序
ASP.NET Core 配置 - 创建自定义配置提供程序 在本文中,我们将创建一个自定义配置提供程序,从数据库读取我们的配置.我们已经了解了默认配置提供程序的工作方式,现在我们将实现我们自己的自定义 ...
- .NET Core开发实战(第11课:文件配置提供程序)--学习笔记
11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...
- .NET Core开发实战(第10课:环境变量配置提供程序)--学习笔记
10 | 环境变量配置提供程序:容器环境下配置注入的最佳途径 环境变量的配置提供程序主要适应场景: 1.在 Docker 中运行时 2.在 Kubernetes 中运行时 3.需要设置 ASP.NET ...
- .NET Core开发实战(第9课:命令行配置提供程序)--学习笔记
09 | 命令行配置提供程序:最简单快捷的配置注入方法 这一节讲解如何使用命令行参数来作为配置数据源 命令行配置(提供程序的)支持三种格式的命令 1.无前缀的 key=value 模式 2.双中横线模 ...
- 扒一扒.NET Core的环境配置提供程序
前言 很久之前,在玩Docker的时候顺便扒了扒,最近,终于下定决心花了些时间整理并成文,希望能够给大家一些帮助. 目录 .NET Core中的配置 ASP.NET Core中的配置 扒一扒环境变量提 ...
- Jco服务配置以及程序编写
Jco服务配置以及程序编写 SAP 与第三方面软件进行数据通信时,运用到的中间件JCO,以下是JCO的服务配置.以及程序的编写,希望能给大家带来点帮助 SAP与java进行通信的流程: 操作步骤 AB ...
- 应用程序初次运行数据库配置小程序(Java版)
应用程序初始化数据库配置小程序 之前写过一个Java版的信息管理系统,但部署系统的时候还需要手动的去配置数据库和导入一些初始化的数据才能让系统运行起来,所以我在想是不是可以写一个小程序在系统初次运行的 ...
- ssis 包配置组织程序_如何停止失控的SSIS程序包
ssis 包配置组织程序 There are many reasons for terminating a long running SSIS Package. Picture a scenario ...
最新文章
- 尚国栋:金融风控贷款违约预测(天池学习赛)
- CSS中的id选择器和class选择器简单介绍
- 搭建rabbitmq的docker集群
- LGOJ P3919【模板】可持久化数组(可持久化线段树/平衡树)
- 乐高无限的服务器怎么建,乐高无限悬空房子怎么建造 建造方法介绍
- 简述linux的重要安装过程,对Linux安装过程的理解
- css覆盖规则_条件 CSS
- webbrowser只对浏览器外应用程序以及在_常用浏览器大盘点!
- python100例详解-Python 经典算法100及解析(小结)
- android测试内存的软件下载,AndroBench p10内存门app下载
- jdk下载,安装与卸载,删除注册表
- 如何调整PDF的页面布局
- SWUST.OJ 964: 数细胞
- 国家级城市群规划的八大变化
- c java gif 夺宝奇兵_java游戏:将GIF转 字符GIF
- python中元组的概念_python元组的概念与基本操作
- java面试题高级_Java高级面试题整理(附答案)
- gg怎样获得root权限,gg怎么获得root权限
- 储能控制器,风光储、风光储并网直流微电网simulink仿真模型
- 4412第一部分 开发板入门