Всем привет. Работаю с через i2c с флэшкой STMicroelectronics M24M02-DR, микроконтроллер msp430f47187, использую встроенный i2c модуль микроконтроллера. Режим master transmit/recieve В двух словах принцип работы флэшки такой: Запись (изначально модуль настроен на передачу (transmit)): 0. старт 1. отправить байт адреса устройства (это делает встроенный i2c модуль) 2. отправить 2 байта адреса записываемого байта (начала адреса записываемого массива байтов(страницы байтов)) по одному 3. Отправлять байты для записи 4. стоп Флэшка может писать либо байтами либо страницами (<=256байт), после каждой записи запускается внутренний "Write cycle", который длится максимум 10 мс. На это время флеха отключается от i2c, а после можно продолжать с ней работу.
Чтение (изначально модуль настроен также на передачу (transmit)): 0.старт 1. отправить байт адреса устройства (это делает встроенный i2c модуль) 2. отправить 2 байта адреса по одному считываемого байта(байтов) 3. Перенастроить модуль на прием 4.старт 5. считывать байты (ловить прерывания ресивера) 6.стоп Считывать можно как единичный байт, так и страницу. Проблема состоит в следующем: после цикла чтения почему то в течении какого-то времени флешка не реагирует на команды, как будто опять включается WriteCycle (т.е. не получается продолжить работу сразу после чтения, а если поставить задержку те же 10 мс, все нормально). pdf читал внимательно, на несколько раз, все равно не нашел ошибку. Может кто сталкивался с таким...
Проверяю так: без дополнительной задержки: запись, чтение, запись(не работает) с задержкой: запись, чтение, запись, чтение.... все работает
Судя по документации на флешку никаких задержек при чтении делать не нужно!!!!!
Исходный код (тактирование 16 МГц, оптимизации нет) union MyFloat { float flt; char b[4]; };
class CFlashMemory { public: CFlashMemory(void); void WriteFloat(unsigned long, float); void ReadFloat(unsigned long, float&); };
CFlashMemory::CFlashMemory(void) { UCB1CTL1 |= UCSWRST;// Enable SW reset UCB1CTL0 = UCMODE_3 + UCMST + UCSYNC; // I2C Master, synchronous mode
UCB1CTL1 |= UCSSEL_2 + UCSWRST;// clock from SMCLK UCB1BR0 = 0xa0; //freq = 100 kHz UCB1BR1 = 0x0; UCB1I2CSA = 80; // Slave Address is 0A0h where b7-b4(device type identifier):1010; b3(chip enable (grounded is scheme)):0; b2-b1(msb address bits): 00; b0(RW): 0 P2SEL |= BIT1 + BIT2; UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation } CFlashMemory FlashMemory = CFlashMemory();
void CFlashMemory::WriteFloat(unsigned long address, float f) { MyFloat temp; temp.flt = f; UCB1I2CSA = 80; UCB1I2CSA |= (address&( (1uL<<16) + (1uL<<17) ))>>16;//specific of the device 1st MSB bits of address
UCB1CTL1 |= UCTR; // master transmitter mode UCB1CTL1 |= UCTXSTT;//init start condition
while(!(UC1IFG & UCB1TXIFG)); UCB1TXBUF = (address>>8) & 0x000000ffuL;//MSB of address
while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = address & 0x000000ffuL;//LSB of address
while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = temp.b[0];//send byte 1 while(!(UC1IFG & UCB1TXIFG)); UCB1TXBUF = temp.b[1];//send byte 2 while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = temp.b[2];//send byte 3 while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = temp.b[3];//send byte 4 while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1CTL1 |= UCTXNACK; UCB1CTL1 |= UCTXSTP;//init stop condition UC1IFG &= ~UCB1TXIFG; __delay_cycles(160000); }
void CFlashMemory::ReadFloat(unsigned long address, float &f) { MyFloat temp; UCB1I2CSA = 80; UCB1I2CSA |= address&((1uL<<16)+(1uL<<17))>>16;//specific of the device 1st MSB bits of address UCB1CTL1 |= UCTR; // master transmitter mode UCB1CTL1 |= UCTXSTT;//init start condition while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = (address>>8) & 0x000000ffuL;//MSB of address while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UCB1TXBUF = address & 0x000000ffuL;//LSB of address while(!(UC1IFG & UCB1TXIFG));//wait 4 tx interrupt UC1IFG &= ~UCB1TXIFG; UCB1CTL1 &= ~UCTR; // master reciever mode UCB1CTL1 |= UCTXSTT;//init start condition while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt temp.b[0] = UCB1RXBUF;//read byte 0 UC1IFG &= ~UCB1RXIFG; while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt temp.b[1] = UCB1RXBUF;//read byte 1 UC1IFG &= ~UCB1RXIFG; while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt temp.b[2] = UCB1RXBUF;//read byte 2 UC1IFG &= ~UCB1RXIFG; while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt temp.b[3] = UCB1RXBUF;//read byte 3 UC1IFG &= ~UCB1RXIFG; //while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt UCB1CTL1 |= UCTXSTP;//init stop condition f = temp.flt; //__delay_cycles(160000);//?????????????????????????????????????????????? }
|