主题中讨论的其他器件: MSP-FET
您好!
我想详细了解一下 MSP430的较新 FRAM 系列、并决定使用 MSP430FR2422……
我的项目如下所示:
LoRa 模块(SX1278)通过 SPI (SPI 模式下的 UCA0)连接到 MSP430FR2422。 MSP430由 DCO (1MHz)提供时钟、RTC 由 VLO (10kHz)提供时钟。 未连接外部晶振。
一切都应该依靠电池运行数月。 主电源为3节带有 LDO 的 AAA 电池。
因此、我决定使用低功耗模式3.5 (LPM3.5)、并且我目前每10秒唤醒一次 MSP430、使用 RTC 进行测试、以发送6字节的 LoRa 数据包。
稍后、这10秒当然会设置为更高的周期时间。
在 LPM3.5模式下、我测得的功耗为200nA (0.2uA)、这是一种奇妙的结果。
通过 RTC 中断的唤醒也运行良好。
LoRa 接收器成功接收来自 MSP430的6个字节的数据包(在10秒内)。
问题是、只有第一个数据包的数据是正确的。
第2个数据包中的数据不正确。 这些对我来说是完全随机的。
我知道 LPM3.5中的 RAM 内容丢失。
在 LoRa 数据包(6字节有效载荷)内、有一个计数器应该对已经发送的数据包进行计数。
LPM3.5之后、MSP430FR2422复位、计数器值丢失或在重新启动后重新初始化...
还有一个固定的、唯一的器件 ID。
这在重新启动后也是完全错误的。
一般而言、我现在问自己如何正确地"保存"计数器值(变量/char 数组)。
现在有几个问题:
1.在切换到 LPM3.5 (RAM -> FRAM)之前、是否必须将整个 RAM 内容写入 FRAM? 之后、唤醒/复位后、是否从 FRAM (FRAM-RAM)恢复 RAM 内容? 或者、如果我只备份与我真正相关的数据、这是否足够? 我是否可以使用(简单)例程来备份整个 RAM?
另一个注意事项:如果我的应用仅使用200字节的 RAM、那么我只能将其存储在 FRAM 中、对吧? 或者在唤醒后以某种方式损坏 RAM 内容。
2.如果我在 CCS 下将带有#pragma PERSISTENT (x)的字符变量/数组存储在 FRAM 中、则这些变量/数组已经存储在 FRAM 中、不再需要保存、对吧? 在从 LPM3.5复位/唤醒后、计数器值不应该被复位?
3.在 CCS 11下、我使用 MSP-FET 进行调试。 到目前为止、这种方法一直很好、但 LPM3.5不能。 这是正常的还是某个位置缺少设置? 不采用 RTC ISR 中的断点。 他们看不到应用程序也会重新启动。 if 语句中用于查询中断矢量状态(决定唤醒或冷启动)的断点也不会被采用。
如果有任何提示或建议、我将不胜感激!
我自己不能再去了...
我将在这里用主例程布置 main.c。
您可能会立即发现错误。
我使用了 CCS 中未经修改的自动生成文件作为链接器文件。
(可能仍需要对此进行调整以使 FRAM 正常工作?)
非常感谢、致以最诚挚的问候
Stefan
#include "msp430.h" #include "stdint.h" #include "SX1278.h" #define FIXED_PACKET_LENGTH (6) #define SENSOR_ID (0x34) // function prototypes void initGpio(void); #pragma PERSISTENT(LoRaPacketCount) unsigned long LoRaPacketCount = 0; #pragma PERSISTENT(SensorNodeID) unsigned char SensorNodeID = SENSOR_ID; #pragma PERSISTENT(LoRa_packet) volatile unsigned char LoRa_packet[FIXED_PACKET_LENGTH] = {0x34, 0xFF, 0xFF, 0x00, 0x00, 0x00}; // payload of the lora packet int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT initGpio(); // Configure GPIO // disabling the SVS (Supply Voltage Supervisor) --> not needed PMMCTL0_H = PMMPW_H; PMMCTL0_L &= ~SVSHE; // First determine whether we are coming out of an LPMx.5 or a regular RESET. if (SYSRSTIV == SYSRSTIV_LPM5WU) // When woken up from LPM3.5, reinit { // If MCU wakes up from LPM3.5, re-init and then return to LPM3.5 again. LoRaPacketCount++; LoRa_packet[0] = SENSOR_ID; // unique SensorNode ID LoRa_packet[1] = 0xFF; // DS1820 temp (LSB) LoRa_packet[2] = 0xFF; // DS1820 temp (MSB) LoRa_packet[3] = (uint8_t)(LoRaPacketCount & 0x000000FF); // 24bit counter (LSB) LoRa_packet[4] = (uint8_t)((LoRaPacketCount & 0x0000FF00) >> 8); // 24bit counter LoRa_packet[5] = (uint8_t)((LoRaPacketCount & 0x00FF0000) >> 16); // 24bit counter (MSB) // send the packet via LoRa Module SX1278_sendData(&LoRa_packet[0]); SX1278_sleep(); __enable_interrupt(); // The RTC interrupt should trigger now... } else { // Device powered up from a cold start. // It configures the device and puts the device into LPM3.5 P2OUT |= BIT0; // NSS high __delay_cycles(75); // Wait for SX1278 to initialize init_SX1278(FIXED_PACKET_LENGTH); // send the packet via LoRa Module SX1278_sendData(&LoRa_packet[0]); SX1278_sleep(); // Configure RTC // Interrupt and reset happen every 1024/10000 * 100 = 10 sec. RTCMOD = 100-1; RTCCTL = RTCSS__VLOCLK | RTCSR |RTCPS__1024; RTCCTL |= RTCIE; } // Enter LPM3.5 mode with interrupts enabled. Note that this operation does // not return. The LPM3.5 will exit through a RESET event, resulting in a // re-start of the code. PMMCTL0_H = PMMPW_H; // Open PMM Registers for write PMMCTL0_L |= PMMREGOFF; // and set PMMREGOFF // It is recommended to turn off the LPM3.5 switch to avoid unnecessary leakage (see user guide page 88) // set LPM5SW = 0 in the PM5CTL0 register PM5CTL0 &= ~LPM5SW; __bis_SR_register(LPM3_bits | GIE); __no_operation(); return 0; } void initGpio(void) { // caution: there are pullup resistors for the I2C funtionality (SDL, SDA) // keep in mind to leave the Port Pins high to reduce current consumption // port configuration will be remaining in low power states P1DIR = 0xFF; P2DIR = 0xFF; P1REN = 0xFF; P2REN = 0xFF; P1OUT = 0xFF; P2OUT = 0xFF; // --- SPI configuration (SX1278 is connected at UCA0) --- // MOSI = P1.4 // MISO = P1.5 // SCLK = P1.6 // CSn = P2.0 (chip enabled is controlled manually by GPIO) P1SEL0 |= BIT4 | BIT5 | BIT6; // set 3-SPI pin as second function UCA0CTLW0 |= UCSWRST; // **Put state machine in reset** UCA0CTLW0 |= UCMST|UCSYNC|UCMSB; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTLW0 |= UCSSEL__SMCLK; // SMCLK UCA0BR0 = 0x02; // SMCLK / 2 = 500kHz, fBitClock = fBRCLK/UCBRx UCA0BR1 = 0; // UCA0MCTLW = 0; // No modulation UCA0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine** // --- end of SPI configuration --- // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; } #pragma vector = RTC_VECTOR __interrupt void RTC_ISR(void) { switch(__even_in_range(RTCIV, RTCIV_RTCIF)) { case RTCIV_NONE : break; // No interrupt pending case RTCIV_RTCIF: // RTC Overflow break; default: break; } }