ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

S5PV210开发板板载Gsensor KXTE9读取XYZ坐标值

2021-11-19 13:02:16  阅读:222  来源: 互联网

标签:板载 cur err S5PV210 cnt transferred int msg 坐标值


Study210开发板板载Gsensor读取XYZ坐标值


声明:源代码是基于韦东山老师以及朱有鹏老师的I2C课程的源代码进行修改

一、板载Gsensor KXTE9需要用到的寄存器简介

1. CT_RESP (0x0C)

	通信测试用,默认为0x55,当把CTRL_3的bit4设为1时,会读取到0xAA,第二次再读就会自动变为0x55,用于测试通信是否成功

2. X_OUT (0x12)

	X方向的加速度值

3. Y_OUT (0x13)

	Y方向的加速度值

4. Z_OUT (0x14)

	Z方向的加速度值

5. CTRL_1 (0x1B)

	写入0x98,可将Gsensor KXTE9 设为操作板式模式(默认为待机),同时将数据传输速率设为40Hz

6. CTRL_3 (0x1D)

	把CTRL_3的bit4设为1时,读取CT_RESP会得到0xAA,第二次再读就会自动变为0x55,用于测试通信是否成功

二、S5PV210和2440在I2C通信上的区别

因为I2C是基于中断进行处理的,两个SoC在中断处理上的不同要注意

三、相关函数功能

1. read_data 读板载KXTE9的寄存器数据

2. write_data 写板载KXTE9的寄存器数据

四、程序运行结果

在这里插入图片描述

五、代码示例

#define GPD0CON     (0xE02000A0)
#define GPD1CON     (0xE02000C0)
#define GPD0DAT     (0xE02000A4)
#define I2CCON0     (0xE1800000)
#define I2CSTAT0    (0xE1800004)
#define I2CDS0      (0xE180000C)

#define rGPD0CON    (*(volatile unsigned int *)GPD0CON)
#define rGPD1CON    (*(volatile unsigned int *)GPD1CON)
#define rGPD0DAT    (*(volatile unsigned int *)GPD0DAT)
#define rI2CCON0    (*(volatile unsigned int *)I2CCON0)
#define rI2CSTAT0   (*(volatile unsigned int *)I2CSTAT0)
#define rI2CDS0     (*(volatile unsigned int *)I2CDS0)

static p_i2c_msg p_cur_msg;

int isLastData(void)
{
	if (p_cur_msg->cnt_transferred == p_cur_msg->len - 1)
		return 1;  /* 正要开始传输最后一个数据 */
	else 
		return 0;
}

void resume_iic_with_ack(void)
{
	unsigned int iiccon = rI2CCON0;
	iiccon |= (1<<7); /* 回应ACK */
	iiccon &= ~(1<<4); /* 恢复IIC操作 */
	rI2CCON0 =  iiccon;
}

void resume_iic_without_ack(void)
{
	unsigned int iiccon = rI2CCON0;
	iiccon &= ~((1<<7) | (1<<4)); /* 不回应ACK, 恢复IIC操作 */
	rI2CCON0 =  iiccon;
}


void i2c_interrupt_func(void)
{
    
	int index;
	unsigned int iicstat = rI2CSTAT0;
	//unsigned int iiccon;

	//printf("i2c_interrupt_func! flags = %d\n\r", p_cur_msg->flags);

	p_cur_msg->cnt_transferred++;
	
	/* 每传输完一个数据将产生一个中断 */

	/* 对于每次传输, 第1个中断是"已经发出了设备地址" */

	if (p_cur_msg->flags == 0)	/* write */
	{

    
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
            
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
				rI2CSTAT0 = 0xd0;
				rI2CCON0 &= ~(1<<4);
				p_cur_msg->err = -1;
				//printf("tx err, no ack\n\r");
				delay10us(10);
				return;
			}
		}
              
		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{            
			/* 对于其他中断, 要继续发送下一个数据
			 */
	
			rI2CDS0 = p_cur_msg->buf[p_cur_msg->cnt_transferred];          
			rI2CCON0 &= ~(1<<4);
		}
		else
		{
			/* 停止传输 */
			rI2CSTAT0 = 0xd0;
			rI2CCON0 &= ~(1<<4);
            intc_clearvectaddr();
          
			delay10us(100);
		}
       
	}
	else /* read */
	{
        
		/* 对于第1个中断, 它是发送出设备地址后产生的
		 * 需要判断是否有ACK
		 * 有ACK : 设备存在, 恢复I2C传输, 这样在下一个中断才可以得到第1个数据
		 * 无ACK : 无设备, 出错, 直接结束传输
		 */
		 
		if (p_cur_msg->cnt_transferred == 0)  /* 第1次中断 */
		{
            
			if (iicstat & (1<<0))
			{ /* no ack */
				/* 停止传输 */
             
				rI2CSTAT0 = 0x90;
				rI2CCON0 &= ~(1<<4);
				p_cur_msg->err = -1;
				//printf("rx err, no ack\n\r");
				delay10us(100);
				return;
			}
			else  /* ack */
			{              
				/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
				/* 恢复I2C传输 */
				if (isLastData())
				{
					resume_iic_without_ack();
				}
				else
				{
					resume_iic_with_ack();
				}
                
                intc_clearvectaddr();
				return;
			}
            
		}

		/* 非第1个中断, 表示得到了一个新数据
		 * 从IICDS读出、保存
		 */
		if (p_cur_msg->cnt_transferred < p_cur_msg->len)
		{
            
			index = p_cur_msg->cnt_transferred - 1;
			p_cur_msg->buf[index] = rI2CDS0;

			/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
			/* 恢复I2C传输 */
			if (isLastData())
			{
				resume_iic_without_ack();
			}
			else
			{
				resume_iic_with_ack();
			}
            intc_clearvectaddr();
            
		}        
		else
		{
			/* 发出停止信号 */
			rI2CSTAT0 = 0x90;
			rI2CCON0 &= ~(1<<4);
            intc_clearvectaddr();
			delay10us(100);      
		}
       
	}
   
    /*清除中断*/
    intc_clearvectaddr();
    
    
}


void s5PV210_i2c_con_init(void)
{
    /*设置GPD0^2为输出并置1,给Gsensor上电*/
    rGPD0CON |= (0x1<<12);
    rGPD0DAT = 1;

    /*设置GPD1^0-1为I2C功能*/
    rGPD1CON &= ~(0xff);
    rGPD1CON |= (0x22);

    /*1.设置I2CACK信号启用(bit7)
     *2.设置I2CCLK = fPCLK /512(bit6)
     *3.设置I2C中断打开(bit5)
     *4.清除中断挂起(bit4)
     *5.设置时钟二级分频为3,即实际时钟为66Mhz/512/(3+1) = 32.23Khz(bit0-3)
     */
    rI2CCON0 = 0xE3;
}

int do_master_tx(p_i2c_msg msg)
{
    
	p_cur_msg = msg;
	
	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 master tx mode */
	rI2CCON0 |= (1<<7); /* TX mode, 在ACK周期释放SDA */
	rI2CSTAT0 = (1<<4);
		
	/* 2. 把从设备地址写入IICDS */
	rI2CDS0 = msg->addr<<1;
	
	/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
	rI2CSTAT0 = 0xf0;
	  
	/* 后续的传输由中断驱动 */
    
	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len)
	{
        delay10us(10);           
        
	}
    
   	if (msg->err)
		return -1;
	else
		return 0;
    
}

int do_master_rx(p_i2c_msg msg)
{  
    p_cur_msg = msg;

	msg->cnt_transferred = -1;
	msg->err = 0;
	
	/* 设置寄存器启动传输 */
	/* 1. 配置为 Master Rx mode */
	rI2CCON0 |= (1<<7); /* RX mode, 在ACK周期回应ACK */
	rI2CSTAT0 = (1<<4);
		
	/* 2. 把从设备地址写入IICDS */
	rI2CDS0 = (msg->addr<<1)|(1<<0);
	
	/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
	rI2CSTAT0 = 0xb0;
	

	/* 后续的传输由中断驱动 */

	/* 循环等待中断处理完毕 */
	while (!msg->err && msg->cnt_transferred != msg->len)
	{
        delay10us(10);             
	}
     

	if (msg->err)
		return -1;
	else
		return 0;
}

int s3c2440_master_xfer(p_i2c_msg msgs, int num)
{
	int i;
	int err;
	
	for (i = 0; i < num; i++)	
	{
        
		if (msgs[i].flags == 0)/* write */
			err = do_master_tx(&msgs[i]);
		else
			err = do_master_rx(&msgs[i]);
		if (err)
			return err;
	}
	return 0;
}
/*写I2c设备的寄存器*/
void write_data(int addr_t, int data_t)
{ 
    unsigned int buf[2];
    buf[0] = addr_t;
    buf[1] = data_t;
    i2c_msg msg;
    
    /* 构造i2c_msg */
    msg.addr  = 0x0f;
    msg.flags  = 0; /* write */
    msg.len   = 2;
    msg.buf   = buf;
    msg.err   = 0;
    msg.cnt_transferred = -1;
    s3c2440_master_xfer(&msg,1);  
}

/*读I2c设备的寄存器*/

int read_data(int addr_t)
{ 
    unsigned int addr =addr_t;
    unsigned int data;
    int len = 2;
    i2c_msg msg[2];

    /* 构造i2c_msg */
    msg[0].addr  = 0x0f;
    msg[0].flags  = 0; /* write */
    msg[0].len   = 1;
    msg[0].buf   = &addr;
    msg[0].err   = 0;
    msg[0].cnt_transferred = -1;

    msg[1].addr  = 0x0f;
    msg[1].flags  = 1; /* read */
    msg[1].len   = len;
    msg[1].buf   = &data;
    msg[1].err   = 0;
    msg[1].cnt_transferred = -1;
    s3c2440_master_xfer(msg,2);
    delay10us(3);
    return data;
}

六、完整代码及Gsensor Kxte9相关资源下载

S5PV210用iic与KXTE9通信

标签:板载,cur,err,S5PV210,cnt,transferred,int,msg,坐标值
来源: https://blog.csdn.net/qq_27998025/article/details/121419553

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有