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为最后一个寄存器,之后的所有寄存器都不再解析和设置


目前通信测试正常,功能没有测试,因为没有对应的视频信号及接口。

这只是一个通信的例子,请根据实际情况修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值