《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 其他 > Linux驅(qū)動開發(fā)-編寫MMA7660三軸加速度傳感器

Linux驅(qū)動開發(fā)-編寫MMA7660三軸加速度傳感器

2022-09-29
來源:電子發(fā)燒友網(wǎng)
關(guān)鍵詞: 加速度傳感器 mma7660 芯片

  【摘要】 通過MMA7660可以做出很多項目: 比如: 老人防跌倒手環(huán)、自行車自動剎車燈,智能鬧鐘,烤火爐跌倒自動斷電、運動手環(huán)等等。 這篇文章就介紹如何在Linux下編寫MMA7660三軸加速度芯片的驅(qū)動,讀取當(dāng)前芯片的方向姿態(tài),得到X,Y,Z三個軸的數(shù)據(jù)。MMA7660是IIC接口的,當(dāng)前驅(qū)動就采用標準的IIC子系統(tǒng)編寫驅(qū)動,使用字符設(shè)備框架將得到的數(shù)據(jù)上傳遞給應(yīng)用層。

  1. MMA7660芯片介紹

  MMA7660FC 是 ± 1.5 克的三軸數(shù)字輸出、超低功率、緊湊型電容式微電機的三軸加速度計,是非常低功耗,小型容性 MEMS 的傳感器。具有低通濾波器,用于偏移和增益誤差補償, 以及用戶可配置的轉(zhuǎn)換成 6 位分辨率,用戶可配置輸出速率等功能。MMA7660芯片可以通過中斷引腳(INT)向外通知傳感器數(shù)據(jù)變化、方向、姿態(tài)識別等信息。模擬工作電壓范圍是 2.4V 至 3.6V,數(shù)字工作電壓范圍是 1.71V 到 3.6V 。常用在手機、掌上電腦、車載導(dǎo)航,便攜式電腦的防盜,自動自行車剎車燈、運動檢測手環(huán)、數(shù)碼機、自動叫醒鬧鐘里等等。

  特別是計步的功能是現(xiàn)在最常見,不管是智能手環(huán)、還是手機都帶有三軸加速度計,可以記錄每天的步數(shù),計算運動量等。現(xiàn)在很多的不倒翁,無人機、相機云臺,很多常見的產(chǎn)品里都能看到三軸加速計的身影。

  通過MMA7660可以做出很多項目: 比如: 老人防跌倒手環(huán)、自行車自動剎車燈,智能鬧鐘,烤火爐跌倒自動斷電、運動手環(huán)等等。

  這篇文章就介紹如何在Linux下編寫MMA7660三軸加速度芯片的驅(qū)動,讀取當(dāng)前芯片的方向姿態(tài),得到X,Y,Z三個軸的數(shù)據(jù)。MMA7660是IIC接口的,當(dāng)前驅(qū)動就采用標準的IIC子系統(tǒng)編寫驅(qū)動,使用字符設(shè)備框架將得到的數(shù)據(jù)上傳遞給應(yīng)用層。

12.JPG

  2. 硬件連線

  當(dāng)前使用的開發(fā)板是友善之臂Tiny4412開發(fā)板,使用三星EXYNOS4412芯片,板子本身自帶了一顆MMA7660芯片,芯片的原理圖如下:

 11.JPG

  內(nèi)核本身有MMA7660的驅(qū)動,下面是源碼的路徑:

 10.JPG

09.JPG

  如果加載自己編寫的驅(qū)動,還需要去掉原來內(nèi)核自帶的驅(qū)動,不然無法匹配。

  Device Drivers  --->

  <*> Hardware Monitoring support  --->

  <*>   Freescale MMA7660 Accelerometer   (將*號去掉,編譯內(nèi)核、燒寫內(nèi)核即可)

08.JPG

  3. 源代碼

  3.1 mma7660設(shè)備端代碼: IIC子系統(tǒng)

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  static struct i2c_client *i2cClient = NULL;

  static unsigned short  i2c_addr_list[]= {0x4c, I2C_CLIENT_END};/*地址隊列*/

  /*

  1. 獲取控制器(總線)

  2. 探測設(shè)備是否存在

  3. 定義一個名字用于找到驅(qū)動端

  */

  static int __init mma7660_dev_init(void)

  {

  /*mach-tiny4412.c*/

  struct i2c_adapter *i2c_adap=NULL;  /*獲取到的總線存放在這個結(jié)構(gòu)體*/

  struct i2c_board_info i2c_info;     /*設(shè)備描述結(jié)構(gòu)體,里面存放著設(shè)備的名字還有地址*/

  /*1. 獲取IIC控制器*/

  i2c_adap = i2c_get_adapter(3);     /*要使用IIC_3號總線*/

  if(!i2c_adap)

  {

  printk(“獲取IIC控制器信息失敗!\n”);

  return -1;

  }

  memset(&i2c_info,0,sizeof(struct i2c_board_info));      /*清空結(jié)構(gòu)體*/

  strlcpy(i2c_info.type,“mma7660_drv”,I2C_NAME_SIZE);    /*名稱的賦值*/

  i2c_info.irq=EXYNOS4_GPX3(1); /*中斷IO口*/

  /*2. 創(chuàng)建IIC設(shè)備客戶端*/

  i2cClient = i2c_new_probed_device(i2c_adap,&i2c_info,i2c_addr_list,NULL);

  if(!i2cClient)

  {

  printk(“mma7660_探測地址出現(xiàn)錯誤!!\n”);

  return -1;

  }

  i2c_put_adapter(i2c_adap);/*設(shè)置模塊使用計數(shù)*/

  printk(“mma7660_dev_init!!\n”);

  return 0;

  }

  static void __exit mma7660_dev_exit(void)//平臺設(shè)備端的出口函數(shù)

  {

  printk(“ mma7660_dev_exit ok!!\n”);

  /*注銷設(shè)備*/

  i2c_unregister_device(i2cClient);

  /*釋放*/

  i2c_release_client(i2cClient);

  }

  module_init(mma7660_dev_init);

  module_exit(mma7660_dev_exit);

  MODULE_LICENSE(“GPL”);

  3.2 mma7660驅(qū)動端代碼: IIC子系統(tǒng)

  復(fù)制

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  /* MMA7760 Registers */

  #define MMA7660_XOUT0x00// 6-bit output value X

  #define MMA7660_YOUT0x01// 6-bit output value Y

  #define MMA7660_ZOUT0x02// 6-bit output value Z

  #define MMA7660_TILT0x03// Tilt status

  #define MMA7660_SRST0x04// Sampling Rate Status

  #define MMA7660_SPCNT0x05// Sleep Count

  #define MMA7660_INTSU0x06// Interrupt Setup

  #define MMA7660_MODE0x07// Mode

  #define MMA7660_SR0x08// Auto-Wake/Sleep and Debounce Filter

  #define MMA7660_PDET0x09// Tap Detection

  #define MMA7660_PD0x0a// Tap Debounce Count

  static const struct i2c_device_id mma7660_id[] =

  {

  {“mma7660_drv”,0}, /*設(shè)備端的名字,0表示不需要私有數(shù)據(jù)*/

  {}

  };

  static u32 mma7660_irq; /*觸摸屏的中斷編號*/

  static struct i2c_client *mma7660_client=NULL;

  static intlast_tilt = 0;

  #define __need_retry(__v)(__v & (1 《 6))

  #define __is_negative(__v)(__v & (1 《 5))

  static const char *mma7660_bafro[] = {

  “未知”, “前面”, “背面”

  };

  static const char *mma7660_pola[] = {

  “未知”,

  “左面”, “向右”,

  “保留”, “保留”,

  “向下”, “向上”,

  “保留”,

  };

  /*

  函數(shù)功能:讀取一個字節(jié)的數(shù)據(jù)

  */

  static int mma7660_read_tilt(struct i2c_client *client, int *tilt)

  {

  int val;

  do {

  val = i2c_smbus_read_byte_data(client, MMA7660_TILT);

  } while (__need_retry(val));

  *tilt = (val & 0xff);

  return 0;

  }

  /*

  函數(shù)功能: 讀取XYZ坐標數(shù)據(jù)

  */

  static int mma7660_read_xyz(struct i2c_client *client, int idx, int *xyz)

  {

  int val;

  do {

  val = i2c_smbus_read_byte_data(client, idx + MMA7660_XOUT);

  } while (__need_retry(val));

  *xyz = __is_negative(val) ? (val | ~0x3f) : (val & 0x3f);

  return 0;

  }

  /*

  工作隊列處理函數(shù)

  */

  static void mma7660_worker(struct work_struct *work)

  {

  int bafro, pola, shake, tap;

  int val = 0;

  mma7660_read_tilt(mma7660_client,&val);

  /* TODO: report it ? */

  bafro = val & 0x03;

  if (bafro != (last_tilt & 0x03)) {

  printk(“%s\n”, mma7660_bafro[bafro]);

  }

  pola = (val 》 2) & 0x07;

  if (pola != ((last_tilt 》 2) & 0x07)) {

  printk(“%s\n”, mma7660_pola[pola]);

  }

  shake = (val 》 5) & 0x01;

  if (shake && shake != ((last_tilt 》 5) & 0x01)) {

  printk(“Shake\n”);

  }

  tap = (val 》 7) & 0x01;

  if (tap && tap != ((last_tilt 》 7) & 0x01)) {

  printk(“Tap\n”);

  }

  /* Save current status */

  last_tilt = val;

  int axis[3];

  int i;

  for (i = 0; i < 3; i++)

  {

  mma7660_read_xyz(mma7660_client, i, &axis[i]);

  }

  printk(“ABS_X=%d\n”,axis[0]);

  printk(“ABS_Y=%d\n”,axis[1]);

  printk(“ABS_Z=%d\n”,axis[2]);

  }

  /*

  函數(shù)功能: mma7660初始化

  */

  static int mma7660_initialize(struct i2c_client *client)

  {

  int val;

  /* Using test mode to probe chip */

  i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x00);

  mdelay(10);

  i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x04);

  mdelay(10);

  i2c_smbus_write_byte_data(client, MMA7660_XOUT, 0x3f);

  i2c_smbus_write_byte_data(client, MMA7660_YOUT, 0x01);

  i2c_smbus_write_byte_data(client, MMA7660_ZOUT, 0x15);

  val = i2c_smbus_read_byte_data(client, MMA7660_ZOUT);

  if (val != 0x15) {

  dev_err(&client->dev, “no device\n”);

  return -ENODEV;

  }

  /* Goto standby mode for configuration */

  i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x00);

  mdelay(10);

  /* Sample rate: 64Hz / 16Hz; Filt: 3 samples  */

  i2c_smbus_write_byte_data(client, MMA7660_SR, ((2《5) | (1《3) | 1));

  /* Sleep count */

  i2c_smbus_write_byte_data(client, MMA7660_SPCNT, 0xA0);

  /* Tap detect and debounce ~4ms */

  i2c_smbus_write_byte_data(client, MMA7660_PDET, 4);

  i2c_smbus_write_byte_data(client, MMA7660_PD, 15);

  /* Enable interrupt except exiting Auto-Sleep */

  i2c_smbus_write_byte_data(client, MMA7660_INTSU, 0xe7);

  /* IPP, Auto-wake, auto-sleep and standby */

  i2c_smbus_write_byte_data(client, MMA7660_MODE, 0x59);

  mdelay(10);

  /* Save current tilt status */

  mma7660_read_tilt(client, &last_tilt);

  mma7660_client = client;

  return 0;

  }

  /*

  靜態(tài)方式初始化工作隊列

  */

  DECLARE_WORK(mma7660_work,mma7660_worker);

  static irqreturn_t mma7660_interrupt(int irq, void *dev_id)

  {

  /*調(diào)度共享工作隊列*/

  schedule_work(&mma7660_work);

  return IRQ_HANDLED;

  }

  /*

  匹配成功時調(diào)用

  */

  static int mma7660_probe(struct i2c_client *client, const struct i2c_device_id *device_id)

  {

  printk(“mma7660_probe!!!\n”);

  printk(“驅(qū)動端IIC匹配的地址=0x%x\n”,client->addr);

  mma7660_client=client;

  /*1. 注冊中斷*/

  mma7660_irq=gpio_to_irq(client->irq);/*獲取中斷編號*/

  if(request_irq(mma7660_irq,mma7660_interrupt,IRQF_TRIGGER_FALLING,“mma7660_irq”,NULL)!=0)

  {

  printk(“mma7660_中斷注冊失敗!\n”);

  }

  /*2. 初始化mma7660*/

  if(mma7660_initialize(client) < 0)

  {

  printk(“ 初始化mma7660失敗!\n”);

  }

  return 0;

  }

  static int mma7660_remove(struct i2c_client *client)

  {

  free_irq(mma7660_irq,NULL);

  printk(“mma7660_remove!!!\n”);

  return 0;

  }

  struct i2c_driver i2c_drv =

  {

  .driver =

  {

  .name = “mma7660”,

  .owner = THIS_MODULE,

  },

  .probe = mma7660_probe,   //探測函數(shù)

  .remove = mma7660_remove, //資源卸載

  .id_table = mma7660_id,   //里面有一個名字的參數(shù)用來匹配設(shè)備端名字

  };

  static int __init mma7660_drv_init(void)

  {

  /*向iic總線注冊一個驅(qū)動*/

  i2c_add_driver(&i2c_drv);

  return 0;

  }

  static void __exit mma7660_drv_exit(void)

  {

  /*從iic總線注銷一個驅(qū)動*/

  i2c_del_driver(&i2c_drv);

  }

  module_init(mma7660_drv_init);

  module_exit(mma7660_drv_exit);

  MODULE_LICENSE(“GPL”);



更多信息可以來這里獲取==>>電子技術(shù)應(yīng)用-AET<<

mmexport1621241704608.jpg

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
亚洲国产精品成人久久综合一区| 午夜精品影院在线观看| 国产目拍亚洲精品99久久精品 | 亚洲欧美资源在线| 亚洲午夜在线观看视频在线| 亚洲精品国产精品国自产观看浪潮| 性视频1819p久久| 午夜精品久久久久久久蜜桃app| 宅男在线国产精品| 一区二区欧美国产| 一本色道久久综合亚洲精品不卡| 亚洲人成艺术| 91久久精品一区二区三区| 亚洲二区在线| 亚洲韩国青草视频| 亚洲激情国产精品| 亚洲精品国产日韩| 99伊人成综合| 亚洲一卡二卡三卡四卡五卡| 亚洲天堂偷拍| 亚洲欧美激情四射在线日| 午夜精彩视频在线观看不卡| 欧美有码视频| 亚洲国产精品电影在线观看| 亚洲欧洲日本一区二区三区| 亚洲精品综合| 一区二区精品| 亚洲欧美日韩精品久久奇米色影视| 亚洲一区影院| 久久av一区二区三区| 久久久中精品2020中文| 欧美成人免费在线观看| 欧美另类videos死尸| 欧美体内she精视频在线观看| 国产精品久久久久久久久久免费| 国产欧美日韩三级| 国产在线精品自拍| 亚洲国语精品自产拍在线观看| 日韩视频精品在线| 亚洲欧美中日韩| 亚洲国产婷婷香蕉久久久久久99| 99re6这里只有精品| 亚洲综合99| 久久视频精品在线| 欧美精品久久久久久久久老牛影院 | 欧美理论片在线观看| 欧美性开放视频| 国产日产亚洲精品系列| 亚洲第一天堂av| 亚洲天堂成人| 最新亚洲视频| 欧美一区二区在线观看| 免费亚洲一区| 国产精品视频成人| 一区在线视频观看| 亚洲私拍自拍| 亚洲国产经典视频| 亚洲视频一区| 美国三级日本三级久久99| 国产精品a久久久久| 国产一区久久| 中国成人亚色综合网站| 亚洲福利精品| 亚洲一区二区四区| 麻豆91精品| 国产精品一级久久久| 亚洲经典视频在线观看| 欧美一区二区三区视频免费播放| 亚洲精品在线观| 欧美婷婷久久| 亚洲欧洲日产国产网站| 亚洲欧美韩国| 欧美激情一区二区三区在线视频 | 亚洲综合首页| 亚洲免费av观看| 欧美一区二区高清| 欧美日韩麻豆| 亚洲成色最大综合在线| 新狼窝色av性久久久久久| 中文在线资源观看网站视频免费不卡 | 亚洲综合二区| 欧美激情综合在线| 黑丝一区二区| 亚洲综合清纯丝袜自拍| 一区二区三区高清在线| 久久综合色天天久久综合图片| 国产精品爽爽爽| 99re6这里只有精品| 亚洲精品视频在线观看免费| 久久久久国产一区二区| 国产精品美女| 夜夜嗨av一区二区三区免费区| 亚洲三级电影在线观看| 久久亚裔精品欧美| 国产一区二区三区日韩| 亚洲欧美99| 亚洲欧美日韩视频二区| 欧美日韩综合| 亚洲美女福利视频网站| 亚洲日本中文字幕| 男女精品视频| 在线精品视频一区二区| 亚洲电影av在线| 久久久久www| 国产午夜精品久久久久久久| 亚洲一区二区成人| 亚洲欧美日本国产有色| 国产精品国产三级欧美二区 | 欧美视频二区| 亚洲伦伦在线| 在线视频精品一| 欧美日韩卡一卡二| 亚洲免费成人av| 一区二区三区四区五区精品视频| 久久综合狠狠综合久久综合88| 国产一区二区久久精品| 欧美在线不卡视频| 久久免费视频网站| 国产综合久久| 久久精品国产91精品亚洲| 久久视频一区二区| 伊人久久综合| 亚洲日本欧美| 欧美日本亚洲视频| 日韩亚洲成人av在线| 亚洲一区二区在线观看视频| 国产精品第三页| 亚洲欧美久久久久一区二区三区| 小辣椒精品导航| 国产亚洲精品久久久| 久久精品99无色码中文字幕| 久久综合福利| 亚洲国产精品久久| 日韩一区二区免费看| 欧美视频一区在线| 亚洲伊人伊色伊影伊综合网| 欧美一区中文字幕| 激情综合亚洲| 艳妇臀荡乳欲伦亚洲一区| 国产精品igao视频网网址不卡日韩| 亚洲视频第一页| 久久精品国产免费看久久精品| 黑人操亚洲美女惩罚| 日韩午夜av电影| 欧美午夜一区二区三区免费大片 | 欧美一区二区日韩一区二区| 国产色视频一区| 亚洲国产电影| 欧美精品一区二区三区蜜桃| 亚洲天堂成人在线观看| 久久嫩草精品久久久精品一| 亚洲国产一区二区精品专区| 这里只有精品丝袜| 国产喷白浆一区二区三区| 亚洲电影网站| 欧美日韩一二区| 午夜视频一区二区| 蜜月aⅴ免费一区二区三区| a4yy欧美一区二区三区| 久久国产视频网站| 亚洲精品午夜| 久久成人免费电影| 亚洲精品国产精品国产自| 午夜在线一区二区| 在线日韩欧美| 亚洲男人的天堂在线| 海角社区69精品视频| 一区二区三区四区五区精品视频| 国产欧美一区二区精品秋霞影院| 亚洲国产综合在线| 国产精品嫩草99a| 亚洲国产天堂久久综合| 欧美色偷偷大香| 亚洲国产美女| 国产精品久久久久久久久免费樱桃 | 国产精品腿扒开做爽爽爽挤奶网站| 久久狠狠婷婷| 国产精品国产三级国产aⅴ9色| 久久精品一区二区| 国产精品国内视频| 亚洲区一区二区三区| 国产精品久久久久一区二区三区 | 久久国产精品一区二区| 欧美日韩在线视频一区二区| 久久不射2019中文字幕| 欧美色图首页| 亚洲精品老司机| 国产亚洲va综合人人澡精品| 亚洲婷婷免费| 一区二区自拍| 欧美资源在线观看| 99精品久久久| 噜噜噜噜噜久久久久久91 | 午夜天堂精品久久久久| 欧美日韩成人综合在线一区二区| 欧美中文字幕视频| 国产精品亚洲综合天堂夜夜| 在线亚洲精品| 亚洲国产精品一区二区第四页av| 久久成人国产精品|