你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【基于stm32的rt-thread IIC 驱动框架适配KX224加速度传感器】

[复制链接]
andeyqi 发布时间:2019-6-21 13:07
本帖最后由 andeyqi 于 2019-6-21 13:07 编辑

依据上一篇对rt-thread I2C软件框架的分析,应用层调用I2C框架的接口就可以通过系统注册的总线设备,完成对应外设的控制。本次试验的芯片型号为ROHM 的i2c 三轴加速度传感器(KX224=1053)系列。
应用层只需使用 struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) 函数找到对应的总线设备,并通过返回的 rt_i2c_bus_device  句柄操作外设,通过rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg  msgs[],rt_uint32_t  num)控制总线完成数据的发送接收,用户层不必关系IIC总线的相关操作,从而减少开发周期,用户只需关系芯片先关的操作即可。

===========================以下进入本次的主题==========================


虽然datasheet中寄存器的描述有很多,不过根据官方的使用说明文档,要想获得三轴加速度的信息,只需设定几个参数即可,设定加速度传感器的测量范围,及输出频率,和工作模式后就能够从芯片的X,Y,Z通道读取出三轴加速度信息。

async_acc.png

本次试验使用的BSP为官方已经适配支持\rt-thread\bsp\stm32\stm32l476-st-nucleo 开发板,进入该目录后env工具执行menuconfig配置界面开启I2C1并设置SCL和SDA线的引脚ID后I2C驱动框架相关的代码就会加入工程中进行编译。
  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <board.h>
  4. #include "kx224.h"

  5. static rt_err_t write_reg(struct rt_i2c_bus_device *bus,rt_uint8_t reg,rt_uint8_t data)
  6. {
  7.         struct rt_i2c_msg msgs;
  8.         rt_uint8_t buff[2];
  9.         rt_size_t size = 0;
  10.         
  11.         buff[0] = reg;
  12.         buff[1] = data;

  13.         msgs.addr = KX224_DEVICE_ADDRESS_1E;
  14.         msgs.flags = RT_I2C_WR;
  15.         msgs.buf = buff;
  16.         msgs.len = 2;

  17.         if( rt_i2c_transfer(bus, &msgs, 1))
  18.         {
  19.                 return RT_EOK;
  20.         }
  21.         else
  22.         {
  23.                 return -RT_ERROR;
  24.         }
  25. }

  26. static rt_err_t write_cmd(struct rt_i2c_bus_device *bus,rt_uint8_t reg)
  27. {
  28.         struct rt_i2c_msg msgs;
  29.         rt_uint8_t buff[2];
  30.         rt_size_t size = 0;
  31.         
  32.         buff[0] = reg;

  33.         msgs.addr = KX224_DEVICE_ADDRESS_1E;
  34.         msgs.flags = RT_I2C_WR;
  35.         msgs.buf = buff;
  36.         msgs.len = 1;

  37.         if(rt_i2c_transfer(bus, &msgs, 1))
  38.         {
  39.                 return RT_EOK;
  40.         }
  41.         else
  42.         {
  43.                 return -RT_ERROR;
  44.         }
  45. }


  46. static rt_err_t red_reg(struct rt_i2c_bus_device *bus,rt_uint8_t len,rt_uint8_t * buf)
  47. {
  48.         struct rt_i2c_msg msgs;
  49.         rt_size_t size = 0;
  50.         
  51.         msgs.addr = KX224_DEVICE_ADDRESS_1E;
  52.         msgs.flags = RT_I2C_RD;
  53.         msgs.buf = buf;
  54.         msgs.len = len;

  55.         if(rt_i2c_transfer(bus, &msgs, 1))
  56.         {
  57.                 return RT_EOK;
  58.         }
  59.         else
  60.         {
  61.                 return -RT_ERROR;
  62.         }
  63. }

  64. static rt_uint32_t _g_sens;
  65. struct rt_i2c_bus_device* bus = NULL;

  66. void kx224_init(void)
  67. {
  68.         rt_uint8_t deviceid = 0,reg = 0,gsel = 0;
  69.         
  70.     bus = rt_i2c_bus_device_find("i2c1");
  71.         if(!bus)
  72.         {
  73.                 rt_kprintf("can't find i2c device\n");
  74.                 return;
  75.         }
  76.         write_cmd(bus,KX224_WHO_AM_I);
  77.         red_reg(bus,1,&deviceid);
  78.         if(deviceid != KX224_WAI_VAL)
  79.         {
  80.                 rt_kprintf("can't find device\n");
  81.                 return;
  82.         }
  83.           write_reg(bus,KX224_CNTL1,KX224_CNTL1_VAL);
  84.         write_reg(bus,KX224_ODCNTL,KX224_ODCNTL_VAL);
  85.         write_cmd(bus,KX224_CNTL1);
  86.         red_reg(bus,1,&reg);
  87.         gsel = reg & KX224_CNTL1_GSELMASK;
  88.         rt_kprintf("reg is 0x%02x gsel is 0x%02x\n",reg,gsel);
  89.         reg |= KX224_CNTL1_PC1;
  90.         write_reg(bus,KX224_CNTL1, reg);
  91.         switch(gsel) {
  92.     case KX224_CNTL1_GSEL_8G :
  93.       // (Equivalent counts) / (Range) = (32768 / 8)
  94.       _g_sens = 4096;
  95.     break;

  96.     case KX224_CNTL1_GSEL_16G :
  97.       // (Equivalent counts) / (Range) = (32768 / 16)
  98.       _g_sens = 2048;
  99.     break;

  100.     case KX224_CNTL1_GSEL_32G :
  101.       // (Equivalent counts) / (Range) = (32768 / 32)
  102.       _g_sens = 1024;
  103.     break;

  104.     default:
  105.     break;
  106.   }
  107.   rt_kprintf("_g_sens is <%d>\n",_g_sens);        
  108. }


  109. void kx224_get_rawval(unsigned char *data)
  110. {

  111.   write_cmd(bus,KX224_XOUT_L);
  112.   red_reg(bus,6,data);
  113. }


  114. void kx224_get_val(float *data)
  115. {
  116.   rt_uint8_t val[6] = {0};
  117.   rt_int16_t acc[3] = {0};
  118.   
  119.   kx224_get_rawval(val);
  120.   acc[0] = ((signed short)val[1] << 8) | (val[0]);
  121.   acc[1] = ((signed short)val[3] << 8) | (val[2]);
  122.   acc[2] = ((signed short)val[5] << 8) | (val[4]);

  123.   // Convert LSB to g
  124.   data[0] = (float)acc[0]/_g_sens;
  125.   data[1] = (float)acc[1]/_g_sens;
  126.   data[2] = (float)acc[2]/_g_sens;
  127. }
复制代码
  1. #ifndef __KX224__
  2. #define __KX224__

  3. #define KX224_DEVICE_ADDRESS_1E   (0x1E)    // 7bit Addrss
  4. #define KX224_DEVICE_ADDRESS_1F   (0x1F)    // 7bit Address
  5. #define KX224_WAI_VAL             (0x2B)

  6. #define KX224_XOUT_L              (0x06)
  7. #define KX224_WHO_AM_I            (0x0F)
  8. #define KX224_CNTL1               (0x18)
  9. #define KX224_ODCNTL              (0x1B)

  10. #define KX224_CNTL1_TPE           (1 << 0)
  11. #define KX224_CNTL1_WUFE          (1 << 1)
  12. #define KX224_CNTL1_TDTE          (1 << 2)
  13. #define KX224_CNTL1_GSELMASK      (0x18)
  14. #define KX224_CNTL1_GSEL_8G       (0x00)
  15. #define KX224_CNTL1_GSEL_16G      (0x08)
  16. #define KX224_CNTL1_GSEL_32G      (0x10)
  17. #define KX224_CNTL1_DRDYE         (1 << 5)
  18. #define KX224_CNTL1_RES           (1 << 6)
  19. #define KX224_CNTL1_PC1           (1 << 7)

  20. #define KX224_ODCNTL_OSA_50HZ     (2)
  21. #define KX224_ODCNTL_LPRO         (1 << 6)
  22. #define KX224_IIR_BYPASS          (1 << 7)

  23. #define KX224_CNTL1_VAL           (KX224_CNTL1_RES | KX224_CNTL1_GSEL_8G)
  24. #define KX224_ODCNTL_VAL          (KX224_ODCNTL_OSA_50HZ)

  25. extern void kx224_get_val(float *data);
  26. extern void kx224_init(void);
  27. #endif /* end of KX224 */
复制代码

以上代码的设定相关代码主要如下,之后就可以读取数据了:
  1. write_reg(bus,KX224_CNTL1,KX224_CNTL1_VAL);
  2.         write_reg(bus,KX224_ODCNTL,KX224_ODCNTL_VAL);
  3.         write_cmd(bus,KX224_CNTL1);
  4.         red_reg(bus,1,&reg);
  5.         gsel = reg & KX224_CNTL1_GSELMASK;
  6.         rt_kprintf("reg is 0x%02x gsel is 0x%02x\n",reg,gsel);
  7.         reg |= KX224_CNTL1_PC1;
  8.         write_reg(bus,KX224_CNTL1, reg);
复制代码
读取数据的相关如下,设定完成后就可以从KX224_XOUT_L开始的寄存器来读取数据了,连续读取6个数据就会读出三轴加速度的值
  1. void kx224_get_rawval(unsigned char *data)
  2. {

  3.   write_cmd(bus,KX224_XOUT_L);
  4.   red_reg(bus,6,data);
  5. }
复制代码

调试过程主要遇到两个问题:①设定的地址设定的读地址和对应的写地址,后开总是从机没有响应NACK,跟了下代码发现驱动框架中会根据设备的7bit或者10bit地址自动计算读读写时对应的地址,地址设定为七地址即可。
②因为板子上的IO口模拟的IIC 总线没有上拉电阻,造成每次都是NACK,IO设定为内部上拉即可。
以上只是相对简单的方式,模块还支持中断的方式,有时间再进一步研究,存粹个人理解有什么不对的欢迎拍砖指正。

151131m3azpaim4n33pamf.jpg


215059dqsn0rq7pt8vnznq.png




AN090-Getting-Started.pdf (523.62 KB, 下载次数: 0)
收藏 评论3 发布时间:2019-6-21 13:07

举报

3个回答
MrJiu 回答时间:2019-6-21 14:04:49
你好像屠版了哦!!!
andeyqi 回答时间:2019-6-21 14:14:52
MrJiu 发表于 2019-6-21 14:04
你好像屠版了哦!!!

???这个怎么讲,为啥屠版了呢
andeyliu310cae 回答时间:2019-6-21 16:35:06
顶一个   

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版