S5PV210开发板板载Gsensor KXTE9读取XYZ坐标值
作者:互联网
Study210开发板板载Gsensor读取XYZ坐标值
- 一、板载Gsensor KXTE9需要用到的寄存器简介
- 二、S5PV210和2440在I2C通信上的区别
- 三、相关函数功能
- 四、程序运行结果
- 五、代码示例
- 六、完整代码及Gsensor Kxte9相关资源下载
声明:源代码是基于韦东山老师以及朱有鹏老师的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相关资源下载
标签:板载,cur,err,S5PV210,cnt,transferred,int,msg,坐标值 来源: https://blog.csdn.net/qq_27998025/article/details/121419553