Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
#define I2C_TIMEOUT (50 RTOS_MS)
#define EEPROM_PAGE_SIZE 16
#include
#include
#include#define I2C_EN (1<<6)
#define I2C_START (1<<5)
#define I2C_STOP (1<<4)
#define I2C_INT (1<<3)
#define I2C_ACK (1<<2)enum {IDLE, SEND_START, SEND_DEV_ADDR, SEND_ADDR, EXCHG_DATA, SEND_STOP};
struct {
union {
struct {
uint8_t Read:1;
uint8_t SlaveAddr:3;
uint8_t DeviceID:4;
};
uint8_t DevAddr;
};
uint8_t Addr;
uint16_t Counter;
uint8_t *pData;
xSemaphoreHandle Busy;
portTickType Time;
volatile uint8_t flag;
} I2C;static uint_fast8_t I2C_Lock (void) {
if(I2C.Busy == NULL) {
vSemaphoreCreateBinary(I2C.Busy);
if( I2C.Busy == NULL ) return 0; // unable to create semaphore
}
if( xSemaphoreTake(I2C.Busy, I2C_TIMEOUT * 2) == pdFALSE )
return 0; // timeout expired
I2C.flag = 1;
return 1;
}static void I2C_UnLock(void) {
vTaskDelay( I2C_TIMEOUT );
if(I2C.flag) { // Error
VICIntEnClear = (1UL << VIC_I2C);
I2CONCLR = ( I2C_ACK | I2C_START | I2C_STOP | I2C_INT );
I2CONSET = ( I2C_EN );
}
xSemaphoreGive(I2C.Busy); // release semaphore
}uint_fast8_t I2C_EEPROM_Read (uint_fast16_t EE_Addr, uint8_t *pDest, uint_fast16_t bytes) {
if(!I2C_Lock()) return 0; // unable to get access to bus;
I2C.DeviceID = 0xA;
I2C.SlaveAddr = EE_Addr >> 8;
I2C.Read = 1;
I2C.Addr = EE_Addr;
I2C.pData = pDest;
I2C.Counter = bytes;
I2CONCLR = ( I2C_ACK | I2C_START | I2C_STOP | I2C_INT );VICIntEnable = (1UL << VIC_I2C);
I2CONSET = ( I2C_EN | I2C_START );I2C_UnLock();
return I2C.Counter == 0;
}
uint_fast8_t I2C_EEPROM_Write (uint_fast16_t EE_Addr, uint8_t *pDest, uint_fast16_t bytes) {
if(!I2C_Lock()) return 0; // unable to get access to bus;uint_fast16_t BytesToWrite;
{
uint_fast16_t AddrOffset = EE_Addr & (EEPROM_PAGE_SIZE - 1); // offset in page;if( AddrOffset + bytes > EEPROM_PAGE_SIZE ) // page boundary
BytesToWrite = EEPROM_PAGE_SIZE - AddrOffset;
}do {
if(BytesToWrite > bytes)
BytesToWrite = bytes;I2C.DeviceID = 0xA;
I2C.SlaveAddr = EE_Addr >> 8;
I2C.Read = 0;
I2C.Addr = EE_Addr;
I2C.pData = pDest;
I2C.Counter = BytesToWrite;
I2CONCLR = ( I2C_ACK | I2C_START | I2C_STOP | I2C_INT );VICIntEnable = (1UL << VIC_I2C);
I2CONSET = ( I2C_EN | I2C_START );I2C_UnLock();
if(I2C.Counter) return 0; // error
bytes -= BytesToWrite;
EE_Addr += BytesToWrite;
pDest += BytesToWrite;
BytesToWrite = EEPROM_PAGE_SIZE;
} while(bytes);
return 1;
}__arm __irq void I2C_handler(void) {
switch(I2STAT) {
case 0x08: // Start done
I2DAT = I2C.DevAddr & ~(1<<0); // SEND SLA+W
I2CONCLR = (I2C_INT | I2C_START);
break;
case 0x20: // Slave addr NACK
I2CONSET = I2C_STOP | I2C_START; // generate stop
I2CONCLR = I2C_INT;
break;
case 0x18: // Slave addr ACK
I2DAT = I2C.Addr;
I2CONCLR = I2C_INT;
break;
case 0x28: // Byte transfer ACK
if(I2C.Read) {
I2CONSET = I2C_START; // generate repeated start
I2CONCLR = I2C_INT;
} else { // Write
if(I2C.Counter) {
I2DAT = *I2C.pData++;
I2C.Counter--;
} else {
I2CONSET = I2C_STOP;
I2C.flag = 0;
}
I2CONCLR = I2C_INT;
}
break;
case 0x10: // Repeated start done
I2DAT = I2C.DevAddr; // SEND SLA+R
I2CONCLR = (I2C_INT | I2C_START);
break;
case 0x40: // Slave ACKed SLA+R
if(I2C.Counter != 1) //
I2CONSET = I2C_ACK; // send ACK if not last byte
I2CONCLR = I2C_INT;
break;
case 0x50: // Byte received with ACK
*I2C.pData++ = I2DAT;
I2C.Counter--;
if(I2C.Counter == 1)
I2CONCLR = I2C_ACK; // send NACK after last byte
I2CONCLR = I2C_INT;
break;
case 0x58: // Last byte received
*I2C.pData++ = I2DAT;
I2C.Counter--;
I2CONSET = I2C_STOP;
I2C.flag = 0;
I2CONCLR = I2C_INT;
break;default: // unexpected status
I2CONCLR = I2C_EN | I2C_INT;
I2C.flag = 0;
I2CONSET = I2C_EN;
__no_operation();
}
VICVectAddr = 0; // Reset VIC logic
}