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);函数对C6748的IIC0模块所在复用引脚的功能配置为IIC引脚。设置SYSCFG0模块的PINMUX4寄存器的PINMUX4_15_12和PINMUX4_11_8字段都为2,则设置了引脚功能为I2C0_SDA和I2C0_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();函数初始化串口终端,使用串口2。UARTStdioInit函数做的事主要是对PSC1(Power and Sleep Controller)进行设置,使能UART2模块,然后设置UART2模块所在复用引脚的功能为TX和RX,并设置UART2的串口参数为8数据位,1停止位,无校验位,UART模式为FIFO模式,然后使能UART的free运行模式,启动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;}
函数先等待UART的THR和TSR寄存器为空,等待上次发送完成,然后再写一个字符数据到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 selector的INTMUX1寄存器的INTSEL6字段(INTMUX1_16_22位)为36(SYS_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,并使能I2C0,I2CMasterInitExpClk函数如下:
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,所以inputClk为24MHz。scaledClk为经过I2C模块预分频后的时钟频率,范围应该在6.7到13.3MHz之间。OutputClk为I2C_SCL时钟线上的频率。函数对ICPSC寄存器的IPSC字段,以及ICCCLKL、ICCLKH寄存器作相应设置,从而得到正确的I2C_SCL频率。IPSC字段必须要在I2C模块处于reset/disable状态时设置,否则设置无效。
(指南P131)
(指南P130)
(指南P906)
(指南P917)
(指南P917)
(指南P934)
然后I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, ADDRESS);设置从机设备地址为ADDRESS(0x50,IICEEPROM地址)。I2C的slave address有7位和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;}
设置ICMDR的IRS位为1,从而使能I2C,并设置ICEMDR的BCM位为0,当C6748的I2C0作为从设备,并且要往主设备发送数据时,可以产生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);设置I2C的data 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 condition。I2CMasterControl函数如下:
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 register,ICIMR)的相应位置位,使能I2C中断的Transmit-data-ready interrupt、Stop condition interrupt、No-acknowledgment interrupt等中断源(interrupt source)。当这些I2C中断源事件出现时,就会产生系统中断事件IIC0_INT(EVT#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 flag,ICXRDY)为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)
如果intCode非0,进入while循环,清除ER(Event flag)寄存器中的事件标志(#36),然后根据intCode作相应处理。因为是发送中断,所以intCode=I2C_INTCODE_TX_READY,I2CMasterDataPut(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)
当发送完最后一个数据后,初值为ICCNT的internal 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中断屏蔽寄存器ICIMR(I2C interrupt mask register)的ICXRDY、NACK、SCD位都清0,从而屏蔽这些I2C中断事件。因为此时没有I2C中断事件产生了(或者被屏蔽了),所有再一次读取I2C中断向量寄存器时,中断码intCode将会变为0,从而程序指针将会跳出I2C中断服务函数,回到II2发送数据程序IICSend,然后while(I2CMasterBusBusy(iic));等待SDL线上的最后一个数据发送完成,完成后跳转回主函数。
回到主函数,当EEPROM进入内部写周期之后,就要对其进行Acknowledge Polling写操作,轮询其写周期是否已结束。EEPROMAckPolling();函数不断查询数据是否已经写进EEPROM。EEPROMAckPolling函数如下:
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的中断码。最后清除EF(Event flag)寄存器中对应I2C0_INT中断的标志位,然后设置标志变量txComFlag=0表示数据发送完成,AckRolling=1,表明轮询无应答,当回到EEPROMAckPolling函数时,还需继续轮询,直到AckRolling=0为止,主函数再继续向下。
memset(buf_recv,0,8);函数为C/C++自带的库函数,其作用是将从buf_recv指向的地址开始,往后8个字节的区别全部赋值为0,利用该函数可以实现对block和array的快速清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);函数读取Data。IICReceive函数如下:
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函数中设置ICCNT,ICCNT为要接收的数据量。在I2CMasterControl函数中,设置ICMDR的RX位为1(不同于IICSend的TX位),从而设置I2C设备为接收模式。在I2CMasterIntEnableEx函数中设置ICIMR寄存器的ICRRDY位(Receive-data-ready interrupt enable bit)为1,使能Receive-data-ready interrupt(不同于IICSend的ICXRDY位,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,而此时ICMDR的STP位为1,所以会产生STOP condition,然后会产生SCD(stop 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位,最大只可能有8位16进制位,然后打印到串口,每打印一位数先判断一下该数是否大于等于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);从EEPROM的0x00地址处开始连续写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);从EEPROM的0x00地址处开始,连续读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)
如果读出的页有一个字节与写进的页不等,则写入与读出不一致,否则一致。
- C6748_I2C
- fullcalendar的stripTime
- HDU
- 51nod 1463 找朋友(线段树 离线)
- SpaceX要再次创造历史:回收的猎鹰9号火箭本周将被再次发射
- Android Studio中 ADB WIFI插件进行无线调试实践
- C6748_I2C
- linux 创建用户useradd与adduser 删除用户userdel 创建删除用户组命令
- 高通骁龙835首秀,和麒麟960、联发科X30、三星Exynos 8895相比如何?| 解析
- nginx单点故障怎么破?
- 类,超类和子类
- Hibernate5下配置Druid连接池
- 数组模拟实现二叉堆——(为以后的链表实现二叉堆打基础) _清风明月
- 腾讯成特斯拉第五大股东,暂不会主动介入运营事务
- IBM如何在云计算上追赶AWS、Google和微软?