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

 
 
> 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
 
Start new topic
Ответов
mib383
сообщение Jun 18 2012, 08:58
Сообщение #2


Участник
*

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



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


Гуру
******

Группа: Модераторы
Сообщений: 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



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

 


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


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