打印
[DemoCode下载]

使用I2C控制三轴传感器 (DMARD08)范例工程代码-函数使用说明

[复制链接]
2830|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaoyang9992006|  楼主 | 2015-2-13 19:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     Smpl_I2C_Gsensor_ARD08.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V2.00
* $Revision: 4 $
* $Date: 12/08/09 5:31p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series I2C Sample Code to access G-Sensor ARD08
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"

// P2.0 -> DMT ARD08 PIN13 CE
// P3.4 -> DMT ARD08 PIN9 SDI
// P3.5 -> DMT ARD08 PIN11 SCL

#define PLLCON_SETTING      SYSCLK_PLLCON_48MHz_XTAL
#define PLL_CLOCK           48000000

// Start Register Address for T, X, Y, Z
#define ARD08_REG_TOUT      0x00
#define ARD08_REG_XOUT      0x02
#define ARD08_REG_YOUT      0x04
#define ARD08_REG_ZOUT      0x06

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
uint8_t g_u8DeviceAddr;


void SYS_Init(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/

    /* Enable External XTAL (4~24 MHz) */
    SYSCLK->PWRCON |= SYSCLK_PWRCON_XTL12M_EN_Msk;

    /* Waiting for 12MHz clock ready */
    SYS_WaitingForClockReady( SYSCLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Switch HCLK clock source to XTAL */
    SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_XTAL;

    /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware. */
    SYSCLK->PLLCON |= SYSCLK_PLLCON_PD_Msk;

    /* Set PLL frequency */        
    SYSCLK->PLLCON = PLLCON_SETTING;

    /* Waiting for clock ready */
    SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);

    /* Switch HCLK clock source to PLL */
    SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_PLL;

    /* Enable IP clock */        
    SYSCLK->APBCLK = SYSCLK_APBCLK_I2C0_EN_Msk;

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
    //SystemCoreClockUpdate();
    PllClock        = PLL_CLOCK;            // PLL
    SystemCoreClock = PLL_CLOCK / 1;        // HCLK
    CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* Set P3.4 and P3.5 for I2C0 SDA and SCL */
    SYS->P3_MFP = SYS_MFP_P34_SDA0 | SYS_MFP_P35_SCL0;

    /* Lock protected registers */
    SYS_LockReg();
}

void I2C0_Init(void)
{
    /* 复位 I2C0 */
    SYS->IPRSTC2 |=  SYS_IPRSTC2_I2C0_RST_Msk;
    SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2C0_RST_Msk;

    /* 使能 I2C0 */
    I2C0->I2CON |= I2C_I2CON_ENS1_Msk;

    /* I2C0 时钟分频, I2C0 总线时钟 = PCLK / (4*60) = 200kHz */
    I2C0->I2CLK = I2C_I2CLK_DIV4(60);

    /* 获得 I2C0 总线时钟 */
    printf("I2C clock %d Hz\n", _I2C_GET_BUS_CLOCK(I2C0));

    /* 配置I2C0 4个从设备地址 */            
    _I2C_SET_SLAVE_ADDRESS_0(I2C0, 0x15);   /* 从设备地址0 : 0x15 */
    _I2C_SET_SLAVE_ADDRESS_1(I2C0, 0x35);   /* 从设备地址1 : 0x35 */
    _I2C_SET_SLAVE_ADDRESS_2(I2C0, 0x55);   /* 从设备地址2 : 0x55 */
    _I2C_SET_SLAVE_ADDRESS_3(I2C0, 0x75);   /* 从设备地址3 : 0x75 */
}

void ARD08_SingleWrite(uint8_t u8Reg, uint8_t u8Data)
{
    /* 发送起始位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STA);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器从设备地址+写位 */
    I2C0->I2CDAT = g_u8DeviceAddr << 1;   
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器寄存器地址 */
    I2C0->I2CDAT = u8Reg;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写数据到传感器寄存器 */
    I2C0->I2CDAT = u8Data;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 发送停止位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STO_SI);

    SYS_SysTickDelay(10);
}

uint8_t ARD08_SingleRead(uint8_t u8Reg)
{
    uint8_t u8data;

    /* 发送起始位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STA);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器从设备地址+写位 */
    I2C0->I2CDAT = g_u8DeviceAddr << 1;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器寄存器地址 */
    I2C0->I2CDAT = u8Reg;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 发送重复起始位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STA_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器从设备地址+读位 */
    I2C0->I2CDAT = ((g_u8DeviceAddr << 1) | 0x01);
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 读传感器寄存器数据并返回NACK */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    u8data = I2C0->I2CDAT;

    /* 发送停止位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STO_SI);

    SYS_SysTickDelay(10);

    return u8data;
}

uint16_t ARD08_MultipleRead(uint8_t u8Reg)
{
    uint8_t u8highByte, u8lowByte;

    /* 发送起始位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STA);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器从设备地址+写位 */
    I2C0->I2CDAT = g_u8DeviceAddr << 1;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器寄存器地址 */
    I2C0->I2CDAT = u8Reg;
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 发送重复起始位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STA_SI);
    _I2C_WAIT_READY(I2C0);

    /* 写传感器从设备地址+读位 */
    I2C0->I2CDAT = ((g_u8DeviceAddr << 1) | 0x01);
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    /* 读传感器寄存器数据并返回ACK */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI_AA);
    _I2C_WAIT_READY(I2C0);

    u8lowByte = I2C0->I2CDAT;

    /* 读传感器寄存器数据并返回NACK */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_SI);
    _I2C_WAIT_READY(I2C0);

    u8highByte = I2C0->I2CDAT;

    /* 发送停止位 */
    _I2C_SET_CONTROL_BITS(I2C0, I2C_I2CON_STO_SI);

    SYS_SysTickDelay(10);

    return ((u8lowByte << 3) | (u8highByte & 0x7));
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main (void)
{
    uint8_t u8RegData;
    int16_t i16Tout, i16Xout, i16Yout, i16Zout;
    int16_t i16Tout_d, i16Xout_d, i16Yout_d, i16Zout_d;

    /* 初始化系统,系统时钟和GPIO配置 */
    SYS_Init();

    /*
        This sample code sets I2C bus clock to 200kHz. Then, accesses G-Sensor ARD08 with
        Single Write, Single Read and Multiple Read operations, and show the converted data.
    */

    printf("+-----------------------------------------------+\n");
    printf("|  M051 I2C Communicates with G-Sensor DMARD08  |\n");
    printf("+-----------------------------------------------+\n");

    /* 配置P2.0为输出模式 */
    _GPIO_SET_PIN_MODE(P2, 0, GPIO_PMD_OUTPUT);

    /* 设置P2.0输出低电平,传感器操作在待机模式 */
    P20 = 0;

    /* 初始化I2C0, I2C0总线时钟 = 200 kHz */
    I2C0_Init();

    /* 设置P2.0为高电平,传感器操作在工作模式 */
    P20 = 1;

    /* 传感器的SDO脚是接地的,所以传感器作为从设备的地址为0x1C */
    g_u8DeviceAddr = 0x1C;

    /* 写ARD08寄存器 */
    ARD08_SingleWrite(0x08, 0x03);          // 采样周期 = 2.925 ms, 采样频率 = 342 Hz
                                            // 移动平均长度 = 1, 带宽 = No Filter
    /* 读ARD08控制寄存器 */
    u8RegData = ARD08_SingleRead(0x08);
    printf("Control Register (0x08): 0x%X\r\n", u8RegData);
    u8RegData = ARD08_SingleRead(0x09);
    printf("Control Register (0x09): 0x%X\r\n", u8RegData);
    u8RegData = ARD08_SingleRead(0x0A);
    printf("Control Register (0x0A): 0x%X\r\n", u8RegData);
    u8RegData = ARD08_SingleRead(0x0B);
    printf("Control Register (0x0B): 0x%X\r\n\r\n", u8RegData);

    while(1)
    {
        i16Tout = ARD08_MultipleRead(ARD08_REG_TOUT);   // 读温度值
        i16Xout = ARD08_MultipleRead(ARD08_REG_XOUT);   // 读X轴值
        i16Yout = ARD08_MultipleRead(ARD08_REG_YOUT);   // 读Y轴值
        i16Zout = ARD08_MultipleRead(ARD08_REG_ZOUT);   // 读Z轴值

        /* 如果输出值最高位为1, 则表示输出值为负值 */
        i16Tout_d = i16Tout | ((i16Tout & 0x400)? 0xF800:0);
        i16Xout_d = i16Xout | ((i16Xout & 0x400)? 0xF800:0);
        i16Yout_d = i16Yout | ((i16Yout & 0x400)? 0xF800:0);
        i16Zout_d = i16Zout | ((i16Zout & 0x400)? 0xF800:0);

        /* 串口打印三轴输出值以及相应的加速度值.     */
        /* 灵敏度为256 LSB/g ,中间值(0x00) 表示 0 g */
        printf("X Output: %.4f g (0x%X)\r\n", (float)i16Xout_d /(float)256, i16Xout);
        printf("Y Output: %.4f g (0x%X)\r\n", (float)i16Yout_d /(float)256, i16Yout);
        printf("Z Output: %.4f g (0x%X)\r\n", (float)i16Zout_d /(float)256, i16Zout);

        /* 串口打印温度寄存器值和实际温度值.*/
        /* 1度 = 16 LSB,中间值(0x00) 表示 25 摄氏度 */
        printf("Temperature: %.2f degrees C (0x%x)\r\n\r\n", ((float)i16Tout_d /(float)16)+25, i16Tout);

        SYS_SysTickDelay(250000);
        SYS_SysTickDelay(250000);
    }
}




沙发
gaoyang9992006|  楼主 | 2015-2-13 19:34 | 只看该作者
示例说明.pdf (869.24 KB)

使用特权

评论回复
板凳
gaoyang9992006|  楼主 | 2015-2-13 19:35 | 只看该作者
DMARD08 Datasheet V1.2.pdf (1.41 MB)

使用特权

评论回复
地板
598330983| | 2015-2-13 19:51 | 只看该作者
单独做在一个文件里比较好。主函数只去调用。

使用特权

评论回复
5
mintspring| | 2015-2-15 23:01 | 只看该作者
谢谢分享,我要买个套件玩玩这个

使用特权

评论回复
6
gaoyang9992006|  楼主 | 2015-2-16 12:21 | 只看该作者
598330983 发表于 2015-2-13 19:51
单独做在一个文件里比较好。主函数只去调用。

嗯你说的对,我这是转发的别人的

使用特权

评论回复
7
ccw1986| | 2015-3-27 08:17 | 只看该作者
最喜欢这样格式的代码了,复制到编译器里面直接能用。
谢谢楼主分享

使用特权

评论回复
8
mintspring| | 2015-3-28 21:22 | 只看该作者
#define ARD08_REG_TOUT      0x00
#define ARD08_REG_XOUT      0x02
#define ARD08_REG_YOUT      0x04
#define ARD08_REG_ZOUT      0x06

使用特权

评论回复
9
mintspring| | 2015-3-28 21:23 | 只看该作者

最喜欢这样格式的代码了,复制到编译器里面直接能用。
谢谢楼主分享

使用特权

评论回复
10
mintspring| | 2015-3-28 21:23 | 只看该作者
DMARD08 Datasheet V1.2.pdf (1.41 MB, 下载次数: 2)

使用特权

评论回复
11
mintspring| | 2015-3-28 21:24 | 只看该作者
        SYS_SysTickDelay(250000);
        SYS_SysTickDelay(250000);

使用特权

评论回复
12
quray1985| | 2015-3-29 09:06 | 只看该作者
谢谢楼主的分享
有个视频再介绍下程序就好了

使用特权

评论回复
13
jack2000168| | 2015-4-2 14:35 | 只看该作者
楼主。楼主。你QQ多少?有事请教您

使用特权

评论回复
14
jack2000168| | 2015-4-2 14:36 | 只看该作者
楼主,DMARD08你们还在使用?

使用特权

评论回复
15
jack2000168| | 2015-4-2 14:38 | 只看该作者
楼主

使用特权

评论回复
16
gaoyang9992006|  楼主 | 2015-4-2 15:43 | 只看该作者
jack2000168 发表于 2015-4-2 14:36
楼主,DMARD08你们还在使用?

不用了,以前用过。

使用特权

评论回复
17
gaoyang9992006|  楼主 | 2015-4-2 15:43 | 只看该作者

你是不是想说这个东西淘汰了,落后了?

使用特权

评论回复
18
734774645| | 2015-4-2 19:28 | 只看该作者
    SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);
这个常量定义的,MSK,我看好多库函数都是msk,或者mask,掩码的意思,就是几个常量一起逻辑运算的结果。

使用特权

评论回复
19
gaoyang9992006|  楼主 | 2015-4-3 13:20 | 只看该作者
734774645 发表于 2015-4-2 19:28
SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);
这个常量定义的,MSK,我看好多库函数都是ms ...

是的,那个就是可以通过运算获取的。

使用特权

评论回复
20
稳稳の幸福| | 2015-4-3 15:30 | 只看该作者
最喜欢这样格式的代码了,复制到编译器里面直接能用。
谢谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1953

主题

15892

帖子

207

粉丝