MPU6050和HMC5883L的字符驱动程序

//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <mach/gpio.h>
#include <plat/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <mach/map.h>
#include <plat/devs.h>
#include <plat/regs-timer.h>
#include <plat/gpio-bank-m.h>
#include <plat/gpio-bank-p.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
//****************************************************************//
#define DEVICE_NAME	"sensor"
#define SENSOR_MAJOR 235
//****************************************************************//
//HM5883L register define
#define SENSOR_HM5883L 0
#define HM5883L_SLAVE_ADDRESS 0x3C

#define HM5883L_CONFIG_A 0x00
#define HM5883L_CONFIG_B 0x01
#define HM5883L_MODE 0x02
#define HM5883L_DATA_X_H 0x03
#define HM5883L_DATA_X_L 0x04
#define HM5883L_DATA_Z_H 0x05
#define HM5883L_DATA_Z_L 0x06
#define HM5883L_DATA_Y_H 0x07
#define HM5883L_DATA_Y_L 0x08
#define HM5883L_STATUS 0x09
#define HM5883L_IDENTIFICATION_A 0x10
#define HM5883L_IDENTIFICATION_B 0x11
#define HM5883L_IDENTIFICATION_C 0x12

//****************************************************************//
//mpu6050 register define
#define SENSOR_MPU6050 SENSOR_HM5883L+1
#define MPU6050_SLAVE_ADDRESS 0xD0

#define SELF_TEST_X 0x0D
#define SELF_TEST_Y 0x0E
#define SELF_TEST_Z 0x0F
#define SELF_TEST_A 0x10

#define SMPLRT_DIV  0x19 
#define CONFIG   0x1A 
#define GYRO_CONFIG  0x1B 
#define ACCEL_CONFIG 0x1C 

#define MOT_THR 0x1F

#define FIFO_EN 0x23

#define I2C_MST_CTRL 0x24

#define I2C_SLV0_ADDR 0x25
#define I2C_SLV0_REG 0x26
#define I2C_SLV0_CTRL 0x27
#define I2C_SLV0_DO 0x63

#define I2C_SLV1_ADDR 0x28
#define I2C_SLV1_REG 0x29
#define I2C_SLV1_CTRL 0x2A
#define I2C_SLV1_DO 0x64

#define I2C_SLV2_ADDR 0x2B
#define I2C_SLV2_REG 0x2C
#define I2C_SLV2_CTRL 0x2D
#define I2C_SLV2_DO 0x65

#define I2C_SLV3_ADDR 0x2E
#define I2C_SLV3_REG 0x2F
#define I2C_SLV3_CTRL 0x30
#define I2C_SLV3_DO 0x66

#define I2C_SLV4_ADDR 0x31
#define I2C_SLV4_REG 0x32
#define I2C_SLV4_DO  0x33
#define I2C_SLV4_CTRL 0x34
#define I2C_SLV4_DI 0x35

#define I2C_MST_STATUS 0x36
#define INT_PIN_CFG 0x37
#define INT_ENABLE 0x38
#define INT_STATUS 0x3A

#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H  0x41
#define TEMP_OUT_L  0x42
#define GYRO_XOUT_H  0x43
#define GYRO_XOUT_L  0x44
#define GYRO_YOUT_H  0x45
#define GYRO_YOUT_L  0x46
#define GYRO_ZOUT_H  0x47
#define GYRO_ZOUT_L  0x48

#define EXT_SENS_DATA_00 0x49
//........
#define EXT_SENS_DATA_23 0x60

#define I2C_MST_DELAY_CTRL 0x67
#define SIGNAL_PATH_RESET 0x68
#define MOT_DETECT_CTRL 0x69
#define USER_CTRL 0x6A
#define PWR_MGMT_1  0x6B
#define PWR_MGMT_2 0x6C
#define FIFO_COUNTH 0x72
#define FIFO_COUNTL 0x73
#define FIFO_R_W 0x74 
#define WHO_AM_I  0x75 
//****************************************************************//
#define SALVE_ADDRESS(type) (type==SENSOR_HM5883L?HM5883L_SLAVE_ADDRESS:MPU6050_SLAVE_ADDRESS)
#define SCL 1
#define SDA 9
#define uchar unsigned char
int sensor_data[10];
//****************************************************************//

struct sensor_ok6410_dev{
	
    struct cdev cdev_sensor;
	struct class *sensor_class;
	dev_t devno;
	atomic_t counter[5];
	//GPP Timer
	struct timer_list gpp_timer[5];
};
/**
 *传感器配置参数 
 * 
 * **/
 typedef struct sensor_config{
	unsigned char mpu6050_pwr_mgmt_1;
	unsigned char mpu6050_smplrt_div;
	unsigned char mpu6050_config;
	unsigned char mpu6050_gyro_config;
	unsigned char mpu6050_accel_config;
	unsigned char mpu6050_int_pin_cfg;
	unsigned char mpu6050_user_ctrl;
	unsigned char hm5883l_mode;
}Sensor_Config;	
//****************************************************************//
struct sensor_ok6410_dev *p_sensor_dev=NULL;
static void gpp_timer_ini_handler(unsigned long arg);
static void I2C_SendACK(int ack);
static char I2C_RecvByte(void);
static void Single_WriteI2C(int type,char REG_Address, char REG_data);
static void InitMPU6050_HM5883L(void);
static void I2C_RecvACK(void);

static void I2C_Start_Stop(int key) {	
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));//out
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));//out
	if(key==1){
		gpio_set_value(S3C64XX_GPP(SCL), 1);
		gpio_set_value(S3C64XX_GPP(SDA), 1);
		udelay(5);
		gpio_set_value(S3C64XX_GPP(SDA), 0);
		udelay(5);
		gpio_set_value(S3C64XX_GPP(SCL), 0);
	}
	else
	{
		gpio_set_value(S3C64XX_GPP(SCL), 1);
		gpio_set_value(S3C64XX_GPP(SDA), 0);
		udelay(5);
		gpio_set_value(S3C64XX_GPP(SDA), 1);
		udelay(5);
	}
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));	
}
static void I2C_SendACK(int ack) {
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));
	
	gpio_set_value(S3C64XX_GPP(SDA), ack);
	gpio_set_value(S3C64XX_GPP(SCL), 1);
	udelay(5);
	gpio_set_value(S3C64XX_GPP(SCL), 0);	
	udelay(5);
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));	
}
static void I2C_RecvACK(){
    int ack;
    s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));
	gpio_set_value(S3C64XX_GPP(SCL), 1);
	udelay(5);
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(0));	
	ack=gpio_get_value(S3C64XX_GPP(SDA));
	gpio_set_value(S3C64XX_GPP(SCL), 0);
	udelay(5);
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));	
}
static void I2C_SendByte(char dat) {
	char i;
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));//out
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));//out
	for (i = 0; i < 8; i++)
	{
		gpio_set_value(S3C64XX_GPP(SDA), dat&0x80);
		gpio_set_value(S3C64XX_GPP(SCL), 1);
		udelay(5);
		gpio_set_value(S3C64XX_GPP(SCL), 0);
		udelay(5);
		dat <<= 1;
	}
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));	
	I2C_RecvACK();
}
static char I2C_RecvByte(void) {
	char i,dat = 0;
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(1));
	gpio_set_value(S3C64XX_GPP(SDA), 1);
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(0));
	for (i = 0; i < 8; i++)
	{
		dat <<=1;
		gpio_set_value(S3C64XX_GPP(SCL), 1);
		udelay(5);
			dat |=gpio_get_value(S3C64XX_GPP(SDA)); 
		gpio_set_value(S3C64XX_GPP(SCL), 0);
		udelay(5);
	}
	s3c_gpio_cfgpin(S3C64XX_GPP(SCL), S3C_GPIO_SFN(0));
	s3c_gpio_cfgpin(S3C64XX_GPP(SDA), S3C_GPIO_SFN(0));
	return dat;
}


/**
 *Single Byte Write 
 * M |S AD+W   RA   DATA   P
 * S |      ACK  ACK    ACK  
 ***/
static void Single_WriteI2C(int type,char REG_Address, char REG_data) {
	
	I2C_Start_Stop(1);          //S
	I2C_SendByte((char)SALVE_ADDRESS(type)); //AD+W
	I2C_SendByte(REG_Address);  //RA
	I2C_SendByte(REG_data); 	//DATA	
	I2C_Start_Stop(0);          //P
}

/**
 *Continous Byte Write 
 * M |S AD+W   RA   DATA   DATA   P
 * S |      ACK  ACK    ACK    ACK
 ***/
static void Continous_WriteI2C(int type,char REG_Address, char REG_data[2]) {
	I2C_Start_Stop(1);          //S
	I2C_SendByte((char)SALVE_ADDRESS(type)); //AD+W 
	I2C_SendByte(REG_Address);  //RA
	I2C_SendByte(REG_data[1]);     //DATA1
	I2C_SendByte(REG_data[0]);     //DATA0  
	I2C_Start_Stop(0);          //P
}

/**
 *Single Byte Read 
 * M |S AD+W   RA   S AD+R        NACK P
 * S |      ACK  ACK      ACK DATA  
 ***/
static signed char Single_ReadI2C(int type,char REG_Address) {
	signed char REG_data;
	
	I2C_Start_Stop(1);                 //S 
	I2C_SendByte((char)SALVE_ADDRESS(type) + 0);    //AD+W
	I2C_SendByte(REG_Address);         //RA
	
	I2C_Start_Stop(1);                 //S
	I2C_SendByte((char)SALVE_ADDRESS(type) + 1);    //AD+R
	REG_data = I2C_RecvByte();//DATA           
		
	I2C_SendACK(0);                    //NACK
	I2C_Start_Stop(0);                 //P
	return REG_data;
}

/**
 *Continous Byte Read 
 * M |S AD+W   RA   S AD+R        ACK    NACK P
 * S |      ACK  ACK      ACK DATA   DATA
 ***/
static char* Continous_ReadI2C(int type,char REG_Address) {
	char REG_data[2];
	
	I2C_Start_Stop(1);                //S 
	I2C_SendByte((char)SALVE_ADDRESS(type) + 0);   //AD+W 
	I2C_SendByte(REG_Address);        //RA
	
	I2C_Start_Stop(1);                //S 
	I2C_SendByte((char)SALVE_ADDRESS(type) + 1);   //AD+R  
	  
	REG_data[0] = I2C_RecvByte();//DATA H
	I2C_SendACK(1);                   //ACK
	REG_data[1] = I2C_RecvByte();//DATA L
	I2C_SendACK(0);                   //NACK 
	I2C_Start_Stop(0);                //P
	return (char*)REG_data;
}

static void InitMPU6050_HM5883L(void) {
	Single_WriteI2C(SENSOR_MPU6050,PWR_MGMT_1, 0x00); 
	Single_WriteI2C(SENSOR_MPU6050,SMPLRT_DIV, 0x07);
	Single_WriteI2C(SENSOR_MPU6050,CONFIG, 0x06);
	Single_WriteI2C(SENSOR_MPU6050,GYRO_CONFIG, 0x18);
	Single_WriteI2C(SENSOR_MPU6050,ACCEL_CONFIG, 0x00);
	Single_WriteI2C(SENSOR_MPU6050,INT_PIN_CFG,1<<1);
	Single_WriteI2C(SENSOR_MPU6050,USER_CTRL,0<<5);
	//open hm5883l
	Single_WriteI2C(SENSOR_HM5883L,HM5883L_MODE,0x00);
}	

static void GetSensorData(int type,char REG_Address,int *result) {
	signed char H;
	unsigned char L;
	H = Single_ReadI2C(type,REG_Address);
	L = Single_ReadI2C(type,REG_Address + 1);
	*result =(int)((H << 8)|L);
}

static ssize_t  s3c6410_sensor_read(struct file *filp, int __user *buf, ssize_t len)
{
	int i=0;
	int *pbuf=buf;

	InitMPU6050_HM5883L();	
		//mpu6050
		GetSensorData(SENSOR_MPU6050,ACCEL_XOUT_H , &sensor_data[0]);
		GetSensorData(SENSOR_MPU6050,ACCEL_YOUT_H , &sensor_data[1]);
		GetSensorData(SENSOR_MPU6050,ACCEL_ZOUT_H ,&sensor_data[2]);
		GetSensorData(SENSOR_MPU6050,GYRO_XOUT_H , &sensor_data[3]);
		GetSensorData(SENSOR_MPU6050,GYRO_YOUT_H , &sensor_data[4]);
		GetSensorData(SENSOR_MPU6050,GYRO_ZOUT_H , &sensor_data[5]);
		//mpu6050
		GetSensorData(SENSOR_MPU6050,TEMP_OUT_H , &sensor_data[6]);		
		//hm5883l
		GetSensorData(SENSOR_HM5883L,HM5883L_DATA_X_H,&sensor_data[7]);
		GetSensorData(SENSOR_HM5883L,HM5883L_DATA_Y_H,&sensor_data[8]);
		GetSensorData(SENSOR_HM5883L,HM5883L_DATA_Z_H,&sensor_data[9]);
		if(false){
			printk(KERN_EMERG "Acc: %d %d %d  Gyro: %d %d %d Compass: : %d %d %d\n",
							sensor_data[0],sensor_data[1],sensor_data[2],
							sensor_data[3],sensor_data[4],sensor_data[5],
							sensor_data[6],sensor_data[7],sensor_data[8]);
	    }
	for(i=0;i<sizeof(sensor_data)/sizeof(sensor_data[0]);i++){	
		copy_to_user(pbuf+i,&sensor_data[i],sizeof(sensor_data[i]));	
	}
	return (ssize_t)sizeof(sensor_data);
}

static DEFINE_TIMER(gpp_timer1, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer8, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer9, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer12, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer13, gpp_timer_ini_handler, 20, 0);

/*定时器处理函数*/
static void gpp_timer_ini_handler(unsigned long arg)
{
	mod_timer(&p_sensor_dev->gpp_timer[arg],jiffies + HZ);
	atomic_inc(&p_sensor_dev->counter[arg]);
}

/*设备打开函数*/
static int s3c6410_sensor_open(
		struct inode *inode,
		struct file *file)
{
	/*初始化定时器*/
	int i=0;
	for(i=0;i<5;i++){
		init_timer(&p_sensor_dev->gpp_timer[i]);
		p_sensor_dev->gpp_timer[i].function = &gpp_timer_ini_handler;
		p_sensor_dev->gpp_timer[i].expires = jiffies + HZ;
		p_sensor_dev->gpp_timer[i].data=(unsigned long)i;
		add_timer(&p_sensor_dev->gpp_timer[i]);
		atomic_set(&p_sensor_dev->counter[i],0);//计数0
	}
	//sensor initial
	InitMPU6050_HM5883L();	
	return 0;
}

/*设备释放函数*/
static int s3c6410_sensor_release(
		struct inode *inode,
		struct file *file)
{
	int i=0;
	for(i=0;i<5;i++){
		del_timer(&p_sensor_dev->gpp_timer[i]);
	}
	return 0;
}

/**
 * arg:0~2000
 * */
static int s3c6410_sensor_ioctl(
		struct inode *inode,
		struct file *file,
		unsigned int cmd,
		unsigned long arg) {
	switch (cmd) {
	case -1:		
	case 0:	
		return 0;	
	default:
		return -EINVAL;
	}
}

static struct file_operations s3c6410_sensor_fops = {
		.owner = THIS_MODULE,	
		.open =  s3c6410_sensor_open,
		.release = s3c6410_sensor_release,
		.ioctl = s3c6410_sensor_ioctl,
		.read = s3c6410_sensor_read,
};

/*设备初始化*/
static int __init s3c6410_sensor_init(void)
{
	unsigned long tmp;
	int ret=0;
	p_sensor_dev = (struct sensor_ok6410_dev *)kmalloc(sizeof(struct sensor_ok6410_dev),GFP_KERNEL);
	if(!p_sensor_dev)
	{
		ret=- ENOMEM;
		goto fail_malloc;
	}	
	if(alloc_chrdev_region(&p_sensor_dev->devno, 0,1, DEVICE_NAME)<0)
	{
		return ret;
	}	
	cdev_init(&p_sensor_dev->cdev_sensor,&s3c6410_sensor_fops);
	p_sensor_dev->cdev_sensor.owner = THIS_MODULE;
	ret =cdev_add(&p_sensor_dev->cdev_sensor,p_sensor_dev->devno,1);
	if(ret)
	{
		return ret;
	}
	p_sensor_dev->sensor_class = class_create(THIS_MODULE,DEVICE_NAME);
	if(IS_ERR(p_sensor_dev->sensor_class))
	{
		return -1;
	}
	device_create(p_sensor_dev->sensor_class,NULL,MKDEV(MAJOR(p_sensor_dev->devno),0),NULL,DEVICE_NAME);
	//gpm0-3 pull up
	tmp = __raw_readl(S3C64XX_GPMPUD);
	tmp &= (~0xFF);
	tmp |= 0xaa;            // 10101010
	__raw_writel(tmp,S3C64XX_GPMPUD);

	//gpm0-3 output mode
	tmp = __raw_readl(S3C64XX_GPMCON);
	tmp &= (~0xFFFF);
	tmp |= 0x1111;
	__raw_writel(tmp,S3C64XX_GPMCON);

	//gpm0-3 output 0
	tmp = __raw_readl(S3C64XX_GPMDAT);
	tmp |= 0x10;
	__raw_writel(tmp,S3C64XX_GPMDAT);
	
	//*****************************************************//
	gpp-1-8-9-12-13 pull up
	tmp = __raw_readl(S3C64XX_GPPPUD);
	tmp &= (~0xFFFF);
	tmp |= 0xaaaaaaaa;              //0000 1010 0000 1010 , 0000 0000 0000 1000  pull down
	__raw_writel(tmp,S3C64XX_GPPPUD);

	//gpp-1-8-9-12-13 output mode
	tmp = __raw_readl(S3C64XX_GPPCON);
	tmp &= (~0xFFFF);
	tmp |= 0x05050004;             // 0000 0101 0000 0101 , 0000 0000 0000 0100  output mode
	__raw_writel(tmp,S3C64XX_GPPCON);

	//gpp-1-8-9-12-13 output 0
	tmp = __raw_readl(S3C64XX_GPPDAT);
	tmp &= (~0xFFFF);
	__raw_writel(tmp,S3C64XX_GPPDAT);
	//*****************************************************//
	return 0;
	fail_malloc: unregister_chrdev_region(p_sensor_dev->devno,1);
	return -1;
}

static void __exit s3c6410_sensor_exit(void)
{
	unregister_chrdev_region(MKDEV(SENSOR_MAJOR,0),1);
	device_destroy(p_sensor_dev->sensor_class,MKDEV(MAJOR(p_sensor_dev->devno),0));
	cdev_del(&p_sensor_dev->cdev_sensor);	
	class_destroy(p_sensor_dev->sensor_class);	
	kfree(p_sensor_dev);	
	return;
}

module_init( s3c6410_sensor_init);
module_exit( s3c6410_sensor_exit);

MODULE_AUTHOR("clare liu 2013/11/15");
MODULE_LICENSE("GPL");


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值