C6748_I2C

来源:互联网 发布:mac 导入图片在哪里 编辑:程序博客网 时间:2024/05/21 17:40

此程序实现C6748的IIC模块对IICEEPROM设备的数据读写功能,地址是0x50(高7位)。程序先写入并读出一个字节数据,然后写入并读出一页数据,接着对比写入和读出的数据,根据结果判断IICEEPROM设备读写是否成功,主函数如下:

intmain(void){    int i,result;    unsignedchar buf_send[8];    unsignedchar buf_recv[8];     //I2C管脚配置    I2CPinMuxSetup(0);     // 初始化串口终端使用串口2    UARTStdioInit();     // 打印串口终端信息    UARTPuts("Tronlong IIC EEPROM Application......\r\n\r\n", -1);    // 中断初始化    InterruptInit();    IICInterruptInit();     // IIC初始化    IICInit(); // 写一个字节UARTPuts("Write single byte to address 0x0, value is 0x55.\r\n\r\n", -1);EEPROMByteWrite(0x0, 0x55);// 等待写完成EEPROMAckPolling(); // 读一个字节memset(buf_recv,0,8);buf_recv[0] = EEPROMRandomRead(0);UARTPuts("Read one byte at a address 0x0, the value is ", -1);UARTPutHexNum(buf_recv[0]);    UARTPuts(".\r\n\r\n", -1); // 读取当前地址值buf_recv[1] = EEPROMCurrentAddressRead();    UARTPuts("Read one byte at current address 0x0, the value is ", -1);UARTPutHexNum(buf_recv[1]);    UARTPuts(".\r\n\r\n", -1);     for(i=0;i<8;i++){    if(i%2 ==0)        buf_send[i]=0xaa;    else        buf_send[i]=0x55;}// 连续写指定长度(一个页面)    UARTPuts("Write one page (8 bytes) to address 0x0.\r\n\r\n", -1);EEPROMPageWrite(0x00,buf_send,8);// 等待写完成EEPROMAckPolling();memset(buf_recv,0,8); // 连续读指定长度(一个页面)    UARTPuts("Read one page (8 bytes) at address 0x0.\r\n\r\n", -1);EEPROMSequentialRead(0x00,buf_recv,8); result = 1;for (i=0;i<8;i++){    if (buf_send[i]!=buf_recv[i])    {        result = 0;        break;    }} // 如果 result 等于 1 ,说明写入的字节值与读出的字节值全部相同。否则,写入与读取的不一致    if (result)        UARTPuts("Verify successfully.\r\n", -1);    else        UARTPuts("Verify failed.\r\n", -1); for(;;){ }}


I2CPinMuxSetup(0);函数对C6748IIC0模块所在复用引脚的功能配置为IIC引脚。设置SYSCFG0模块的PINMUX4寄存器的PINMUX4_15_12PINMUX4_11_8字段都为2,则设置了引脚功能为I2C0_SDAI2C0_SCL

(手册P22

(指南P204

(指南P226

函数如下:

voidI2CPinMuxSetup(unsignedint instanceNum){unsignedint savePinMux = 0; if(0 == instanceNum){ savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \~(SYSCFG_PINMUX4_PINMUX4_15_12 | \SYSCFG_PINMUX4_PINMUX4_11_8); HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \(PINMUX4_I2C0_SDA_ENABLE | \PINMUX4_I2C0_SCL_ENABLE | \savePinMux); } elseif(1 == instanceNum){savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \~(SYSCFG_PINMUX4_PINMUX4_23_20 | \SYSCFG_PINMUX4_PINMUX4_19_16); HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \(PINMUX4_I2C1_SDA_ENABLE | \PINMUX4_I2C1_SCL_ENABLE | \savePinMux); } else{ } }


主函数配置了I2C管脚后,就调用UARTStdioInit();函数初始化串口终端,使用串口2UARTStdioInit函数做的事主要是对PSC1Power and Sleep Controller)进行设置,使能UART2模块,然后设置UART2模块所在复用引脚的功能为TXRX,并设置UART2的串口参数为8数据位,1停止位,无校验位,UART模式为FIFO模式,然后使能UARTfree运行模式,启动UART2,详细细节可参考这篇博文:

http://blog.csdn.net/zengaliang/article/details/78348051

启动UART2之后,串口2就可以进行收发了。先是打印串口终端信息,UARTPuts("Tronlong IIC EEPROM Application......\r\n\r\n", -1);UARTPuts函数判断要发送的字符是否已经是空字符,如果不是,则调用UARTPutc函数将字符写到UART的transmitter FIFO,如果是,就退出。UARTPuts函数如下:

unsignedintUARTPuts(char *pTxBuffer, int numBytesToWrite){unsignedint count = 0;unsignedint flag = 0; if(numBytesToWrite < 0){flag = 1;} while('\0' != *pTxBuffer){/* Checks if data is a newline character. */if('\n' == *pTxBuffer){/* Ensuring applicability to serial console.*/UARTPutc('\r');UARTPutc('\n');}else{UARTPutc((unsignedchar)*pTxBuffer);}pTxBuffer++;count++; if((0 == flag) && (count == numBytesToWrite)){break;} }/* Returns the number of bytes written onto the transmitter FIFO. */return count;}


UARTPutc函数如下:

voidUARTPutc(unsignedchar byteTx){UARTConsolePutc(byteTx);}


UARTConsolePutc函数如下:

voidUARTConsolePutc(unsignedchar data){UARTCharPut(UART_CONSOLE_BASE, data);}


UART_CONSOLE_BASE在程序中被定义为0x01D0 D000,即UART2模块的基地址。UARTCharPut函数如下:

voidUARTCharPut(unsignedint baseAdd, unsignedchar byteTx){unsignedint txEmpty; txEmpty = (UART_THR_TSR_EMPTY | UART_THR_EMPTY); /*** Here we check for the emptiness of both the Trasnsmitter Holding** Register(THR) and Transmitter Shift Register(TSR) before writing** data into the Transmitter FIFO(THR for non-FIFO mode).*/ while (txEmpty != (HWREG(baseAdd + UART_LSR) & txEmpty)); /*** Transmitter FIFO(THR register in non-FIFO mode) is empty.** Write the byte onto the THR register.*/HWREG(baseAdd + UART_THR) = byteTx;}


函数先等待UARTTHRTSR寄存器为空,等待上次发送完成,然后再写一个字符数据到THR

 

回到主函数,进行中断初始化工作,InterruptInit();函数使能全局中断,IICInterruptInit();进行IIC中断初始化,IICInterruptInit函数如下:

voidIICInterruptInit(void){IntRegister(C674X_MASK_INT6, IICIsr);IntEventMap(C674X_MASK_INT6, SYS_INT_I2C0_INT);    IntEnable(C674X_MASK_INT6);}


IICInterruptInit函数注册CPU#6号可屏蔽中断的服务函数为IICIsr,设置interrupt selectorINTMUX1寄存器的INTSEL6字段(INTMUX1_16_22位)为36SYS_INT_I2C0_INT),将#36号中断事件映射到CPU#6号可屏蔽中断,然后使能CPU#6号可屏蔽中断,IntEnable(C674X_MASK_INT6)

(手册P94

回到主函数,中断初始化完成后,对IIC初始化,IICInit();IICInit函数如下:

voidIICInit(void){//IIC 复位 / 禁用I2CMasterDisable(SOC_I2C_0_REGS); // 配置总线速度为 100KHzI2CMasterInitExpClk(SOC_I2C_0_REGS, 24000000, 8000000, 100000); // 设置从设备地址I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, ADDRESS); // IIC 使能I2CMasterEnable(SOC_I2C_0_REGS);}


函数先是复位IIC0模块,I2CMasterDisable函数如下:

voidI2CMasterDisable(unsignedint baseAddr){/* Bring the I2C module out of reset */HWREG(baseAddr + I2C_ICMDR) &= ~(I2C_ICMDR_IRS);}


I2CMasterDisable函数清除I2C0外设的ICMDR寄存器(I2C Mode Register)的IRS位,从而复位并禁用I2C0

(手册P184

(指南P917

(指南P929

然后I2CMasterInitExpClk(SOC_I2C_0_REGS, 24000000,8000000, 100000);函数I2C主模块的操作进行初始化,配置I2C0的总线速度为100KHz,并使能I2C0I2CMasterInitExpClk函数如下:

voidI2CMasterInitExpClk(unsignedint baseAdd, unsignedint inputClk,unsignedint scaledClk, unsignedint outputClk){unsignedint prescale = 0;unsignedint dValue = 0;unsignedint div = 0; /* Calculate the prescalar value */prescale = (inputClk/scaledClk) - 1; HWREG(baseAdd + I2C_ICPSC) = prescale; switch (prescale){case 0:dValue = 7;break;case 1:dValue = 6;break;default:dValue = 5;break;} div = scaledClk/outputClk;div -= (2*dValue); HWREG(baseAdd + I2C_ICCLKL)= div/2;HWREG(baseAdd + I2C_ICCLKH) = div - HWREG(baseAdd + I2C_ICCLKL); return;}


函数的输入参数列表,inputClk为输入I2C模块的时钟,I2C0的输入时钟为PLL旁路时钟,晶振的时钟为24MHz,所以inputClk24MHzscaledClk为经过I2C模块预分频后的时钟频率,范围应该在6.713.3MHz之间。OutputClkI2C_SCL时钟线上的频率。函数对ICPSC寄存器的IPSC字段,以及ICCCLKLICCLKH寄存器作相应设置,从而得到正确的I2C_SCL频率。IPSC字段必须要在I2C模块处于reset/disable状态时设置,否则设置无效。

(指南P131

(指南P130

(指南P906

(指南P917

(指南P917

(指南P934

然后I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, ADDRESS);设置从机设备地址为ADDRESS0x50IICEEPROM地址)。I2Cslave address7位和10位以及free mode三种形式,在7位和10位从机地址后面会跟一个读写位R/Wn,根据I2C是发送方还是接收方来决定。I2CMasterSlaveAddrSet函数如下:

voidI2CMasterSlaveAddrSet(unsignedint baseAddr, unsignedint slaveAddr){/*Set the address of the slave with which the master will communicate.*/HWREG(baseAddr + I2C_ICSAR) = slaveAddr;}


(指南P917

(指南P926

(指南P909

(指南P910

完成了对I2C0的设置后,就可以使能I2C了,

I2CMasterEnable(SOC_I2C_0_REGS);函数如下:

voidI2CMasterEnable(unsignedint baseAddr){/* Bring the I2C module out of reset */HWREG(baseAddr + I2C_ICMDR) |= I2C_ICMDR_IRS; /* Set the backward compatibility mode off, for proper interruption */HWREG(baseAddr + I2C_ICEMDR) &= ~I2C_ICEMDR_BCM;}


设置ICMDRIRS位为1,从而使能I2C,并设置ICEMDRBCM位为0,当C6748I2C0作为从设备,并且要往主设备发送数据时,可以产生transmit data ready中断。

(指南P917

(指南P933

这样所有的初始化工作就完成了,回到主函数,先往EEPROM写一个字节(0x55)的数据,EEPROMByteWrite(0x0, 0x55);EEPROMByteWrite函数如下:

voidEEPROMByteWrite(unsignedint Address, unsignedchar Data){slaveData[0] = Address;slaveData[1] = Data; IICSend(SOC_I2C_0_REGS,2);}


IICSend函数为阻塞函数,只有当CPU执行完该函数才能执行其他操作,否则无法执行其他操作,函数如下:

voidIICSend(unsignedint iic, unsignedint dataCnt){txCompFlag = 1;dataIdx = 0; while(I2CMasterBusBusy(iic)); I2CSetDataCount(iic, dataCnt); I2CMasterControl(iic, I2C_CFG_MST_TX | I2C_CFG_STOP); I2CMasterIntEnableEx(iic, I2C_INT_TRANSMIT_READY | I2C_INT_STOP_CONDITION | I2C_INT_NO_ACK); I2CMasterStart(iic); // 等待数据发送完成while(txCompFlag); while(I2CMasterBusBusy(iic));}while(I2CMasterBusBusy(iic));判断IIC设备是否正忙,如果正忙,则一直等待,直到空闲为止。I2CMasterBusBusy函数如下:unsignedintI2CMasterBusBusy(unsignedint baseAddr){return ((HWREG(baseAddr + I2C_ICSTR) & I2C_ICSTR_BB));}


(指南P917

(指南P920

I2CSetDataCount(iic, dataCnt);设置I2Cdata count寄存器(ICCNT),该寄存器的值表明I2C处于主收发器(master-transmitter-receiver)且重复模式(repeat mode)被关闭(off)的情况下要传输的字节数。I2CSetDataCount函数如下:

voidI2CSetDataCount(unsignedint baseAddr, unsignedint count){HWREG(baseAddr + I2C_ICCNT)= count;}


(指南P917

(指南P924

I2CMasterControl(iic, I2C_CFG_MST_TX | I2C_CFG_STOP);函数配置I2C控制器的运行模式为主发送器模式(Master-transmitter Mode),并对STP位置位,产生STOP条件(condition)。当内部的数据计数器计到0时(所有要发送的数据都已发送),对STP位置位会产生一个STOP conditionI2CMasterControl函数如下:

voidI2CMasterControl(unsignedint baseAddr, unsignedint cmd){/* Since, the IRS bit needs to be set, to bring the module out* of local reset, we do that here, every time*/HWREG(baseAddr + I2C_ICMDR) = cmd;HWREG(baseAddr + I2C_ICMDR) |= I2C_ICMDR_IRS;}


(指南P929

(指南P929

(指南P929

然后对IRS位置1,使能I2C模块。I2CMasterIntEnableEx(iic, I2C_INT_TRANSMIT_READY | I2C_INT_STOP_CONDITION | I2C_INT_NO_ACK);I2C中断屏蔽寄存器(I2C interrupt mask registerICIMR)的相应位置位,使能I2C中断的Transmit-data-ready interruptStop condition interruptNo-acknowledgment interrupt中断源(interrupt source。当这些I2C中断源事件出现时,就会产生系统中断事件IIC0_INTEVT#36)。I2CMasterIntEnableEx函数如下:

voidI2CMasterIntEnableEx(unsignedint baseAddr, unsignedint intFlag){/*Enable the master interrupt.*/HWREG(baseAddr + I2C_ICIMR) |= intFlag;}


(指南P917

(指南P919

使能I2C中断的中断源之后,就可以启动I2C的数据发送了。I2CMasterStart(SOC_I2C_0_REGS);函数如下:

voidI2CMasterStart(unsignedint baseAddr){HWREG(baseAddr + I2C_ICMDR) |= I2C_ICMDR_STT;}


(指南P928

启动I2C传输后,因为默认情况下,发送数据准备好标志(transmit-data-ready interrupt flagICXRDY)为1,此时满足transmit ready条件,所以会产生transmit interrupt,程序跳转到中断服务函数IICIsr中。

(指南P916

中断服务函数voidIICIsr(void)如下:

voidIICIsr(void){volatileunsignedint intCode = 0; // 取得中断代码intCode = I2CInterruptVectorGet(SOC_I2C_0_REGS); while(intCode!=0){    // 清除中断事件    IntEventClear(SYS_INT_I2C0_INT);         if (intCode == I2C_INTCODE_TX_READY)        {         I2CMasterDataPut(SOC_I2C_0_REGS, slaveData[dataIdx]);         dataIdx++;        }         if(intCode == I2C_INTCODE_RX_READY)        {         slaveData[dataIdx] = I2CMasterDataGet(SOC_I2C_0_REGS);         dataIdx++;        }         if (intCode == I2C_INTCODE_STOP)        {         I2CMasterIntDisableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY |                                             I2C_INT_DATA_READY |                                             I2C_INT_NO_ACK |                                             I2C_INT_STOP_CONDITION);         txCompFlag = 0;        }         if (intCode == I2C_INTCODE_NACK)        {         I2CMasterIntDisableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY |                                             I2C_INT_DATA_READY |                                             I2C_INT_NO_ACK |                                             I2C_INT_STOP_CONDITION);         // 产生停止位         I2CMasterStop(SOC_I2C_0_REGS);          I2CStatusClear(SOC_I2C_0_REGS, I2C_CLEAR_STOP_CONDITION);          // 清除中断         IntEventClear(SYS_INT_I2C0_INT);         txCompFlag = 0;         AckRolling = 1;        }         if (I2CMasterIntStatus(SOC_I2C_0_REGS) & I2C_ICSTR_NACKSNT)        {         I2CMasterIntDisableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY |                                             I2C_INT_DATA_READY |                                             I2C_INT_NO_ACK |                                             I2C_INT_STOP_CONDITION);          // 产生停止位         I2CMasterStop(SOC_I2C_0_REGS);          I2CStatusClear(SOC_I2C_0_REGS, (I2C_CLEAR_NO_ACK_SENT |                                         I2C_CLEAR_STOP_CONDITION));          // 清除中断         IntEventClear(SYS_INT_I2C0_INT);         txCompFlag = 0;        }         intCode = I2CInterruptVectorGet(SOC_I2C_0_REGS);}}函数中先是获得中断代码intCode,从而获得造成I2C中断的I2C中断源是什么(STOP Condition、No ack acknowledgement等等)。I2CInterruptVectorGet(SOC_I2C_0_REGS);函数如下:unsignedintI2CInterruptVectorGet(unsignedint baseAddr){return (HWREG(baseAddr + I2C_ICIVR) & I2C_ICIVR_INTCODE);}


(指南P917

(指南P932

如果intCode0,进入while循环,清除EREvent flag)寄存器中的事件标志(#36),然后根据intCode作相应处理。因为是发送中断,所以intCode=I2C_INTCODE_TX_READYI2CMasterDataPut(SOC_I2C_0_REGS, slaveData[dataIdx]);将要发送的数据写到ICDXR寄存器中,I2CMasterDataPut函数如下:

voidI2CMasterDataPut(unsignedint baseAddr, unsignedchar data){/*write data to be transmited to Data transmit register */HWREG(baseAddr + I2C_ICDXR) = data;}


(指南P917

(指南P927

当发送完最后一个数据后,初值为ICCNTinternal data counter变为0,此时,因为ICMDR寄存器的STP位为1,所以产生STOP condition,从而产生stop condition detected interrupt,读取中断码intCode时为6,进入该中断处理分支,在该处理分支中,I2CMasterIntDisableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY |

                                             I2C_INT_DATA_READY |

                                             I2C_INT_NO_ACK |

                                             I2C_INT_STOP_CONDITION);

函数将I2C中断屏蔽寄存器ICIMRI2C interrupt mask register)的ICXRDYNACKSCD位都清0,从而屏蔽这些I2C中断事件。因为此时没有I2C中断事件产生了(或者被屏蔽了),所有再一次读取I2C中断向量寄存器时,中断码intCode将会变为0,从而程序指针将会跳出I2C中断服务函数,回到II2发送数据程序IICSend,然后while(I2CMasterBusBusy(iic));等待SDL线上的最后一个数据发送完成,完成后跳转回主函数。

 

回到主函数,当EEPROM进入内部写周期之后,就要对其进行Acknowledge Polling写操作,轮询其写周期是否已结束。EEPROMAckPolling();函数不断查询数据是否已经写进EEPROMEEPROMAckPolling函数如下:

voidEEPROMAckPolling(void){    do    {        AckRolling = 0;        Delay(0xFFFFF);        slaveData[0] = ADDRESS;        IICSend(SOC_I2C_0_REGS, 1);        Delay(0xFFFFF);    }while(AckRolling==1);}


AT24C02手册P9

如果EEPROM写操作还没完成,轮询将不会得到回应,因此会产生NCAK中断。IIC中断服务函数会进入该分支段。

       

 if (intCode == I2C_INTCODE_NACK)        {         I2CMasterIntDisableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY |                                             I2C_INT_DATA_READY |                                             I2C_INT_NO_ACK |                                             I2C_INT_STOP_CONDITION);         // 产生停止位         I2CMasterStop(SOC_I2C_0_REGS);          I2CStatusClear(SOC_I2C_0_REGS, I2C_CLEAR_STOP_CONDITION);          // 清除中断         IntEventClear(SYS_INT_I2C0_INT);         txCompFlag = 0;         AckRolling = 1;        }

在该函数分支段中,程序关闭相关的I2C中断使能位,然后对ICMDR寄存器的STP位置位,手动产生stop condition,终止I2C数据传输(I2C transaction),I2CMasterStop函数如下:

voidI2CMasterStop(unsignedint baseAddr){HWREG(baseAddr + I2C_ICMDR) |= I2C_ICMDR_STP;}


再清除ICSTR寄存器的I2C中断标志位,此时的intCode应该是NACK的中断码。最后清除EFEvent flag)寄存器中对应I2C0_INT中断的标志位,然后设置标志变量txComFlag=0表示数据发送完成,AckRolling=1,表明轮询无应答,当回到EEPROMAckPolling函数时,还需继续轮询,直到AckRolling=0为止,主函数再继续向下。

 

memset(buf_recv,0,8);函数C/C++自带的库函数,其作用是将从buf_recv指向的地址开始,往后8个字节的区别全部赋值为0,利用该函数可以实现对blockarray的快速清0. EEPROMRandomRead(0);EEPROM指定地址处读取一个字节,函数如下:

unsignedcharEEPROMRandomRead(unsignedint Address){    slaveData[0] = Address;     IICSend(SOC_I2C_0_REGS,1);    IICReceive(SOC_I2C_0_REGS, 1);     return slaveData[0];}


根据手册,读指定地址字节之前,需先往从设备写指定地址,所以先调用函数IICSend(SOC_I2C_0_REGS,1);,然后调用IICReceive(SOC_I2C_0_REGS, 1);函数读取DataIICReceive函数如下:

voidIICReceive(unsignedint iic, unsignedint dataCnt){txCompFlag = 1;dataIdx = 0; while(I2CMasterBusBusy(SOC_I2C_0_REGS)); I2CSetDataCount(SOC_I2C_0_REGS, dataCnt); I2CMasterControl(SOC_I2C_0_REGS, I2C_CFG_MST_RX | I2C_CFG_STOP); I2CMasterIntEnableEx(SOC_I2C_0_REGS, I2C_INT_DATA_READY | I2C_INT_STOP_CONDITION | I2C_INT_NO_ACK); I2CMasterStart(SOC_I2C_0_REGS); // 等待数据接收完成while(txCompFlag); while(I2CMasterBusBusy(SOC_I2C_0_REGS));}


函数与IICSend函数大同小异,在I2CSetDataCount函数中设置ICCNTICCNT为要接收的数据量。在I2CMasterControl函数中,设置ICMDRRX位为1(不同于IICSendTX位),从而设置I2C设备为接收模式。在I2CMasterIntEnableEx函数中设置ICIMR寄存器的ICRRDY位(Receive-data-ready interrupt enable bit)为1,使能Receive-data-ready interrupt(不同于IICSendICXRDY位,Transmit-data-ready interrupt enable bit)。

AT24C02手册P11

I2C0收到数据时,会产生接收中断,然后程序进入中断服务程序。读取I2C中断码intCode,此时intCode等于I2C_INTCODE_RX_READY。然后I2CMasterDataGet(SOC_I2C_0_REGS);函数读取数据到数组中,当读取了ICCNT个数据后,存储了ICCNT值的internal data counter变为0,而此时ICMDRSTP位为1,所以会产生STOP condition,然后会产生SCDstop condition detected)中断,再读intCode,会进入I2C_INTCODE_STOP中断的处理分支,操作与IICSend的时候是一样的。I2CMasterDataGet函数如下:

unsignedintI2CMasterDataGet(unsignedint baseAddr){unsignedint rData; rData = HWREG(baseAddr + I2C_ICDRR);return rData;}


函数读取ICDRR寄存器的值。

(指南P917

(指南P925

回到主函数,打印串口信息,UARTPuts("Read one byte at a address 0x0, the value is ", -1);然后UARTPutHexNum(buf_recv[0]);打印buf_recv[0]数据的16进制形式到串口。UARTPutHexNum函数如下:

voidUARTPutHexNum(unsignedint hexValue){unsignedchar num[8] = {0};unsignedint quotient = 0;unsignedint dividend = 0;int count = 0; dividend = hexValue; do{quotient = dividend/16;num[count] = (unsignedchar)(dividend % 16);if(0 == quotient){break;}count++;dividend = quotient; }while(count < 8); if(8 == count){count--;} UARTPutc('0');UARTPutc('x'); while(count >= 0){/* Checking for alphanumeric numbers. */if((16 - num[count]) <= 6){/* Printing alphanumeric numbers. */UARTPutc(num[count--] + 0x37);}else{/* Printing numbers in the range 0 to 9. */UARTPutc(num[count--] + 0x30);}}}


函数将收到的数据转换为16进制,从16进制的最低位开始,每次除16取余数获得该位的数值,并将其存入num数组中,然后除16将数值右移4位,再除16求余数获得第二位的数值,一直重复下去,直到为0,重复次数最多8次,因为unsigned int数据为32位,最大只可能有816进制位,然后打印到串口,每打印一位数先判断一下该数是否大于等于10,是就打印成A-E,不是则打印该数的ASCII码。

 

回到主函数,读取EEPROM当前地址存的字节到buf_recv[1]中,EEPROMCurrentAddressRead函数如下:

unsignedcharEEPROMCurrentAddressRead(void){    IICReceive(SOC_I2C_0_REGS, 1);     return slaveData[0];}


读取EEPROM当前地址的字节不需要先写字节地址(word address)这一步操作了(dummy write),直接发送设备地址就行了。

AT24C02手册P11

主函数继续往下,EEPROMPageWrite函数往EEPROM连续写指定长度,EEPROMPageWrite(0x00,buf_send,8);EEPROM0x00地址处开始连续写8个字节buf_send数组的数据。EEPROMPageWrite函数如下:

voidEEPROMPageWrite(unsignedint Address, unsignedchar *Data, unsignedint Size){    int i;     slaveData[0] = Address;     for (i=0;i<Size;i++)        slaveData[i+1] = Data[i];     IICSend(SOC_I2C_0_REGS, Size + 1);}


AT24C02手册P10

然后对EEPROM进行轮询操作,等待数据写完成。EEPROMSequentialRead函数再从指定地址连续读指定长度的数据出来到数组中,

EEPROMSequentialRead(0x00,buf_recv,8);EEPROM0x00地址处开始,连续读8个字节的数并存到buf_recv数组中,EEPROMSequentialRead函数如下:

voidEEPROMSequentialRead(unsignedint Address , unsignedchar * Data , unsignedint Size){    int i;     slaveData[0] = Address;     IICSend(SOC_I2C_0_REGS,1);    IICReceive(SOC_I2C_0_REGS, Size);     for (i=0;i<Size;i++)        Data[i] = slaveData[i] ;}


AT24C02手册P11

(指南P909

 

如果读出的页有一个字节与写进的页不等,则写入与读出不一致,否则一致。