hi3861使用iic驱动adxl346
Posted 耳 东
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hi3861使用iic驱动adxl346相关的知识,希望对你有一定的参考价值。
开发平台
Ubuntu 18.04
DOPI hi3861lv开发板、adxl346模组
Q群:735884031
一.配置3861iic
1.搭建demo工程,可参考我的上一篇博客
2.查看引脚复用,使用GPIO9、GPIO10作为iic0 IO
3.配置io复用,初始化iic控制器
/Hi3861V100R001C00SPC025/app/adxl346$ tree
.
├── app.json
├── iic
│ ├── iic.c
│ ├── iic.h
│ └── SConscript
├── SConscript
└── src
├── main.c
└── SConscript
iic.c
// 标准库
#include <stdio.h>
#include <unistd.h>
// 第三方库
#include <hi3861_platform.h>
#include <hi_io.h>
#include <hi_i2c.h>
#include <hi_types_base.h>
#include <hi_i2c.h>
#include <hi_early_debug.h>
#include <hi_stdlib.h>
// 自定义头文件
#include "i2c.h"
hi_u32 iic0_write_reg(hi_u8 dev_addr, hi_u8 reg, hi_u8 val)
hi_u32 status;
hi_u8 send_buff[2] = 0 ;
hi_i2c_data send_data = 0 ;
send_buff[0] = reg;
send_buff[1] = val;
send_data.send_buf = send_buff;
send_data.send_len = 2;
dev_addr <<= 1;
status = hi_i2c_writeread(HI_I2C_IDX_0, dev_addr, &send_data);
if (status != HI_ERR_SUCCESS)
return status;
return 0;
hi_u32 iic0_read_reg(hi_u8 dev_addr, hi_u8 reg)
hi_u32 status;
hi_u8 send_buff[2] = 0 ;
hi_u8 receive_buff[2] = 0 ;
hi_i2c_data send_data = 0 ;
send_buff[0] = reg;
send_data.send_buf = send_buff;
send_data.send_len = 1;
send_data.receive_buf = receive_buff;
send_data.receive_len = 1;
dev_addr <<= 1;
dev_addr |= 0x01;
status = hi_i2c_writeread(HI_I2C_IDX_0, dev_addr, &send_data);
if (status != HI_ERR_SUCCESS)
return status;
return receive_buff[0];
int iic0_init(void)
// 复用GPIO
hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_I2C0_SCL);
hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2C0_SDA);
// 初始化iic0
hi_i2c_init(HI_I2C_IDX_0, 100000);
return 0;
main.c
// 标准库
#include <stdio.h>
#include <unistd.h>
// 第三方库
#include <hi3861_platform.h>
#include <hi_i2c.h>
// 用户自定义
#include "gpio.h"
#include "adxl346.h"
hi_void app_main(hi_void)
iic0_init();
while(1)
sleep(1);
回到sdk根目录单独编译adxl346 demo
# ./build.sh adxl346
编译报错了,找不到iic初始化api,查看/build/build_tmp/下是否生成对应的中间文件,sdk编译的中间文件都在该目录下,包括编译log文件
打开内核iic编译选项 BSP Setting -> i2c driver support
./build.sh menuconfig
编译通过了
二.移植adxl346
adxl346在linux内核中自带驱动源码,有兴趣的小伙伴也可以去官网下载,附上官网链接
https://wiki.analog.com/resources/tools-software/linux-drivers/input-misc/adxl345
移植完成后
int adxl346_init(void)
// 初始化adxl346
iic0_write_reg(ADXL346_DEV_ADDR, POWER_CTL, 0x00);
iic0_write_reg(ADXL346_DEV_ADDR, OFSX, 0x00);
iic0_write_reg(ADXL346_DEV_ADDR, OFSY, 0x00);
iic0_write_reg(ADXL346_DEV_ADDR, OFSZ, 0x00);
iic0_write_reg(ADXL346_DEV_ADDR, THRESH_TAP, 0x31);
iic0_write_reg(ADXL346_DEV_ADDR, DUR, 0x10);
iic0_write_reg(ADXL346_DEV_ADDR, LATENT, 0x60);
iic0_write_reg(ADXL346_DEV_ADDR, WINDOW, 0xF0);
iic0_write_reg(ADXL346_DEV_ADDR, THRESH_ACT, 0x05);
iic0_write_reg(ADXL346_DEV_ADDR, THRESH_INACT, 0x03);
iic0_write_reg(ADXL346_DEV_ADDR, TIME_INACT, 0x04);
iic0_write_reg(ADXL346_DEV_ADDR, THRESH_FF, 0x07);
iic0_write_reg(ADXL346_DEV_ADDR, TIME_FF, 0x20);
iic0_write_reg(ADXL346_DEV_ADDR, TAP_AXES, ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN);
iic0_write_reg(ADXL346_DEV_ADDR, ACT_INACT_CTL, 0xFF);
iic0_write_reg(ADXL346_DEV_ADDR, BW_RATE, 0x08);
iic0_write_reg(ADXL346_DEV_ADDR, DATA_FORMAT, ADXL_FULL_RES);
iic0_write_reg(ADXL346_DEV_ADDR, FIFO_CTL, DATA_READY/*ADXL_FIFO_STREAM*/);
iic0_write_reg(ADXL346_DEV_ADDR, INT_MAP, 0);
iic0_write_reg(ADXL346_DEV_ADDR, ORIENT_CONF, ORIENT_DEADZONE(ADXL_DEADZONE_ANGLE_10p8) | ORIENT_DIVISOR(ADXL_LP_FILTER_DIVISOR_16));
iic0_write_reg(ADXL346_DEV_ADDR, POWER_CTL, PCTL_AUTO_SLEEP | PCTL_LINK | PCTL_MEASURE);
return 0;
void adxl_read_data(void)
printf(" x = %d y = %d z = %d\\n", iic0_read_reg(ADXL346_DEV_ADDR, DATAX0), iic0_read_reg(ADXL346_DEV_ADDR, DATAY0), iic0_read_reg(ADXL346_DEV_ADDR, DATAZ0));
调用初始化,轮询读取数据后,将模块沿旋转90°
x = 3 y = 244 z = 217
x = 4 y = 244 z = 216
x = 3 y = 246 z = 218
x = 6 y = 245 z = 218
x = 5 y = 245 z = 217
x = 1 y = 250 z = 220
x = 3 y = 245 z = 216
x = 19 y = 243 z = 217
x = 65 y = 243 z = 215
x = 110 y = 246 z = 197
x = 152 y = 243 z = 174
x = 190 y = 241 z = 145
x = 219 y = 242 z = 107
x = 243 y = 241 z = 69
x = 255 y = 241 z = 27
三.配置GPIO中断使用中断方式读取
1.3861配置GPIO中断
hi_void gpio_2_irq_callback(hi_void *arg)
printf("-----------------gpio_2_irq_callback\\n");
int gpio_irq_init(void)
hi_gpio_init();
hi_io_set_func (HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_2_GPIO);
hi_gpio_set_dir (HI_IO_NAME_GPIO_2, HI_GPIO_DIR_IN);
hi_gpio_register_isr_function(HI_IO_NAME_GPIO_2, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_FALL_LEVEL_LOW, gpio_2_irq_callback, NULL);
return 0;
2.adxl346清楚中断状态,在初始化完成以及产生中断之后,都去读取一下中断状态寄存器清楚中断标志位,要不然不会产生新的中断
iic0_read_reg(ADXL346_DEV_ADDR, ACT_TAP_STATUS);
iic0_read_reg(ADXL346_DEV_ADDR, INT_SOURCE);
iic0_read_reg(ADXL346_DEV_ADDR, ORIENT);
3.修改完成之后查看INT1引脚波形已经产生了中断信号
以上是关于hi3861使用iic驱动adxl346的主要内容,如果未能解决你的问题,请参考以下文章