/**************************************************************************//**
* [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);
}
}