Herz 6 11 мая, 2020 Опубликовано 11 мая, 2020 · Жалоба Решил я, на старости лет, освоить MSP430. Наверное напрасно: после ПИКов - голова кругом. Но уже жаль потраченного времени, чтобы отступить. Поэтому пока не сдаюсь. Купил LaunchPad на FR2355, установил Code Composer Studio v.9, полистал немного доки. Именно "немного", потому что их - вагон, а садиться за парту, как обычно, времени нет. Поэтому обучение приходится проводить "в процессе". Подключил по I2C сенсор TMP275 с целью освоения заодно этого интерфейса. Раньше с ним не работал, всегда предпочитал SPI. Нашёл на просторах сети простенький пример работы с I2C от какого-то индуса, немного подправил. Пока использую поллинг флага запонения приёмного регистра - вроде всё работает: 1. Записиваю число 0х00 в Pointer Register сенсора. Мол, читать буду регистр температуры. Проходит, получаю ACK. 2. Читаю температурный регистр, получаю адекватное значение температуры. Но, читаю только первый байт, остальные не интересуют. Потому сразу посылаю STOP. 3. Повторяю всё в цикле, выглядит нормально. Смущает немного только некоторая задержка (30мкс) между чтением и записью. Частота клока - 132кГц. Частота DCO (по умолчанию) - 2МГц. */ #include <msp430.h> // Direction mode of I2c bus (0 - transmit, 1 - receive) unsigned char Dir_Mode = 0; unsigned char TXByteCtr; // transmit bytes counter int PRxData; // received data int i; // counter unsigned char Pointer; // content of pointer register byte // P0, P1 codes of Pointer Register for internal TMP275 addressing int const Temp_REG = 0; int const Config_REG = 1; int const itgAddress = 0x4F; void init_I2C(void); void Transmit(void); void Receive(void); /** * main.c */ int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer // Set P1.4 to output direction P1DIR |= BIT4; // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; P4SEL0 |= BIT6 + BIT7; // Assign I2C pins to USCI_B1 init_I2C(); Pointer = Temp_REG; while(1) { //Transmit process Dir_Mode = 0; Transmit(); while (UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent //Receive process Dir_Mode = 1; Receive(); while (UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent } } void init_I2C(void) { UCB1CTL1 |= UCSWRST; // Enable SW reset UCB1CTLW0 |= UCMST + UCMODE_3; // I2C Master, synchronous mode UCB1BRW = 8; // fSCL = SMCLK/8 UCB1CTLW1 = UCASTP_2; // automatic stop assertion UCB1TBCNT = 1; // TX only 1 byte of data UCB1I2CSA = itgAddress; // Slave Address is 0x4Fh UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB1IE |= UCRXIE0 + UCTXIE0; //Enable RX and TX interrupt // __bis_SR_register(GIE); // Enable global interrupts } void Transmit(void) { UCB1CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition while (UCB1CTL1 & UCTXSTT); // Start condition sent? UCB1TXBUF = Pointer; } void Receive(void) { UCB1CTL1 &= ~UCTR ; // Clear UCTR (set Receiver mode) UCB1CTL1 |= UCTXSTT; // I2C start condition P1OUT |= BIT4; // P1.4 on (LED on) while (UCB1CTL1 & UCTXSTT); // Start condition sent? while (!(UCB1IFG & UCRXIFG0)); UCB1CTL1 |= UCTXSTP; // I2C stop condition, after one byte only PRxData = UCB1RXBUF; // Get RX data } Но, если пытаюсь заменить поллинг прерыванием, выползает странность. 1. Записи числа 0х00 в Pointer Register не происходит. 2. Чтение по-прежнему выполняется (только потому, что в Pointer Register сохранился адрес температурного регистра). 3. После чтения STOP-condition не проходит, хотя в продпрограмме обработки прерывания я его посылку прописал, и даже дожидаюсь окончания. Вместо этого сразу начинается следующая запись. */ #include <msp430.h> // Direction mode of I2c bus (0 - transmit, 1 - receive) unsigned char Dir_Mode = 0; unsigned char TXByteCtr; // transmit bytes counter int PRxData; // received data int i; // counter unsigned char Pointer; // content of pointer register byte // P0, P1 codes of Pointer Register for internal TMP275 addressing int const Temp_REG = 0; int const Config_REG = 1; int const itgAddress = 0x4F; void init_I2C(void); void Transmit(void); void Receive(void); /** * main.c */ int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer // Set P1.4 to output direction P1DIR |= BIT4; // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; P4SEL0 |= BIT6 + BIT7; // Assign I2C pins to USCI_B1 init_I2C(); Pointer = Temp_REG; while(1) { //Transmit process Dir_Mode = 0; Transmit(); while (UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent //Receive process Dir_Mode = 1; Receive(); while (UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent } } void init_I2C(void) { UCB1CTL1 |= UCSWRST; // Enable SW reset UCB1CTLW0 |= UCMST + UCMODE_3; // I2C Master, synchronous mode UCB1BRW = 8; // fSCL = SMCLK/8 UCB1CTLW1 = UCASTP_2; // automatic stop assertion UCB1TBCNT = 1; // TX only 1 byte of data UCB1I2CSA = itgAddress; // Slave Address is 0x4Fh UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB1IE |= UCRXIE0 + UCTXIE0; //Enable RX and TX interrupt __bis_SR_register(GIE); // Enable global interrupts } void Transmit(void) { UCB1CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition while (UCB1CTL1 & UCTXSTT); // Start condition sent? UCB1TXBUF = Pointer; } void Receive(void) { UCB1CTL1 &= ~UCTR ; // Clear UCTR (set Receiver mode) UCB1CTL1 |= UCTXSTT; // I2C start condition P1OUT |= BIT4; // P1.4 on (LED on) while (UCB1CTL1 & UCTXSTT); // Start condition sent? // while (!(UCB1IFG & UCRXIFG0)); // UCB1CTL1 |= UCTXSTP; // I2C stop condition, after one byte only // PRxData = UCB1RXBUF; // Get RX data } //------------------------------------------------------------------------------- // Interrupt routine // //------------------------------------------------------------------------------- #pragma vector = EUSCI_B1_VECTOR __interrupt void EUSCI_B1_TX_ISR(void) { switch(__even_in_range(UCB1IV,0x1e)) { case 0x00: // Vector 0: No interrupts break; case 0x02: // Vector 2: ALIFG, Arbitration lost break; case 0x04: // Vector 4: NACKIFG, Not acknowledgment break; case 0x06: // Vector 6: STTIFG, Start condition received break; case 0x08: // Vector 8: STPIFG, Stop condition received break; case 0x0a: // Vector 10: RXIFG3, Slave 3 Data received break; case 0x0c: // Vector 12: TXIFG3, Slave 3 Transmit buffer empty break; case 0x0e: // Vector 14: RXIFG2, Slave 2 Data received break; case 0x10: // Vector 16: TXIFG2, Slave 2 Transmit buffer empty break; case 0x12: // Vector 18: RXIFG1, Slave 1 Data received break; case 0x14: // Vector 20: TXIFG1, Slave 1 Transmit buffer empty break; case 0x16: // Vector 22: RXIFG0, Data received, receiver buffer is full P1OUT &= ~BIT4; // P1.4 off PRxData = UCB1RXBUF; // Get RX data UCB1CTL1 |= UCTXSTP; // I2C stop condition while (UCB1CTL1 & UCTXSTP); // wait for stop pass break; case 0x18: // Vector 24: TXIFG0, Transmit buffer is empty break; case 0x1a: // Vector 26: BCNTIFG, Byte counter zero break; case 0x1c: // Vector 28: clock low time-out break; case 0x1e: // Vector 30: 9th bit break; default: break; } } Здесь зелёный луч - состояние пина P1.4, это я пытаюсь проконтролировать время от посылки START-a в режиме Recieve до собственно начала обработки прерывания по заполнению буфера приёмника. Выходит, что обработка начинается уже в период записи (Transmit), хотя сам Transmit начаться, вроде бы, не должен, пока STOP от чтения не пройдёт (см. строку while (UCB1CTL1 & UCTXSTP); // wait for stop pass )... Что тут происходит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Baser 5 11 мая, 2020 Опубликовано 11 мая, 2020 · Жалоба А чего вы именно за MSP430 взялись? Из-за аналоговых плюшек? Мы вот потихоньку пытаемся с них сползти через 20 лет работы с ними. Бедность периферии просто выводила из себя. По вашему вопросу я может скажу неправду, т.к. с FR серией никогда не работал, но в сериях F1xxx и F2xxx периферийный модуль I2C был просто безобразный по неудобству работы и по наличию странных проблем в дизайне. Короче, за последние 10 лет я несколько раз делал попытки его применить, и натыкаясь на очередную бяку опускал руки Все I2C функции и до меня и у меня на фирме работают чисто программно. Все наглядно и просто, но правда, поллинг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 11 мая, 2020 Опубликовано 11 мая, 2020 · Жалоба 23 минуты назад, Baser сказал: По вашему вопросу я может скажу неправду, т.к. с FR серией никогда не работал, но в сериях F1xxx и F2xxx периферийный модуль I2C был просто безобразный по неудобству работы и по наличию странных проблем в дизайне. Не надо возводить напраслину на MSP430! Хотя я делал всего один проект на нём (MSP430FR5739), но с существенными проблемами не сталкивался. I2C использовал и, естественно, аппаратный и естественно - без поллингов, по прерываниям. Всё нормально там. 48 минут назад, Herz сказал: 3. После чтения STOP-condition не проходит, хотя в продпрограмме обработки прерывания я его посылку прописал, и даже дожидаюсь окончания. Вместо этого сразу начинается следующая запись. Что-то как-то странно у Вас выглядит ISR. Я конечно давно уже занимался MSP430 и многое забыл, но что-то у Вас там сильно много чего не хватает. Обрабатывается только UCRXIFG0... Ещё и цикл ожидания внутри ISR! Бррр.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 10 hours ago, Baser said: А чего вы именно за MSP430 взялись? Купился на низкое потребление, всякие там LPM... Хотя, если разобраться, то не так уж важно. Но впервые слышу о том, что сам МК плохой. Вроде много чего на нём (них) сделано. 10 hours ago, jcxz said: Что-то как-то странно у Вас выглядит ISR. Я конечно давно уже занимался MSP430 и многое забыл, но что-то у Вас там сильно много чего не хватает. Обрабатывается только UCRXIFG0... Ещё и цикл ожидания внутри ISR! Бррр.... Согласен, некрасиво. Но так было сделано только для проверки. И именно ситуации с завершением чтения - посылкой STOP. Так и не понятно, отчего она не проходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 13 минут назад, Herz сказал: Купился на низкое потребление, всякие там LPM... Хотя, если разобраться, то не так уж важно. Но впервые слышу о том, что сам МК плохой. Вроде много чего на нём (них) сделано. И не жалейте! Хорошее семейство. Для своей ниши. Особенно радует то, что есть встроенная FRAM. Мне в своё время очень понравилась их система тактирования, с удобным отключением неиспользуемых частот + режимы LPM (у меня было батарейное устройство) с удобным входом/выходом из них. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Baser 5 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 11 часов назад, jcxz сказал: Не надо возводить напраслину на MSP430! Хотя я делал всего один проект на нём (MSP430FR5739), но с существенными проблемами не сталкивался. I2C использовал и, естественно, аппаратный и естественно - без поллингов, по прерываниям. Всё нормально там. Напраслину я не возвожу и сверх меры не хаю Само ядро и система команд очень неплохая. И во время старта производства, начало 2000-х, MSP430 был прорывом. По потреблению с ним никто тогда не мог соревноваться. Но времени прошло много. Еще раз скажу, что серии с FRAM я не применял, может быть они существенно новее и лучше. И сама технология FRAM выглядит очень привлекательно. 43 минуты назад, Herz сказал: Купился на низкое потребление, всякие там LPM... Хотя, если разобраться, то не так уж важно. Но впервые слышу о том, что сам МК плохой. Вроде много чего на нём (них) сделано. Нормальная серия МК, но уже некоторое время назад его представители общего применения начали проигрывать АРМ-ам. А вот специализированные серии MSP430 - хороши. Я пару лет назад смотрел, на чем делать новые проекты (старые были на MSP430F1xx и F2xx) и ничего хорошего не выбрал. В сериях F1xx и F2xx периферия очень бедная, серии F5xx и F6xx уже проигрывали по потреблению, да и улучшение периферии было небольшим. Сейчас перехожу на STM32, т.к. по критериям скорость+периферия+потребление+цена, у STM32 можно выбрать лучший вариант, чем у MSP430. з.ы. сейчас глянул, что Тексас наковал сотни новых MSP430 с разными буковками - возможно они сделали шаг вперед. А так, 15 лет они топтались на месте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 7 minutes ago, Baser said: серии F5xx и F6xx уже проигрывали по потреблению, да и улучшение периферии было небольшим. Сейчас перехожу на STM32, т.к. по критериям скорость+периферия+потребление+цена, у STM32 можно выбрать лучший вариант, чем у MSP430. По потреблению сейчас всех уделывает RE от Renesas - https://www.renesas.com/us/en/products/microcontrollers-microprocessors/re.html А MSP430 давно морально устарели. Применяли их в аналоговых модулях ПЛК Сименс, потому и живы до сих пор. Но это не значит что индивидуальные разработчики должны на них западать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexunder 4 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 4 minutes ago, AlexandrY said: По потреблению сейчас всех уделывает RE от Renesas - https://www.renesas.com/us/en/products/microcontrollers-microprocessors/re.html а как же кинетисы? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 55 minutes ago, alexunder said: 59 minutes ago, AlexandrY said: По потреблению сейчас всех уделывает RE от Renesas - https://www.renesas.com/us/en/products/microcontrollers-microprocessors/re.html а как же кинетисы? А как же EFM32 ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexunder 4 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 20 minutes ago, dimka76 said: А как же EFM32 ? Волшебные! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 12 мая, 2020 Опубликовано 12 мая, 2020 · Жалоба 23 hours ago, Herz said: . . . Подключил по I2C сенсор TMP275 с целью освоения заодно этого интерфейса. Раньше с ним не работал, всегда предпочитал SPI. . . . Нашёл на просторах сети простенький пример работы с I2C от какого-то индуса, немного подправил. C I2C довольно отдельная песТня, тк много-чего зависит от слейва. Сильно желательно использование лог. анализатора. В качестве примеров я всегда брал "родные" Ti (хотя пишут теже индусы многие). Конкретно для FR2355 у меня нет, вот на MSP430FR57xx_Code_Examples. "Преемственность" периферии во-многом сохраняется, есть документация "Migration to . . ". Есть также пакет msp430_driverlib_1_97_00_19.zip - там на все проц-ры, в т.ч. FR2x (сюда выложить не получается по размеру) slac491d.zip part_MSP430FR2xx_4xx.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 13 мая, 2020 Опубликовано 13 мая, 2020 · Жалоба Спасибо, я практически всё это находил, но... 1) Примеры от Тексаса слишком "наворочены" как для меня, начинающего. Они там попытались объять все случаи и сделать унивесальные библиотеки, но вышло очень громоздко и запутано. 2) Я сознательно не хочу "перескакивать" на другие примеры, пока не разберусь, почему не работает этот. Для меня важнее найти ошибку, чем найти работающий код. Хотя, возможно, выбора не останется, придётся сравнивать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
controller_m30 1 13 мая, 2020 Опубликовано 13 мая, 2020 (изменено) · Жалоба В 12.05.2020 в 00:07, Herz сказал: Здесь зелёный луч - состояние пина P1.4, это я пытаюсь проконтролировать время от посылки START-a в режиме Recieve до собственно начала обработки прерывания по заполнению буфера приёмника. Выходит, что обработка начинается уже в период записи (Transmit), хотя сам Transmit начаться, вроде бы, не должен, пока STOP от чтения не пройдёт (см. строку while (UCB1CTL1 & UCTXSTP); // wait for stop pass )... Что тут происходит? Видно три цветных блока (Оранжевый №1, Синий, Оранжевый №2) 1. Первый оранжевый блок - START+Addr+R (вероятно это он) 2. Синий блок - считанный первый байт 3. После этого наступает прерывание по приёму байта (зеленый луч=0) 4. Второй оранжевый блок - считанный второй байт, и вероятно после этого состояние STOP. Причина чтения двух байт вместо одного - в обработчике прерывания флаг STOP устанавливается после прочтения регистра данных, а это запускает чтение следующего байта. А чтобы прочитался только один байт, нужно установить флаг STOP перед прочтением регистра данных. Т.е. в обработчике прерывания поменять местами строки В 12.05.2020 в 00:07, Herz сказал: PRxData = UCB1RXBUF; // Get RX data UCB1CTL1 |= UCTXSTP; // I2C stop condition Изменено 13 мая, 2020 пользователем controller_m30 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 13 мая, 2020 Опубликовано 13 мая, 2020 · Жалоба И еще один момент: после получения последнего байта ведущий должен выставить на шину NAK вместо ACK. Это заставит ведомого прекратить выдавать биты на шину и позволит ведущему сформировать STOP или повторный START после окончания NACK (в противном случае ведомый начнет в этом месте выдавать первый бит следующего байта, который может оказаться нулем и не позволит сформировать STOP или START). При беглом просмотре вашего кода из первого сообщения никаких упоминаний NACK я не увидел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
controller_m30 1 14 мая, 2020 Опубликовано 14 мая, 2020 · Жалоба Не разглядел, что на картинке второй оранжевый блок это запись START+Addr+W. Но байта данных за ним нет... Пока видится два варианта: 1. Выключить прерывание Transmit в команде инициализации UCB1IE |= UCRXIE0 + UCTXIE0; //Enable RX and TX interrupt Потому что этот обработчик пустой, и может это как-то влияет на нежелание передавать байт данных. 2. Или прерывание не выключать, а перенести в обработчик этого прерывания команду UCB1TXBUF = Pointer; Может из обработчика данные всё-же отправятся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться