Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: msp430 + flash память
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
mib383
Всем привет.
Работаю с через 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);//??????????????????????????????????????????????
}

Сергей Борщ
QUOTE (mib383 @ Jun 18 2012, 07:35) *
после цикла чтения почему то в течении какого-то времени флешка не реагирует на команды, как будто опять включается WriteCycle
Не вижу посылки NACK в ответ на последний считанный байт. В процессе передачи вижу (там она вроде как и лишняя и не к месту), а в приеме - не вижу. Не к месту - потому что взводить NACK надо перед приемом последнего байта или во время приема, но никак не после. Странно, что помогает задержка.

P.S. используйте кнопку оформления кода для публикации коротких исходников и теги [ codebox ] [ /codebox ] для длинных.
mib383
Цитата(Сергей Борщ @ Jun 18 2012, 13:16) *
Не вижу посылки NACK в ответ на последний считанный байт. В процессе передачи вижу (там она вроде как и лишняя и не к месту), а в приеме - не вижу. Не к месту - потому что взводить NACK надо перед приемом последнего байта или во время приема, но никак не после. Странно, что помогает задержка.

P.S. используйте кнопку оформления кода для публикации коротких исходников и теги [ codebox ] [ /codebox ] для длинных.

NACK перед(сразу после приема предпоследнего) и после приема последнего байта пробовал, не помогает.
И в документации на msp написано, что если МК настроен на ресив, то перед стоп состоянием он генерит NACK
mib383
Ладно, допустим NACK я поставил неправильно. Между какими строками мне его вставить, чтобы отмести эту проблему
Сергей Борщ
QUOTE (mib383 @ Jun 18 2012, 11:58) *
Между какими строками мне его вставить, чтобы отмести эту проблему
Заставили меня глянуть в описание процессора. NACK он формирует сам после получения UCB1CTL1 |= UCTXSTP.

Но и вы прочитайте описание:
QUOTE
Setting the UCTXSTP bit will generate a STOP condition. After setting
UCTXSTP, a NACK followed by a STOP condition is generated after reception
of the data from the slave, or immediately if the USCI module is currently
waiting for UCBxRXBUF to be read.


CODE
If UCBxRXBUF is not read the master holds the bus during reception of the last
data bit and until the UCBxRXBUF is read.


QUOTE
When performing multiple consecutive I2C master transactions without the
repeated start feature, the current transaction must be completed before the
next one is initiated. This can be done by ensuring that the transmit stop
condition flag UCTXSTP is cleared before the next I2C transaction is initiated
with setting UCTXSTT = 1. Otherwise, the current transaction might be
affected.


Значит ваш код должен выглядеть примерно так:
CODE
while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt
UCB1CTL1 |= UCTXSTP;  //init stop condition
temp.b[3] = UCB1RXBUF;//read byte 3

while( UCB1CTL1 & UCTXSTP);  //wait until STOP processed


Нажмите для просмотра прикрепленного файла

И в процессе передачи дергать UCB1CTL1 |= UCTXNACK; вам не нужно - подтверждения выдает ваша память, вы их слушаете.
mib383
Спасибо большое, помогло.
mib383
Опять столкнулся с проблемой! Исходный код:
Код
void CFlashMemory::ReadByte(unsigned long address, char &byte)
{
  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

  UCB1CTL1 &= ~UCTR; // master reciever mode
  UCB1CTL1 |= UCTXSTT;//init start condition
  while(UCB1CTL1 & UCTXSTT);
  
  while(!(UC1IFG & UCB1RXIFG));//wait 4 rx interrupt
  UCB1CTL1 |= UCTXSTP;//init stop condition
  byte = UCB1RXBUF;//read byte

  while( UCB1CTL1 & UCTXSTP);
}

Функция работает через раз! Когда не работает, то после первого UCB1CTL1 |= UCTXSTT; генерится NACK. Ничего понять не могу, где ошибка может быть....
И второе, по идее после первого UCB1CTL1 |= UCTXSTT; нужно ставить цикл while(UCB1CTL1 & UCTXSTT); Но при попытке его туда вписать, программа просто зацикливается на нем!
Помогите пожалуйста. Уже совсем с этим i2c запарился
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.