📄 iic.c
字号:
#define IIC_UNKNOWN() IIC_DEBUG_PUT(IIC_DEBUG_UNKNOWN,0);#else#define IIC_DEBUG_DUMP()#define IIC_W_CON(val) IICCON = val #define IIC_R_CON(val) val = IICCON#define IIC_W_BUF(val) IICBUF = val #define IIC_R_BUF(val) val = IICBUF#define IIC_S_INT() #define IIC_UNKNOWN()#endif // IIC_DEBUG////////////////////////////////////////////////////////////////////////////////// LIBRARY FUNCTIONS FOR IIC READ & WRITE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static void IICWriteIsr(void);// write page, return count of writed bytes static int IICWritePage(U32 type, U8 dev, U32 addr, U8 * data, U32 len){ int pos; while((IICCON & IICCON_BUSY) != 0){;} // wait IIC busy// switch(type) { case IIC_EEPROM_AT24C01 : // AT24C01 case IIC_EEPROM_AT24C02 : // AT24C02 pos = 8 - (addr & 0x7); // break; case IIC_EEPROM_AT24C04 : // AT24C04 case IIC_EEPROM_AT24C08 : // AT24C08 case IIC_EEPROM_AT24C16 : // AT24C16 pos = 16 - (addr & 0xF); break; default : return(0); } if(pos < len) { len = pos; } // Disable_Int(nGLOBAL_INT); // IIC_TX.flag = 0x0; // clear flag IIC_TX.count = 0x0; // current tx byte IIC_TX.msb = 0; // 8 bits of address IIC_TX.lsb = addr & 0xff; // 8 bits of address IIC_TX.size = len; // Page buffer byte counter IIC_TX.noack = 0; // no ACK flag for(pos = 0; pos < len; ++pos) { IIC_TX.buffer[pos] = *data++; // } switch(type) { case IIC_EEPROM_AT24C04 : dev = (dev & 0xFC) | ((addr >> 7) & 0x2); break; case IIC_EEPROM_AT24C08 : dev = (dev & 0xF8) | ((addr >> 7) & 0x6); break; case IIC_EEPROM_AT24C16 : dev = (dev & 0xF0) | ((addr >> 7) & 0xE); break; default : dev = (dev & 0xFE); break; } dev |= S_WRITE; // slave device address & page address IIC_TX.dev = dev; // Write to EEPROM Enable_Int(nGLOBAL_INT); // // Setup IICON register for transmit start ///////////////////////////////////// IIC_W_CON(IICCON_BF|IICCON_COND_START|IICCON_IEN);// Send Slave Address and Write command //////////////////////////////////////// while((IIC_TX.flag & IIC_PAGE_TX_DONE) == 0 && IIC_TX.noack == 0) {;} if(IIC_TX.noack != 0) { Print("\nPage write error. %d\nReset IIC", IIC_TX.noack); IICCON = IICCON_RESET; return(0); } { int wait; wait = (fMCLK / 1000 / 4 ) * 10; for(; wait > 0; --wait); }// return(len);}//// dev = device address// addr = address // data = data buffer// len = data length // int IICWrite(U8 dev, U32 addr, U8 * data, U32 len){ U32 size; int cnt;// switch(IIC_EEPROM_type) { case IIC_EEPROM_AT24C01 : size = 128; break; case IIC_EEPROM_AT24C02 : size = 256; break; case IIC_EEPROM_AT24C04 : size = 512; break; case IIC_EEPROM_AT24C08 : size = 1024; break; case IIC_EEPROM_AT24C16 : size = 2048; break; } if(data == 0 || len == 0 || addr + len > size) { return(0); } SysSetInterrupt(nIIC_INT,IICWriteIsr); // Setup IIC Tx interrupt Enable_Int(nIIC_INT); // Enable IIC interrupt while(len > 0) { cnt = IICWritePage(IIC_EEPROM_type, dev, addr, data, len); if(cnt == 0) { Print("\nIICWrite error"); Disable_Int(nIIC_INT); return(0); } len -= cnt; // remain write bytes addr += cnt; // move address data += cnt; // move data pointer } Disable_Int(nIIC_INT); return(1);}////////////////////////////////////////////////////////////////////////////////// IIC INTERRUPT SERVICE ROUTINES //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void IICWriteIsr(void){ U32 iiccon; U8 ch; IIC_S_INT(); if((IIC_TX.flag & IIC_DEV_ADDR) == 0) { IIC_R_CON(iiccon); // read control reg IIC_W_BUF(IIC_TX.dev); // write dev address to buffer reg IIC_TX.flag |= IIC_DEV_ADDR; // set write dev address done flag } else if((IIC_TX.flag & IIC_BYTE_ADDR_LSB) == 0) {// send write address ////////////////////////////////////////////////////////// IIC_R_CON(iiccon); // read control register if(iiccon & IICCON_LRB) { // not rx device address ack IIC_TX.noack |= IIC_DEV_ADDR; } IIC_W_BUF(IIC_TX.lsb); // write address IIC_TX.flag |= IIC_BYTE_ADDR_LSB; // set write address done flag } else if(IIC_TX.count < IIC_TX.size) { IIC_R_CON(iiccon); // read control register if(iiccon & IICCON_LRB) { // no ack if(IIC_TX.count == 0) { IIC_TX.noack |= IIC_BYTE_ADDR_LSB; } else { IIC_TX.noack |= IIC_PAGE_TX_DONE; } } // send next character ///////////////////////////////////////////////////////// ch = IIC_TX.buffer[IIC_TX.count++]; // IIC_W_BUF(ch); // write byte to buffer reg } else if((IIC_TX.flag & IIC_PAGE_TX_DONE) == 0) { IIC_R_CON(iiccon); if(IICCON & IICCON_LRB) { IIC_TX.noack |= IIC_PAGE_TX_DONE; } // generate stop condition //////////////////////////////////////////////////////* STOP IIC Controller */ IIC_W_CON(IICCON_COND_STOP); // write control reg IIC_R_BUF(ch); /* byte data or page data transmit done */ IIC_TX.flag |= IIC_PAGE_TX_DONE; } else { IIC_R_CON(iiccon); IIC_UNKNOWN(); }}////////////////////////////////////////////////////////////////////////////////// Read From Serial EEPROM /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static void IICReadIsr(void);void IICRead(U8 dev,U32 addr, U8 * data, U32 len){ Disable_Int(nGLOBAL_INT); // disable global Int SysSetInterrupt(nIIC_INT,IICReadIsr) ; // Setup IIC Rx interrupt Enable_Int(nIIC_INT); // Enable IIC interrupt // Wait while the iic bus is busy ////////////////////////////////////////////// while((IICCON & IICCON_BUSY) != 0) {;}// switch(IIC_EEPROM_type) { case IIC_EEPROM_AT24C04 : dev = (dev & 0xFC) | ((addr >> 7) & 0x2); break; case IIC_EEPROM_AT24C08 : dev = (dev & 0xF8) | ((addr >> 7) & 0x6); break; case IIC_EEPROM_AT24C16 : dev = (dev & 0xF0) | ((addr >> 7) & 0xE); break; default : dev = (dev & 0xFE); break; } dev |= S_WRITE; // // IIC_RX.buffer = data; // data buffer pointer IIC_RX.flag = 0x0; // interrupt flag IIC_RX.count = 0x0; // read byte count IIC_RX.size = len; // read size IIC_RX.dev = dev; // device address IIC_RX.msb = (U8)((addr>>8) & 0xff); IIC_RX.lsb = (U8) (addr & 0xff); // low byte of address IIC_RX.noack = 0;// Start, interrupt enable Enable_Int(nGLOBAL_INT); // Enable global interrupt IIC_W_CON(IICCON_BF | IICCON_COND_START | IICCON_IEN);// while((IIC_RX.flag & IIC_BYTE_RX_DONE) == 0 && IIC_RX.noack == 0) {// wait rx done or no ack condition } if(IIC_RX.noack != 0) { Print("\nIIC read error. No ack %d\nReset IIC", IIC_RX.noack); IICCON = IICCON_RESET; } Disable_Int(nIIC_INT); // Enable IIC interrupt IIC_DEBUG_DUMP();}////////////////////////////////////////////////////////////////////////////////// IIC read ISR ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void IICReadIsr(void){ U32 iiccon; // U8 ch; // IIC_S_INT(); if((IIC_RX.flag & IIC_DEV_ADDR) == 0) { IIC_W_BUF(IIC_RX.dev); // write dev addr IIC_RX.flag |= IIC_DEV_ADDR; // set write device address done flag } else if((IIC_RX.flag & IIC_BYTE_ADDR_LSB) == 0) {////////////////////////////////////////////////////////////////////////////////// send low byte of word address /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IIC_R_CON(iiccon); // read control reg if(iiccon & IICCON_LRB) { IIC_RX.noack |= IIC_DEV_ADDR; } IIC_W_BUF(IIC_RX.lsb); // write low byte of address word IIC_RX.flag |= IIC_BYTE_ADDR_LSB; // send lsb byte addr } else if((IIC_RX.flag & IIC_REPEAT_START) == 0) {////////////////////////////////////////////////////////////////////////////////// Generate Repeat Start /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IIC_R_CON(iiccon); if(iiccon & IICCON_LRB) { IIC_RX.noack |= IIC_BYTE_ADDR_LSB; } IIC_W_CON(IICCON_COND_RESTART|IICCON_IEN);// Generate Start //////////////////////////////////////////////////////////////// BF, Start Condition, ACK enable, interrupt enable IIC_W_CON(IICCON_BF|IICCON_COND_START|IICCON_ACK|IICCON_IEN);// Select device ///////////////////////////////////////////////////////////////// device address// read bit IIC_W_BUF((IIC_RX.dev | S_READ)); IIC_RX.flag |= IIC_REPEAT_START; } else if((IIC_RX.flag & IIC_MULTI_RECV) == 0) {/* Receive multiple data */ IIC_R_CON(iiccon); if(IICCON & IICCON_BF) { IIC_RX.flag |= IIC_MULTI_RECV; } IIC_W_CON(IICCON_ACK|IICCON_IEN); IIC_R_BUF(ch); } else if(IIC_RX.count < IIC_RX.size) {////////////////////////////////////////////////////////////////////////////////// read received byte ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IIC_R_CON(iiccon); if(iiccon & IICCON_LRB) { IIC_RX.noack |= IIC_MULTI_RECV; } IIC_R_BUF(ch); *(IIC_RX.buffer)++ = ch; // write rx byte to buffer IIC_RX.count++; // received bytes } else if((IIC_RX.flag & IIC_NO_MORE_RECV) == 0) { /* Now,no more received data is required from slave */ IIC_W_CON(IICCON_NOACK | IICCON_IEN); IIC_RX.flag |= IIC_NO_MORE_RECV; } else if((IIC_RX.flag & IIC_BYTE_RX_DONE) == 0) { /* Receive last data and STOP */ IIC_R_BUF(ch); IIC_W_CON(IICCON_COND_STOP); IIC_R_BUF(ch);/* byte data receive done */ IIC_RX.flag |= IIC_BYTE_RX_DONE; } else { IIC_UNKNOWN(); }}////////////////////////////////////////////////////////////////////////////////// read from console address & byte value and write byte to serial EEPROM //////////////////////////////////////////////////////////////////////////////////////void IICWriteByteTest(void){ U32 size; // EEPROM size U32 addr; // EEPROM address U8 ch; // writed character// size = IICEEPROMSize(); Print("\nEnter Byte Write address of IIC EEPROM (up to [0x%x]) ", size // up limit off address );// addr = get_number(16,0); // read address from console if(addr >= size) // check input address { Print("\nByte address [0x%x] not valid\n", addr); return; } while(kbd_hit()) { // clear input ch = get_byte(); // from console } // Print("\nEnter writed byte 0x"); ch = get_number(16,0); // read byte from console IICWriteByte(addr, ch);}////////////////////////////////////////////////////////////////////////////////// read address from console and read byte from EEPROM /////////////////////////////////////////////////////////////////////////////////////////////////////////void IICReadByteTest(void){ U32 size; // serial EEPROM size U32 addr; // addres int cnt; U8 ch; // read character // size = IICEEPROMSize(); Print("\nEnter Byte Read address of IIC EEPROM (up to [0x%x]) ", size // up limit off address );// addr = get_number(16,0); // read address from console if(addr >= size) // check input address { Print("\nByte address [0x%x] not valid\n", addr); return; } Print("\nEnter count of bytes (up to %d) ", size - addr); cnt = get_number(10, 3); if(cnt > size - addr) {cnt = size - addr;} if(cnt < 1) {cnt = 1;} Print("\n"); while(cnt-- > 0) { if(IICReadByte(addr, & ch) != 0) { Print("0x%02x ", ch); } addr++; }}////////////////////////////////////////////////////////////////////////////////// IIC Test using IIC 64Kbit Serial EEPROM /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void IICTest(void) { IICSetup(); // Initialize IIC control block Enable_Int(nGLOBAL_INT); // enable global interrupt mask while(1) { U8 it;// print EEPROM name, device address Print("\n\nIIC %s Test. Device Address %d", IICEEPROMName(), IICEEPROMAddr());// Print("\n[W] IIC Page Write Test."); Print("\n[R] IIC Sequential Read Test."); Print("\n[L] IIC Read/Write Test."); Print("\n[C] IIC Configuration View."); Print("\n[S] IIC EEPROM type & address Select."); Print("\n[B] IIC Byte Write."); Print("\n[D] IIC Byte Read."); Print("\n[T] IIC Byte Write & Read Test."); Print("\n[Q] Quit IIC Test"); Print("\nSelect Test Item : "); it = get_upper(); switch(it) { case 'W' : IICWriteTest(); break; // EEPROM write case 'R' : IICReadTest(); break; // EEPROM read case 'L' : IICWriteReadTest(0); break; // EEPROM write & read test case 'C' : IICConfig(); break; // IIC configuration case 'S' : IICEEPROMSelect(); break; // Select IIC EEPROM case 'B' : IICWriteByteTest(); break; case 'D' : IICReadByteTest(); break; case 'T' : IICByteTest(); break; // IIC Byte Write & Read Test case 'Q' : return; default : break; }// Print("\nPress Any Key to Continue IIC Test") ; it = get_upper(); if(it == 'Q') { return; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -