最近、天気が暑くて、「外の気温、何度かな?」と思う時が多くなりました。
そこで、外の気温を測って、室内に表示する「無線温度計」を自分で作ってみました。
STM32F103C8T6の開発ボードを使いましたが、一番の問題は、
「マイクロコントローラーをスリープ状態にする」ことです。
色々試してみました。
このstm32sleepというライブラリーも使ってみましたが、
どうもうまく行けませんでした。
そのライブラリーのもとをみて、更に探し、
tomtorさんのコードを見つかりました。
このコードの関数を使って、何とかできました!
使い方は簡単です。
Arduinoコードのloop()の一番最後のところに、
mdelay(1000);
を追加するだけで、1000ミリ秒をスリープさせます。
あ、Arduino IDEに使えるSTM32 Coreが必要ですけどね。
使っているのが、rogerclarkmelbourneさんのArduino_STM32です。
ちなみに、STMicroelectronics社の正式なものもあります。
ここから、tomtorさんのコードの抜粋です。
そこで、外の気温を測って、室内に表示する「無線温度計」を自分で作ってみました。
STM32F103C8T6の開発ボードを使いましたが、一番の問題は、
「マイクロコントローラーをスリープ状態にする」ことです。
色々試してみました。
このstm32sleepというライブラリーも使ってみましたが、
どうもうまく行けませんでした。
そのライブラリーのもとをみて、更に探し、
tomtorさんのコードを見つかりました。
このコードの関数を使って、何とかできました!
使い方は簡単です。
Arduinoコードのloop()の一番最後のところに、
mdelay(1000);
を追加するだけで、1000ミリ秒をスリープさせます。
あ、Arduino IDEに使えるSTM32 Coreが必要ですけどね。
使っているのが、rogerclarkmelbourneさんのArduino_STM32です。
ちなみに、STMicroelectronics社の正式なものもあります。
#include <libmaple/pwr.h> #include <libmaple/scb.h> #include <RTClock.h> // Define the Base address of the RTC registers (battery backed up CMOS Ram), so we can use them for config of touch screen or whatever. // See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam // 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device. #define BKP_REG_BASE ((uint32_t *)(0x40006C00 + 0x04)) RTClock rt(RTCSEL_LSI, 39); // 1 milli second alarm void storeBR(int i, uint32_t v) { BKP_REG_BASE[2*i]= (v << 16); BKP_REG_BASE[2*i+1]= (v & 0xFFFF); } uint32_t readBR(int i) { return ((BKP_REG_BASE[2*i] & 0xFFFF) >> 16) | (BKP_REG_BASE[2*i+1] & 0xFFFF); } void sleepMode(bool deepSleepFlag) { // Clear PDDS and LPDS bits PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS | PWR_CR_CWUF; // Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet): PWR_BASE->CR |= PWR_CR_CWUF; // Enable wakeup pin bit. PWR_BASE->CR |= PWR_CSR_EWUP; SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP; // System Control Register Bits. See... // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Cihhjgdh.html if (deepSleepFlag) { // Set Power down deepsleep bit. PWR_BASE->CR |= PWR_CR_PDDS; // Unset Low-power deepsleep. PWR_BASE->CR &= ~PWR_CR_LPDS; } else { adc_disable(ADC1); adc_disable(ADC2); #if STM32_HAVE_DAC dac_disable_channel(DAC, 1); dac_disable_channel(DAC, 2); #endif // Unset Power down deepsleep bit. PWR_BASE->CR &= ~PWR_CR_PDDS; // set Low-power deepsleep. PWR_BASE->CR |= PWR_CR_LPDS; } // Now go into stop mode, wake up on interrupt asm(" wfi"); // Clear SLEEPDEEP bit so we can use SLEEP mode SCB_BASE->SCR &= ~SCB_SCR_SLEEPDEEP; } uint32 sleepTime; void AlarmFunction () { // We always wake up with the 8Mhz HSI clock! // So adjust the clock if needed... #if F_CPU == 8000000UL // nothing to do, using about 12 mA #elif F_CPU == 16000000UL rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_2); #elif F_CPU == 48000000UL rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_6); #elif F_CPU == 72000000UL rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_9); // 72MHz => 48 mA -- datasheet value => between 40 and 41mA #else #error "Unknown F_CPU!?" #endif extern volatile uint32 systick_uptime_millis; systick_uptime_millis+= sleepTime; } void mdelay(int n, bool mode= false) { sleepTime= n; time_t nextAlarm = (rt.getTime() + n); // Calculate from time now. rt.createAlarm(&AlarmFunction, nextAlarm); sleepMode(mode); } #define RCC_CFGR_HPRE_DIV1 0x00000000U #define RCC_CFGR_HPRE_DIV2 0x00000080U #define RCC_CFGR_HPRE_DIV4 0x00000090U #define RCC_CFGR_HPRE_DIV8 0x000000A0U #define RCC_CFGR_HPRE_DIV16 0x000000B0U #define RCC_CFGR_HPRE_DIV64 0x000000C0U #define RCC_CFGR_HPRE_DIV128 0x000000D0U #define RCC_CFGR_HPRE_DIV256 0x000000E0U #define RCC_CFGR_HPRE_DIV512 0x000000F0U void msleep(uint32_t ms) { uint32_t start= rt.getTime(); while (rt.getTime() - start < ms) { asm(" wfi"); } }