реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> msp430 + flash память
mib383
сообщение Jun 18 2012, 04:35
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177



Всем привет.
Работаю с через 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);//??????????????????????????????????????????????
}

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 18 2012, 06:16
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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

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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
mib383
сообщение Jun 18 2012, 07:32
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177



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

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

NACK перед(сразу после приема предпоследнего) и после приема последнего байта пробовал, не помогает.
И в документации на msp написано, что если МК настроен на ресив, то перед стоп состоянием он генерит NACK

Сообщение отредактировал mib383 - Jun 18 2012, 08:08
Go to the top of the page
 
+Quote Post
mib383
сообщение Jun 18 2012, 08:58
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177



Ладно, допустим NACK я поставил неправильно. Между какими строками мне его вставить, чтобы отмести эту проблему
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 18 2012, 13:53
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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; вам не нужно - подтверждения выдает ваша память, вы их слушаете.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
mib383
сообщение Jun 20 2012, 03:43
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177



Спасибо большое, помогло.
Go to the top of the page
 
+Quote Post
mib383
сообщение Jul 19 2012, 06:42
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177



Опять столкнулся с проблемой! Исходный код:
Код
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 запарился

Сообщение отредактировал mib383 - Jul 19 2012, 06:43
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 09:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01416 секунд с 7
ELECTRONIX ©2004-2016