/**************************************************
** 文件名称:NUC120_HOT_I2C.c
** 文件说明:NUC120助学板练习程序
** 创建日期:2011-04-11
** 修改日期:
** 备 注:I2C查询方式完成单字节写及随机地址读操作
**************************************************/
#include <stdio.h>
#include "NUC1xx.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvSYS.h"
#include "Driver\DrvUART.h"
#include "Driver\DrvI2C.h"
uint8_t Run_Led = 4; //2----LED1 3----LED2 4----LED3 5----LED4
volatile uint8_t Receive_Data = 0;
volatile uint8_t IsStart = FALSE;
/***************
** 函数声明 **
***************/
void Init_System (void);
void Init_Uart (void);
void UART_INT_HANDLE(uint32_t u32IntStatus);
void I2C_WriteByte ( uint32_t address,uint8_t data );
uint8_t I2C_ReadByte ( uint32_t address );
/*****************************
** Name: UART_INT_HANDLE
** Function: UART Callback function
** Input: u32IntStatus
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void UART_INT_HANDLE(uint32_t u32IntStatus)
{
uint8_t bInChar[1]={0xFF};
if(u32IntStatus & DRVUART_RDAINT)
{
/* Get all the input characters */
while(UART0->ISR.RDA_IF==1)
{
/* Get the character from UART Buffer */
DrvUART_Read(UART_PORT0,bInChar,1);
if (IsStart!=TRUE)
{
IsStart = TRUE;
Receive_Data = bInChar[0];
}
}
}
}
/*****************************
** Name: Init_System
** Function: 系统初始化函数
** Input: None
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void Init_System(void)
{
/* Unlock the locked registers before access */
UNLOCKREG(x); //寄存器锁定键地址寄存器(RegLockAddr) :有些系统控制寄存器需要被保护起来,以防止误操作而影响芯片运行,
//这些寄存器在上电复位到用户解锁定之前是锁定的。用户可以连续依次写入“59h”, “16h” “88h”到0x5000_0100解锁定.
/* Enable the 12MHz oscillator oscillation */
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); //SYSCLK->PWRCON.XTL12M_EN = 1;
/* Waiting for 12M Xtal stable */
//while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1); //SYSCLK->CLKSTATUS.XTL12M_STB
/*eClkSrc - [in] E_SYS_XTL12M / E_SYS_XTL32K / E_SYS_OSC22M / E_SYS_OSC10K / E_SYS_PLL */
// Note: Only some of NuMicro NUC100 Series support this function.
DrvSYS_Delay(5000);
LOCKREG(x);
//向“0x5000_0100”写入任何值,就可以重锁保护寄存器
}
/*****************************
** Name: Init_Uart
** Function: UART初始化函数
** Input: None
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void Init_Uart(void)
{
STR_UART_T param;
/*
声明 UART设置的结构体 位于DRVUART.H
结构体如下
typedef struct DRVUART_STRUCT
{
uint32_t u32BaudRate;
E_DATABITS_SETTINS u8cDataBits;
E_STOPBITS_SETTINS u8cStopBits;
E_PARITY_SETTINS u8cParity;
E_FIFO_SETTINGS u8cRxTriggerLevel;
uint8_t u8TimeOut ;
}STR_UART_T;
*/
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0); //使能UART时钟
//SYSCLK->CLKSEL1.UART_S = 0; //UART时钟源选择. 00 =外部12MHz 晶振 01 = PLL 1x =内部 22MHz 振荡器
DrvGPIO_InitFunction(E_FUNC_UART0); //GPB_MFP0-1-2-3置位 GPIO使能UART功能
//outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) | (0xF<<0));
param.u32BaudRate = 115200; // 波特率
param.u8cDataBits = DRVUART_DATABITS_8; // 数据位
param.u8cStopBits = DRVUART_STOPBITS_1; // 停止位
param.u8cParity = DRVUART_PARITY_NONE; // 校验位
param.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES; // FIFO存储深度 1 字节
param.u8TimeOut = 0; // FIFO超时设定
/* Set UART Configuration */
if(DrvUART_Open(UART_PORT0,¶m) != E_SUCCESS) // 串口开启、结构体整体赋值
printf("UART0 open failed\n");
/* u32Port -[in] UART Channel: UART_PORT0 / UART_PORT1 /UART_PORT2 */
/* sParam -[in] the struct parameter to configure UART */
/* Enable Interrupt and install the call back function */
DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);
/*u32Port -[in] UART Channel: UART_PORT0 / UART_PORT1 / UART_PORT2 */
/*u32InterruptFlag -[in] DRVUART_LININT/DRVUART_WAKEUPINT/DRVUART_BUFERRINT/DRVUART_RLSINT */
/* DRVUART_MOSINT/DRVUART_THREINT/DRVUART_RDAINT/DRVUART_TOUTINT */
/*pfncallback -[in] A function pointer for callback function */
}
int main (void)
{
uint8_t test = 250;
uint8_t EEPROM_Data = 0;
Init_System();
Init_Uart();
DrvGPIO_InitFunction(E_FUNC_I2C1);
DrvGPIO_Open(E_GPA,Run_Led, E_IO_OUTPUT); //程序运行指示
DrvGPIO_ClrBit(E_GPA,Run_Led);
printf("\n");
printf("/*==========================\n");
printf("======菜农 %d 助学计划======\n",test);
printf("========NUC120助学板========\n");
printf("======程序参考新唐BSP库======\n");
printf("=======2011年04月11日=======\n");
printf("========I2C(查询)实验=======\n");
printf("I2C查询方式完成单字节写及随机地址读操作\n");
printf("'R/r'为读指令、'U/u'为加1并存储指令、'D/d'为减1并存储指令\n");
printf("===========================/\n");
EEPROM_Data = I2C_ReadByte(0x00);
printf("AT24C16地址0的内容为:0x%x!\n",EEPROM_Data);
printf("====请输入字符开始测试!===\n");
printf("==========================*/\n");
while(1)
{
if (IsStart)
{
switch (Receive_Data)
{
case 'R':
case 'r':
EEPROM_Data = I2C_ReadByte(0x00);
printf("AT24C16地址0的内容为:0x%x!\n",EEPROM_Data);
break;
case 'U':
case 'u':
I2C_WriteByte(0x00,++EEPROM_Data);
printf("AT24C16地址0的内容加1成功!\n");
break;
case 'D':
case 'd':
I2C_WriteByte(0x00,--EEPROM_Data);
printf("AT24C16地址0的内容减1成功!\n");
break;
default:
printf("请确认您输入的指令是否合法!\n");
}
IsStart = FALSE;
}
}
}
/*****************************
** Name: I2C_WriteByte
** Function: I2C向写单字节函数
** Input: uint32_t address,uint8_t data
** OutPut: None
** Data: 2011-04-11
** Note:
****************************/
void I2C_WriteByte ( uint32_t address,uint8_t data )
{
/*
在字节写模式下,主器件发送起始命令和从器件地址信息(R/W 位置 0)给从器件,
主器件在收到从器件产生应答信号后,主器件发送1个8位字节地址写入AT24C01/
02/04/08/16 的地址指针,对于 AT24C31/64/128/256 来说,所不同的是主器件
发送两个8位地址字写入AT24C32/64/128/256的地址指针。主器件在收到从器件的
另一个应答信号后,再发送数据到被寻址的存储单元。AT24Cxx 再次应答,并在
主器件产生停止信号后开始内部数据的擦写,在内部擦写过程中,AT24Cxx 不再
应答主器件的任何请求。
*/
uint32_t i;
DrvI2C_Open(I2C_PORT1, 50000); //打开I2C1功能,并配置 I2C总线时钟为50KHZ
/* Parameters:port - [in] I2C_PORT0 / I2C_PORT1 */
/* u32BusClock - [in] I2C bus clock frequency (Hz) */
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //设定I2C控制比特 START
/* Parameters:port - [in] I2C_PORT0 / I2C_PORT1 */
/* start - [in] 1:Enable / 0:Disable */
/* stop - [in] 1:Enable / 0:Disable */
/* intFlag - [in] Wrtie '1' to clear this flag */
/* ack - [in] 1:Enable / 0:Disable */
while (I2C1->CON.SI == 0); //查询中断标志位 SI
I2C1->DATA = 0xA0; //发送写命令
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
I2C1->DATA = address&0XFF; //发送地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
I2C1->DATA = data; //发送待写内容
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //清标志位 SI 并STOP
for(i=0;i<60;i++);
DrvI2C_Close(I2C_PORT1);
for(i=0;i<6000;i++);
for(i=0;i<6000;i++);
}
/*****************************
** Name: I2C_ReadByte
** Function: I2C向读单字节函数
** Input: uint32_t address,uint8_t data
** OutPut: None
** Data: 2011-04-11
** Note:
****************************/
uint8_t I2C_ReadByte ( uint32_t address )
{
/*
随机读操作允许主器件对寄存器的任意字节进行读操作,主器件
首先通过发送起始信号、从器件地址和它想读取的字节数据的地
址执行一个伪写操作。在AT24Cxx 应答之后,主器件重新发送起
始信号和从器件地址,此时R/W 位置1,AT24CXX 响应并发送应答
信号,然后输出所要求的一个 8位字节数据,主器件不发送应答
信号但产生一个停止信号。
*/
uint8_t TEMP;
DrvI2C_Open(I2C_PORT1, 50000);
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //设定I2C控制比特 START并清中断标志
while (I2C1->CON.SI == 0); //查询中断标志位 SI
I2C1->DATA = 0XA0; //发送写命令
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
I2C1->DATA = address&0xFF; //发送地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //设定I2C控制比特 START并清中断标志
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
I2C1->DATA = 0XA1; //发送读命令
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
//I2C1->DATA = 0xFF; //通过操作数据寄存器配合控制位的设置启动一次新的I2C操作(此句加与不加未影响到结果)
/*"Software should load the data byte (to be transmitted)into I2DAT before new I2CON setting is done." 手册中该句怎么解释?*/
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI
TEMP= I2C1->DATA; //读数据
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //清标志位 SI 并STOP
DrvI2C_Close(I2C_PORT1);
return TEMP;
}