/******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V0.10
* $Revision: 4 $
* $Date: 13/10/07 3:56p $
* [url=home.php?mod=space&uid=247401]@brief[/url] Mini51 Series I2C Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "Mini51Series.h"
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
volatile uint8_t g_u8DeviceAddr;
volatile uint8_t g_u8DataLen;
volatile uint8_t rawlenth;
volatile uint8_t g_au8Reg;
volatile uint8_t g_u8EndFlag = 0;
uint8_t *g_au8Buffer;
typedef void (*I2C_FUNC)(uint32_t u32Status);
I2C_FUNC __IO s_I2CHandlerFn = NULL;
/*---------------------------------------------------------------------------------------------------------*/
/* I2C IRQ Handler */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_IRQHandler(void)
{
uint32_t u32Status;
u32Status = I2C_GET_STATUS(I2C);
if (I2C_GET_TIMEOUT_FLAG(I2C))
{
/* Clear I2C Timeout Flag */
I2C_ClearTimeoutFlag(I2C);
}
else
{
if (s_I2CHandlerFn != NULL)
s_I2CHandlerFn(u32Status);
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* I2C Rx multi Callback Function */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterRx_multi(uint32_t u32Status)
{
if(u32Status == 0x08) /* START has been transmitted and prepare SLA+W */
{
I2C_SET_DATA(I2C, (g_u8DeviceAddr << 1)); /* Write SLA+W to Register I2CDAT */
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x18) /* SLA+W has been transmitted and ACK has been received */
{
I2C_SET_DATA(I2C, g_au8Reg);
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x20) /* SLA+W has been transmitted and NACK has been received */
{
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA | I2C_STO);
}
else if(u32Status == 0x28) /* DATA has been transmitted and ACK has been received */
{
if (rawlenth > 0)
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA);//repeat start
else
{
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
g_u8EndFlag = 1;
}
}
else if(u32Status == 0x10) /* Repeat START has been transmitted and prepare SLA+R */
{
I2C_SET_DATA(I2C, ((g_u8DeviceAddr << 1) | 0x01)); /* Write SLA+R to Register I2CDAT */
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x40) /* SLA+R has been transmitted and ACK has been received */
{
if (rawlenth > 1)
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
else
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x50) /* DATA has been received and ACK has been returned */
{
g_au8Buffer[g_u8DataLen++] = (unsigned char) I2C_GetData(I2C);
if (g_u8DataLen < (rawlenth-1))
{
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_AA);
}
else
{
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
}
else if(u32Status == 0x58) /* DATA has been received and NACK has been returned */
{
g_au8Buffer[g_u8DataLen++] = (unsigned char) I2C_GetData(I2C);
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
g_u8EndFlag = 1;
}
else
{
/* TO DO */
printf("Status 0x%x is NOT processed\n", u32Status);
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* I2C Tx multi Callback Function */
/*---------------------------------------------------------------------------------------------------------*/
void I2C_MasterTx_multi(uint32_t u32Status)
{
if(u32Status == 0x08) /* START has been transmitted */
{
I2C_SET_DATA(I2C, g_u8DeviceAddr << 1); /* Write SLA+W to Register I2CDAT */
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x18) /* SLA+W has been transmitted and ACK has been received */
{
I2C_SET_DATA(I2C, g_au8Reg);
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else if(u32Status == 0x20) /* SLA+W has been transmitted and NACK has been received */
{
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STA | I2C_STO);
}
else if(u32Status == 0x28) /* DATA has been transmitted and ACK has been received */
{
if(g_u8DataLen < rawlenth)
{
I2C_SET_DATA(I2C, g_au8Buffer[g_u8DataLen++]);
I2C_SET_CONTROL_REG(I2C, I2C_SI);
}
else
{
I2C_SET_CONTROL_REG(I2C, I2C_SI | I2C_STO);
g_u8EndFlag = 1;
}
}
else
{
/* TO DO */
printf("Status 0x%x is NOT processed\n", u32Status);
}
}
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable external 12MHz XTAL, internal 22.1184MHz */
CLK->PWRCON |= CLK_PWRCON_XTL12M | CLK_PWRCON_IRC22M_EN_Msk;
/* Waiting for clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL_STB_Msk | CLK_CLKSTATUS_IRC22M_STB_Msk);
/* Switch HCLK clock source to XTL, STCLK to XTL */
CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_XTAL | CLK_CLKSEL0_HCLK_S_XTAL;
/* Enable IP clock */
CLK->APBCLK = CLK_APBCLK_UART_EN_Msk;
/* Select IP clock source */
CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_XTAL;
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set P0 multi-function pins for UART RXD and TXD */
SYS->P0_MFP = SYS_MFP_P01_RXD | SYS_MFP_P00_TXD;
/* Set P3.4 and P3.5 for I2C SDA and SCL */
SYS->P3_MFP = SYS_MFP_P34_SDA | SYS_MFP_P35_SCL;
/* Lock protected registers */
SYS_LockReg();
/* Update System Core Clock */
SystemCoreClockUpdate();
}
void UART_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset IP */
SYS->IPRSTC2 |= SYS_IPRSTC2_UART_RST_Msk;
SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART_RST_Msk;
UART->BAUD = UART_BAUD_DIV_X_EN_Msk | UART_BAUD_DIV_X_ONE_Msk | (((__XTAL + (115200/2)) / 115200)-2);
UART->LCR = 0x3 | (0x0 << UART_LCR_PBE_Pos) | (0x0 << UART_LCR_NSB_Pos) ;
}
void I2C_Init(void)
{
/* Open I2C module and set bus clock */
I2C_Open(I2C, 100000);
/* Set I2C 4 Slave Addresses */
I2C_SetSlaveAddr(I2C, 0, 0x15, 0); /* Slave Address : 0x15 */
I2C_SetSlaveAddr(I2C, 1, 0x35, 0); /* Slave Address : 0x35 */
I2C_SetSlaveAddr(I2C, 2, 0x55, 0); /* Slave Address : 0x55 */
I2C_SetSlaveAddr(I2C, 3, 0x75, 0); /* Slave Address : 0x75 */
/* Enable I2C interrupt */
I2C_EnableInt(I2C);
NVIC_EnableIRQ(I2C_IRQn);
}
void I2C0_Write_SLAVE_multi(uint8_t slvaddr,uint16_t slvraw,uint8_t slvreg,uint8_t *data)
{
g_u8DeviceAddr = slvaddr;
rawlenth=slvraw;
g_au8Reg = slvreg;
g_au8Buffer=data;
g_u8DataLen = 0;
g_u8EndFlag = 0;
/* I2C function to write data to slave */
s_I2CHandlerFn = (I2C_FUNC)I2C_MasterTx_multi;
/* I2C as master sends START signal */
I2C_SET_CONTROL_REG(I2C, I2C_STA);
/* Wait I2C Tx Finish */
while(g_u8EndFlag == 0);
g_u8EndFlag = 0;
}
void I2C0_Read_SLAVE_multi(uint8_t slvaddr,uint16_t slvraw,uint8_t slvreg,uint8_t *data)
{
g_u8DeviceAddr = slvaddr;
rawlenth=slvraw;
g_au8Reg = slvreg ;
g_au8Buffer=data;
g_u8EndFlag = 0;
g_u8DataLen = 0;
/* I2C function to read data from slave */
s_I2CHandlerFn = (I2C_FUNC)I2C_MasterRx_multi;
I2C_SET_CONTROL_REG(I2C, I2C_STA);
/* Wait I2C Rx Finish */
while(g_u8EndFlag == 0);
}
/*---------------------------------------------------------------------------------------------------------*/
/* Main Function */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main (void)
{
uint8_t u8Data[10];
uint8_t DID,slvreg;
uint32_t i;
uint8_t *Buffer;
uint16_t raw;
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Init UART for printf */
UART_Init();
/*
This sample code sets I2C bus clock to 100kHz. Then, accesses EEPROM 24LC64 with Byte Write
and Byte Read operations, and check if the read data is equal to the programmed data.
*/
printf("+-------------------------------------------------------+\n");
printf("| Mini51 I2C Driver Sample Code with EEPROM 24LC64 |\n");
printf("+-------------------------------------------------------+\n");
/* Init I2C to access EEPROM */
I2C_Init();
printf("\n");
printf("Check I2C Slave(I2C0) is running first!\n");
printf("Press any key to continue.\n");
getchar();
/* Access Slave with no address */
printf("\n");
DID=0x15;
slvreg=0x66;
raw=10;
Buffer=u8Data;
for (i=0;i<raw;i++)
{
Buffer[i]=1<<(i%8);
}
I2C0_Write_SLAVE_multi(DID,raw,slvreg,Buffer);
I2C0_Read_SLAVE_multi(DID,raw,slvreg,Buffer);
/* Compare data */
for (i=0;i<raw;i++)
{
if(Buffer[i] != 1<<(i%8))
{
printf("I2C Byte Write/Read Failed, Data 0x%x\n", Buffer[i]);
// while(1);
}
printf("Master Access Slave Register:0x%X Data:0x%X Test OK\n", (slvreg+i), Buffer[i]);
}
printf("SLAVE Address test OK.\n");
s_I2CHandlerFn = NULL;
/* Close I2C */
I2C_Close(I2C);
return 0;
}