- /**************************************************
- ** 文件名称:NUC120_HOT_I2C_Interrupt.c
- ** 文件说明:NUC120助学板练习程序
- ** 创建日期:2011-04-26
- ** 修改日期:
- ** 备 注: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; //为1表示上位机发送指令正在执行 为0表示上位机发送指令处理完毕
- typedef enum
- {
- I2C_START = 0x08,
- I2C_REP_START = 0x10,
- I2C_MT_SLA_ACK = 0x18,
- I2C_MT_SLA_NACK = 0x20,
- I2C_MT_DATA_ACK = 0x28,
- I2C_MT_DATA_NACK = 0x30,
- I2C_MT_ARB_LOST = 0x38,
- I2C_MR_ARB_LOST = 0x38,
- I2C_MR_SLA_ACK = 0x40,
- I2C_MR_SLA_NACK = 0x48,
- I2C_MR_DATA_ACK = 0x50,
- I2C_MR_DATA_NACK = 0x58,
- I2C_ST_SLA_ACK = 0xA8,
- I2C_ST_ARB_LOST_SLA_ACK = 0xB0,
- I2C_ST_DATA_ACK = 0xB8,
- I2C_ST_DATA_NACK = 0xC0,
- I2C_ST_LAST_DATA = 0xC8,
- I2C_SR_SLA_ACK = 0x60,
- I2C_SR_ARB_LOST_SLA_ACK = 0x68,
- I2C_SR_GCALL_ACK = 0x70,
- I2C_SR_ARB_LOST_GCALL_ACK = 0x78,
- I2C_SR_DATA_ACK = 0x80,
- I2C_SR_DATA_NACK = 0x88,
- I2C_SR_GCALL_DATA_ACK = 0x90,
- I2C_SR_GCALL_DATA_NACK = 0x98,
- I2C_SR_STOP = 0xA0,
- I2C_NO_INFO = 0xF8,
- I2C_BUS_ERROR = 0x00,
- I2C_BUS_OK = 0xFF
- }NU_I2C_STATUS_ENUM;
- typedef struct
- {
- unsigned char Busy;
- unsigned int State;
- unsigned int SystickCount;
- unsigned int Count;
- unsigned int MainCount, SubCount;
- unsigned int SubAddr;
- unsigned char MainComm, SubComm;
- unsigned char TxBuffer[16], RxBuffer[16];
- }I2C_HOT_T;
- volatile I2C_HOT_T I2c;
- /***************
- ** 函数声明 **
- ***************/
- void Init_System (void);
- void Init_Uart (void);
- void Init_I2C(void);
- void I2C_Start(void);
- void I2C_REStart(void);
- void I2C_Stop(void);
- void I2C_Exit(void);
- void UART_INT_HANDLE(uint32_t u32IntStatus);
- void I2C1_INT_HANDLE (uint32_t status);
-
- /*****************************
- ** 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: I2C1_INT_HANDLE
- ** Function: I2C1 Callback function
- ** Input: status
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void I2C1_INT_HANDLE (uint32_t status)
- {
- switch(status & 0xf8)
- {
- case I2C_START://主机收到自己发送的开始信号
- if (I2c.State == I2C_START) {//本次中断应该接收TW_START信号
- I2C1->DATA = I2c.SubAddr & 0xfe;//发送子机地址(写)
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //STA位必须清除,否则死机 清除中断标志
- I2c.State = I2C_MT_SLA_ACK;//Status下次I2C_MT_SLA_ACK
- }
- else I2C_Exit();//通讯失败
- break;
- case I2C_REP_START://主机收到自己发送的重新开始信号
- if (I2c.State == I2C_REP_START) {//本次中断应该接收TW_RESTART信号
- I2C1->DATA = I2c.SubAddr | 0x01;//发送子机地址(读)
- I2c.State = I2C_MR_SLA_ACK;//Status下次I2C_MR_SLA_ACK
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //STA位必须清除,否则死机 清除中断标志
- }
- else I2C_Exit();//通讯失败
- break;
- case I2C_MT_SLA_ACK://主发机接收到从机的地址应答信号后发送命令
- if (I2c.State == I2C_MT_SLA_ACK) {//本次中断应该接收TW_MT_SLA_ACK信号
- I2c.State = I2C_MT_DATA_ACK;//Status下次应该收TW_MT_DATA_ACK
- I2C1->DATA = I2c.SubComm;//发送子机命令
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
- }
- else I2C_Exit();//通讯失败
- break;
- case I2C_MR_SLA_ACK://主收机接收到从机的地址应答信号
- if ((I2c.State == I2C_MR_SLA_ACK) && I2c.SubCount) {//本次中断应该接收TW_MR_SLA_ACK信号
- I2c.State = I2C_MR_DATA_ACK;//Status下次应该收TW_MR_DATA_ACK
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
- }
- else I2C_Exit();//通讯失败
- break;
- case I2C_MT_DATA_ACK://主收机接收到从机的数据应答信号
- if ((I2c.State == I2C_MT_DATA_ACK) && (I2c.Count < I2c.MainCount)) {//本次中断应该接收TW_MT_DATA_ACK信号
- I2C1->DATA = I2c.TxBuffer[I2c.Count ++];//发送子机数据
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
- }
- else {
- if ((I2c.State == I2C_MT_DATA_ACK) && (I2c.Count == I2c.MainCount) && (I2c.SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号
- I2C_REStart();//
- }
- else I2C_Stop();//通讯成功
- }
- break;
- case I2C_MR_DATA_ACK:
- if ((I2c.State == I2C_MR_DATA_ACK) && (I2c.Count < I2c.SubCount)) {
- I2c.RxBuffer[I2c.Count ++] = I2C1->DATA;//接收子机数据
- if (I2c.Count < I2c.SubCount) {
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
- }
- else {
- DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
- I2c.State = I2C_MR_DATA_NACK;//下次进入I2C_MR_DATA_NACK,接收数据准备完成
- }
- }
- else I2C_Exit();//通讯失败
- break;
- case I2C_MR_DATA_NACK://数据接收结束
- if ((I2c.State == I2C_MR_DATA_NACK) && (I2c.Count == I2c.SubCount)) {
- I2C_Stop();//通讯成功
- }
- else I2C_Exit();//通讯失败
- break;
- // case I2C_MT_DATA_NACK:
- // Exit();//通讯失败
- // break;
- default:
- I2C_Exit();//通讯失败
- }
- }
- /*****************************
- ** Name: Init_System
- ** Function: 系统初始化函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-03-17
- ** Note:
- ****************************/
- void Init_System(void)
- {
- /* Unlock the locked registers before access */
- UNLOCKREG();
- /* Enable the 12MHz oscillator oscillation */
- DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); //SYSCLK->PWRCON.XTL12M_EN = 1;
- /* Waiting for 12M Xtal stable */
- DrvSYS_Delay(5000);
- LOCKREG();
- }
- /*****************************
- ** Name: Init_Uart
- ** Function: UART初始化函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-03-17
- ** Note:
- ****************************/
- void Init_Uart(void)
- {
- STR_UART_T param;
-
- 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功能
- 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");
-
- DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);
-
- }
- /*****************************
- ** Name: Init_I2C
- ** Function: I2C初始化函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void Init_I2C(void)
- {
- /* Set I2C I/O */
- DrvGPIO_InitFunction(E_FUNC_I2C1);
- I2c.SubAddr = 0xA0;
- }
- /*****************************
- ** Name: I2C_Start
- ** Function: I2C启动函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void I2C_Start(void)
- {
- I2c.Busy = TRUE;
- I2c.State = I2C_START;//主机准备发送启始位
- I2c.Count = 0;//发送数据个数
- /* Open I2C1, and set clock = 50Kbps */
- DrvI2C_Open(I2C_PORT1,50000);
-
- /* Enable I2C1 interrupt and set corresponding NVIC bit */
- DrvI2C_EnableInt(I2C_PORT1);
-
- /* Install I2C1 call back function for slave */
- DrvI2C_InstallCallback(I2C_PORT1, I2CFUNC, I2C1_INT_HANDLE);
-
- DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0);
- DrvSYS_Delay(8000);
- }
- /*****************************
- ** Name: I2C_REStart
- ** Function: I2C重新启动函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void I2C_REStart(void)
- {
- I2c.Busy = TRUE;
- I2c.State = I2C_REP_START;//主机准备发送启始位
- I2c.Count = 0;//发送数据个数
- DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0);
- }
- /*****************************
- ** Name: I2C_Stop
- ** Function: I2C停止函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void I2C_Stop(void)
- {
- I2c.Busy= FALSE;
- I2c.State = I2C_BUS_OK;//通讯成功
- DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
- }
- /*****************************
- ** Name: I2C_Exit
- ** Function: I2C退出函数
- ** Input: None
- ** OutPut: None
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- void I2C_Exit(void)
- {
- I2c.Busy = FALSE;
- I2c.State = I2C_BUS_ERROR;//通讯失败
- DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
- }
- /*****************************
- ** Name: I2C_ReadByte
- ** Function: I2C写单字节函数
- ** Input: unsigned int Address, unsigned char &Data
- ** OutPut: I2c.State
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- unsigned char I2C_ReadByte(unsigned int Address, unsigned char *Data)
- {
- I2c.SubAddr |= 0x01;
- I2c.MainCount = 0;//发送0个数据(只读)
- //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
- I2c.SubComm = Address;//读出地址
- I2c.SubCount = 1;//接收1个数据
- I2C_Start();//启动I2C模块
- if (I2c.State == I2C_BUS_OK) {//通讯成功
- Data[0] = I2c.RxBuffer[0];//从接收缓冲区取出一个字节
- }
- return I2c.State;//(读出数据在RxBuffer[0]~RxBuffer[15])
- }
- /*****************************
- ** Name: I2C_ReadBuffer
- ** Function: I2C写多字节函数
- ** Input: unsigned int Address, unsigned char &Data,unsigned int Cnt
- ** OutPut: I2c.State
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- unsigned char I2C_ReadBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
- {
- int i;
- I2c.SubAddr |= 0x01;
- I2c.MainCount = 0;//发送0个数据(只读)
- //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
- I2c.SubComm = Address;//读出地址
- I2c.SubCount = (Cnt <= sizeof(I2c.RxBuffer)) ? Cnt : sizeof(I2c.RxBuffer);//接收Cnt个数据
- I2C_Start();//启动I2C模块
- if (I2c.State == I2C_BUS_OK) {//通讯成功
- for (i = 0; i < I2c.SubCount; i ++) Data[i] = I2c.RxBuffer[i];//从接收缓冲区取出Cnt个字节
- }
- return I2c.State;//(读出数据在RxBuffer[0]~RxBuffer[15])
- }
- /*****************************
- ** Name: I2C_WriteByte
- ** Function: I2C读单字节函数
- ** Input: unsigned int Address, unsigned char &Data
- ** OutPut: I2c.State
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- unsigned char I2C_WriteByte(unsigned int Address, unsigned char Data)
- {
- I2c.SubAddr &= 0xfe;
- I2c.MainCount = 1;//发送1个数据
- //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
- I2c.SubComm = Address;//写入地址
- I2c.TxBuffer[0] = Data;//写入1个数据到发送缓冲区
- I2c.SubCount = 0;//接收0个数据
- I2C_Start();//启动I2C模块
- DrvSYS_Delay(100);
- return I2c.State;
- }
- /*****************************
- ** Name: I2C_WriteBuffer
- ** Function: I2C写多字节函数
- ** Input: unsigned int Address, unsigned char &Data,unsigned int Cnt
- ** OutPut: I2c.State
- ** Data: 2011-04-26
- ** Note: 拷贝HOT大叔C++例程中IIC的操作
- ****************************/
- unsigned char I2C_WriteBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
- {
- int i;
- I2c.SubAddr &= 0xfe;
- I2c.MainCount = (Cnt <= sizeof(I2c.TxBuffer)) ? Cnt : sizeof(I2c.TxBuffer);//发送Cnt个数据
- //本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
- I2c.SubComm = Address;//写入地址
- for (i = 0; i < I2c.MainCount; i ++) I2c.TxBuffer[i] = Data[i];//写入Cnt个数据到发送缓冲区
- I2c.SubCount = 0;//接收0个数据
- I2C_Start();//启动I2C模块
- DrvSYS_Delay(100);
- return I2c.State;
- }
-
- int main (void)
- {
- uint8_t test = 250;
- uint8_t EEPROM_Data = 0; //IIC地址0x00读写数据
- uint8_t I2C_Page_Test[16]; //IIC地址0x10页读写数据
- uint8_t i = 0;
-
- Init_System();
- Init_Uart();
- Init_I2C();
- 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库及HOT大叔例程====\n");
- printf("=======2011年04月26日=======\n");
- printf("========I2C(中断)实验=======\n");
- printf("I2C中断方式完成对AT24C16的读写操作\n");
- printf("'r'为读地址0x00单字节指令、'u'为地址0x00单字节加1并存储指令\n");
- printf("'d'为地址0x00单字节减1并存储指令\n");
- printf("'R'为读地址0x10开始单页指令、'u'为地址0x10开始单页加1并存储指令\n");
- printf("'d'为地址0x10开始单页减1并存储指令\n");
- printf("===========================/\n");
- if(I2C_BUS_OK==(I2C_ReadByte(0x00,&EEPROM_Data)))
- printf("AT24C16地址0的内容为:0x%x!\n",EEPROM_Data);
- else
- printf("AT24C16地址0的内容读取失败!\n");
- if (I2C_BUS_OK==I2C_ReadBuffer(0x10,I2C_Page_Test,16))
- {
- printf("AT24C16地址0x10开始16字节的内容为:\n");
- for (i=0;i<16;i++)
- printf("0x%x ",I2C_Page_Test[i]);
- }
- else
- printf("AT24C16地址0x10开始16字节的内容读取失败!\n");
- printf("\n====请输入字符开始测试!===\n");
- printf("==========================*/\n");
- while(1)
- {
- if (IsStart)
- {
- switch (Receive_Data)
- {
- case 'R':
- if (I2C_BUS_OK==I2C_ReadBuffer(0x10,I2C_Page_Test,16))
- {
- printf("\nAT24C16地址0x10开始16字节的内容为:\n");
- for (i=0;i<16;i++)
- printf("0x%x ",I2C_Page_Test[i]);
- }
- else
- printf("\nAT24C16地址0x10开始16字节的内容读取失败!");
- break;
- case 'r':
- if (I2C_BUS_OK==I2C_ReadByte(0x00,&EEPROM_Data))
- printf("\nAT24C16地址0的内容为:0x%x!",EEPROM_Data);
- else
- printf("\nAT24C16地址0的内容读取失败!");
- break;
- case 'U':
- for (i=0;i<16;i++)
- I2C_Page_Test[i]++;
- if (I2C_BUS_OK==I2C_WriteBuffer(0x10,I2C_Page_Test,16))
- printf("\nAT24C16地址0x10开始16字节的内容加1成功!");
- else
- {
- printf("\nAT24C16地址0x10开始16字节的内容加1失败!");
- for (i=0;i<16;i++)
- I2C_Page_Test[i]--;
- }
- break;
- case 'u':
- if (I2C_BUS_OK==I2C_WriteByte(0x00,++EEPROM_Data))
- printf("\nAT24C16地址0的内容加1成功!");
- else
- printf("\nAT24C16地址0的内容加1失败!");
- break;
- case 'D':
- for (i=0;i<16;i++)
- I2C_Page_Test[i]--;
- if (I2C_BUS_OK==I2C_WriteBuffer(0x10,I2C_Page_Test,16))
- printf("\nAT24C16地址0x10开始16字节的内容减1成功!");
- else
- {
- printf("\nAT24C16地址0x10开始16字节的内容减1失败!");
- for (i=0;i<16;i++)
- I2C_Page_Test[i]++;
- }
- break;
- case 'd':
- if (I2C_BUS_OK==I2C_WriteByte(0x00,--EEPROM_Data))
- printf("\nAT24C16地址0的内容减1成功!");
- else
- printf("\nAT24C16地址0的内容减1失败!");
- break;
- default:
- printf("\n请确认您输入的指令是否合法!");
-
- }
- IsStart = FALSE;
- }
- }
- }