#include "driverapp.h"
#define I2C_DEVICE_ADDR 0x1d
#define I2C_WRITE_MODE 0
#define I2C_READ_MODE 1
#define CHIP_ID_REG 0x0d
#define CRTL_REG 0x2a
#define XYZ_DATA_REG 0x0e
#define OUT_XYZ_DATA_REG 0x01
#define clk_out() nxp_soc_gpio_set_io_dir(PAD_GPIO_D+6,1)
#define data_out() nxp_soc_gpio_set_io_dir(PAD_GPIO_D+7,1) //将gpioD7模式给输出
#define data_in() nxp_soc_gpio_set_io_dir(PAD_GPIO_D+7,0) //将gpioD7模式给输入
#define clk_set() nxp_soc_gpio_set_out_value(PAD_GPIO_D+6,1) //将gpioD6设置高电平
#define clk_clear() nxp_soc_gpio_set_out_value(PAD_GPIO_D+6,0) //将gpioD6设置低电平
#define data_set() nxp_soc_gpio_set_out_value(PAD_GPIO_D+7,1) //将gpioD7设置高电平
#define data_clear() nxp_soc_gpio_set_out_value(PAD_GPIO_D+7,0) //将gpioD7设置低电平
#define data_get() nxp_soc_gpio_get_in_value(PAD_GPIO_D+7)
#define demo_i2c_delay() udelay(50)
//封装发送起始信号函数
static void demo_i2c_start(void){
//时钟gpio输出
data_out();
//时钟为高
clk_set();
//数据为高
data_set();
//延时
demo_i2c_delay();
//数据为低
data_clear();
demo_i2c_delay();
//时钟为低
clk_clear();
}
//封装发送终止信号函数
static void demo_i2c_stop(void){
//时钟gpio输出
data_out();
//时钟为高
clk_set();
//数据为低
data_clear();
//延时
demo_i2c_delay();
//数据为高
data_set();
demo_i2c_delay();
//时钟为低
clk_clear();
}
//封装发送ack函数
static void demo_i2c_send_ack(unsigned char ack){
data_out();
clk_clear();
if(ack)
data_set();
else
data_clear();
demo_i2c_delay();
clk_set();
demo_i2c_delay();
clk_clear();
}
//封装接受ack函数
static unsigned char demo_i2c_receive_ack(void){
unsigned char ack = 0;
data_in();
clk_clear();
demo_i2c_delay();
clk_set();
demo_i2c_delay();
ack = data_get();
clk_clear();
return ack;
}
//封装发送8位数据函数
static void demo_i2c_send(unsigned char data){
signed char i;
data_out();
clk_clear();
for(i=7;i>=0;i--){
if(data&(1<<i))
data_set();
else
data_clear();
demo_i2c_delay();
clk_set();
demo_i2c_delay();
clk_clear();
}
}
static unsigned char demo_i2c_receive(void){
unsigned char data = 0;
signed char i;
data_in();
clk_clear();
for(i=7;i>=0;i--){
demo_i2c_delay();
clk_set();
demo_i2c_delay();
data |= (data_get()<<i);
clk_clear();
}
return data;
}
//模拟一次通信过程
static void demo_i2c_write_bytes(unsigned char *buf,unsigned char reg,int len)
{
int i=0;
demo_i2c_start();
demo_i2c_send((I2C_DEVICE_ADDR<<1)|I2C_WRITE_MODE);
if(demo_i2c_receive_ack())
demo_dbg("i2c write addr error!\n");
demo_i2c_send(reg);/* deivce address */
if(demo_i2c_receive_ack())
demo_dbg("i2c write reg error!\n");
while(len--)
{
demo_i2c_send(buf[i++]);/* send data */
if(demo_i2c_receive_ack())
demo_dbg("i2c write data error!\n");
}
demo_i2c_stop();
}
static void demo_i2c_read_bytes(unsigned char *buf,unsigned char reg,int len)
{
int i=0;
demo_i2c_start();
demo_i2c_send((I2C_DEVICE_ADDR<<1)|I2C_WRITE_MODE);
if(demo_i2c_receive_ack())
demo_dbg("i2c write addr error!\n");
demo_i2c_send(reg);/* deivce address */
if(demo_i2c_receive_ack())
demo_dbg("i2c write reg error!\n");
// demo_i2c_stop();
demo_i2c_start();
demo_i2c_send((I2C_DEVICE_ADDR<<1)|I2C_READ_MODE);
if(demo_i2c_receive_ack())
demo_dbg("i2c write addr error!\n");
#if 1
while(len--)
{
buf[i++] = demo_i2c_receive();
if(len >0)
demo_i2c_send_ack(0);
}
demo_i2c_send_ack(1);
#else
for(i=0;i<len;i++)
{
buf[i] = demo_i2c_receive();
demo_i2c_send_ack((len==1)?1:(i/(len-1)));/* 条件表达式保证最后一次发1其它为0 */
}
#endif
demo_i2c_stop();
}
static void demo_i2c_device_init(void)
{
unsigned char data = 0;
nxp_soc_gpio_set_io_func(PAD_GPIO_D+6,0);//初始化clk功能
nxp_soc_gpio_set_io_func(PAD_GPIO_D+7,0);//初始化sda功能
data_out();//将sda设置为输出
clk_out();//将clk设置为输出
demo_i2c_read_bytes(&data,CHIP_ID_REG,1);//读mmaID_REG寄存器值
demo_dbg("mma8653 chip id = 0x%x\n",data);
/* do enable 1 */
data |= 1;
demo_i2c_write_bytes(&data,CRTL_REG,1);//使能CRTL_REG为avtive
}
static int demo_i2c_open(struct inode *pinode, struct file *pfile)
{
demo_i2c_device_init();
return 0;
}
static int demo_i2c_close(struct inode *pinode, struct file *pfile)
{
unsigned char data = 0;
/* do desable 0 */
data &= ~1;
demo_i2c_write_bytes(&data,CRTL_REG,1);//关闭
return 0;
}
static ssize_t demo_i2c_read(struct file *pfile, char __user *pbuf, size_t count, loff_t *poffset)
{
unsigned char data[10] = {0};
short x,y,z;
demo_i2c_read_bytes(data,OUT_XYZ_DATA_REG,7);
x = (data[0]<<2)|(data[1]>>6);
y = (data[2]<<2)|(data[3]>>6);
z = (data[4]<<2)|(data[5]>>6);
x = (short)(x<<6)>>6;
y = (short)(y<<6)>>6;
z = (short)(z<<6)>>6;
demo_dbg("x=%03d,y=%03d,z=%03d\n",x,y,z);
mdelay(300);
return 1;
}
static struct file_operations demo_i2c_fops = {
.owner = THIS_MODULE,
.open = demo_i2c_open,
.release = demo_i2c_close,
.read = demo_i2c_read,
};
static struct miscdevice demo_i2c_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "demo_mma",
.fops = &demo_i2c_fops,
};
static int __init demo_i2c_init(void)
{
//注册杂项驱动
return misc_register(&demo_i2c_misc);
}
static void __exit demo_i2c_exit(void)
{
//注销杂项
misc_deregister(&demo_i2c_misc);
}
module_init(demo_i2c_init);
module_exit(demo_i2c_exit);
MODULE_LICENSE("Dual BSD/GPL"); //BSD/GPL双重许可证
MODULE_AUTHOR("edu"); //模块作者(可选)