主题中讨论的其他器件: 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;
}
}