diff --git a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino index 35644dc..73df14a 100644 --- a/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino +++ b/examples/Peripherals/ADC/Internal_channels/Internal_channels.ino @@ -27,70 +27,82 @@ #endif #if defined(STM32C0xx) -#define VTEMP 760 +#define VTEMP 760 #define AVG_SLOPE 2530 -#define VREFINT 1212 +#define VREFINT 1212 #elif defined(STM32F1xx) -#define VTEMP 1430 +#define VTEMP 1430 #define AVG_SLOPE 4300 -#define VREFINT 1200 +#define VREFINT 1200 #elif defined(STM32F2xx) || defined(STM32F4xx) -#define VTEMP 760 +#define VTEMP 760 #define AVG_SLOPE 2500 -#define VREFINT 1210 +#define VREFINT 1210 #endif /* Analog read resolution */ +#if defined(LL_ADC_RESOLUTION_12B) #define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B +#elif defined(LL_ADC_DS_DATA_WIDTH_12_BIT) +#define LL_ADC_RESOLUTION LL_ADC_DS_DATA_WIDTH_12_BIT +#else +#error "ADC resolution could not be defined!" +#endif #define ADC_RANGE 4096 // the setup routine runs once when you press reset: void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); - while (!Serial); + while (!Serial) + ; analogReadResolution(12); } -static int32_t readVref() -{ +#ifdef AVREF +static uint32_t readVref() { + uint32_t Vref = 3300; #ifdef STM32U0xx /* On some devices Internal voltage reference calibration value not programmed during production and return 0xFFFF. See errata sheet. */ - if ((uint32_t)(*VREFINT_CAL_ADDR) == 0xFFFF) { - return 3300U; - } + if ((uint32_t)(*VREFINT_CAL_ADDR) != 0xFFFF) { #endif #ifdef __LL_ADC_CALC_VREFANALOG_VOLTAGE #ifdef STM32U5xx - return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC1, analogRead(AVREF), LL_ADC_RESOLUTION)); + Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC1, analogRead(AVREF), LL_ADC_RESOLUTION); #else - return (__LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION)); + Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION); #endif #else - return (VREFINT * ADC_RANGE / analogRead(AVREF)); // ADC sample to mV + Vref = VREFINT * ADC_RANGE / analogRead(AVREF); // ADC sample to mV +#endif +#ifdef STM32U0xx + } #endif + return Vref; } +#endif #ifdef ATEMP -static int32_t readTempSensor(int32_t VRef) -{ +static int32_t readTempSensor(int32_t VRef) { + uint32_t temp = 0; #ifdef __LL_ADC_CALC_TEMPERATURE #ifdef STM32U5xx - return (__LL_ADC_CALC_TEMPERATURE(ADC1, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); + temp = __LL_ADC_CALC_TEMPERATURE(ADC1, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); +#elif defined(STM32WB0x) + (void)VRef; + temp = __LL_ADC_CALC_TEMPERATURE(analogRead(ATEMP), LL_ADC_DS_DATA_WIDTH_12_BIT); #else - return (__LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); + temp = __LL_ADC_CALC_TEMPERATURE(VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); #endif #elif defined(__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS) - return (__LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, VTEMP, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION)); -#else - return 0; + temp = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(AVG_SLOPE, VTEMP, CALX_TEMP, VRef, analogRead(ATEMP), LL_ADC_RESOLUTION); #endif + return temp; } #endif -static int32_t readVoltage(int32_t VRef, uint32_t pin) -{ +static int32_t readVoltage(int32_t VRef, uint32_t pin) { #ifdef STM32U5xx return (__LL_ADC_CALC_DATA_TO_VOLTAGE(ADC1, VRef, analogRead(pin), LL_ADC_RESOLUTION)); #else @@ -100,7 +112,7 @@ static int32_t readVoltage(int32_t VRef, uint32_t pin) // The loop routine runs over and over again forever: void loop() { -#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) +#if defined(ICACHE) && defined(HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) bool icache_enabled = false; if (HAL_ICACHE_IsEnabled() == 1) { icache_enabled = true; @@ -110,9 +122,15 @@ void loop() { } } #endif /* ICACHE && HAL_ICACHE_MODULE_ENABLED && !HAL_ICACHE_MODULE_DISABLED */ + // Print out the value read +#ifdef AVREF int32_t VRef = readVref(); Serial.printf("VRef(mv)= %i", VRef); +#else + // No Vref fro STM32WB0xx + int32_t VRef = LL_ADC_VIN_RANGE_3V6; +#endif #ifdef ATEMP Serial.printf("\tTemp(°C)= %i", readTempSensor(VRef)); #endif @@ -121,9 +139,8 @@ void loop() { #endif Serial.printf("\tA0(mv)= %i\n", readVoltage(VRef, A0)); delay(200); -#if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) - if (icache_enabled) - { +#if defined(ICACHE) && defined(HAL_ICACHE_MODULE_ENABLED) && !defined(HAL_ICACHE_MODULE_DISABLED) + if (icache_enabled) { /* Re-enable instruction cache */ if (HAL_ICACHE_Enable() != HAL_OK) { Error_Handler(); diff --git a/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino new file mode 100644 index 0000000..a268188 --- /dev/null +++ b/examples/Peripherals/Registers/Reset_reason/Reset_reason.ino @@ -0,0 +1,99 @@ +/* Last Reset Reason Sketch +* This sketch will determine what caused the last reset on the STM32 MCU. Most microcontrollers +* have a register dedicated to storing the last reason of the chip, weather being from a +* low power condition, software caused brown-out. Test it by resetting the MCU via the USER button +* which triggers the Reset_my_MCU() function or unplug the USB cable and repluggit back. Adjust your +* UART, USER Button pin and registers accordingly. Use the MCU's datasheet and/or stm32yyyxxx.h for reference. +* The code is provided "as is" with no liability. +*/ + +#include "stm32yyxx_ll_rcc.h" +#include "IWatchdog.h" + +#define USER_BTN_PIN USER_BTN // Adjust this for your board + +// Enumerator for combining reset flag bits into one byte then display them +enum reset_reason { + UNKNOWN_RESET = 0, + BROWN_OUT = 1 << 0, + NRST_PIN = 1 << 1, + SOFTWARE_RST = 1 << 2, + INDEPENDENT_WDG = 1 << 3, + WINDOW_WDG = 1 << 4, + LOW_POWER = 1 << 5, + OPTION_BYTE_LOADER = 1 << 6, + POWER_ON_DOWN = 1 << 7 +}; + +reset_reason last_reset_reason = UNKNOWN_RESET; +static int default_button_state = LOW; + +void Reset_My_MCU() { + // There are a few reset conditions. + // Keep the one you wish to use and comment out the others. + // Below is the Software reset condition + // NVIC_SystemReset(); + + // Below is the Watchdog Timer reset condition + IWatchdog.begin(1000); //1ms tick then reset + while (1) + ; // Wait for reset +} + +void setup() { + pinMode(USER_BTN_PIN, INPUT); + default_button_state = digitalRead(USER_BTN_PIN); + Serial.begin(115200); + while (!Serial) + ; // Wait for Serial + +#ifdef RCC_CSR_BORRSTF + if (LL_RCC_IsActiveFlag_BORRST()) last_reset_reason = (reset_reason)(last_reset_reason | BROWN_OUT); +#endif + if (LL_RCC_IsActiveFlag_PINRST()) last_reset_reason = (reset_reason)(last_reset_reason | NRST_PIN); + if (LL_RCC_IsActiveFlag_SFTRST()) last_reset_reason = (reset_reason)(last_reset_reason | SOFTWARE_RST); +#if defined(RCC_RSR_IWDG1RSTF) + if (LL_RCC_IsActiveFlag_IWDG1RST()) last_reset_reason = (reset_reason)(last_reset_reason | INDEPENDENT_WDG); +#else + if (LL_RCC_IsActiveFlag_IWDGRST()) last_reset_reason = (reset_reason)(last_reset_reason | INDEPENDENT_WDG); +#endif +#if defined(RCC_RSR_WWDG1RSTF) + if (LL_RCC_IsActiveFlag_WWDG1RST()) last_reset_reason = (reset_reason)(last_reset_reason | WINDOW_WDG); +#else + if (LL_RCC_IsActiveFlag_WWDGRST()) last_reset_reason = (reset_reason)(last_reset_reason | WINDOW_WDG); +#endif + if (LL_RCC_IsActiveFlag_LPWRRST()) last_reset_reason = (reset_reason)(last_reset_reason | LOW_POWER); +#if defined(RCC_CSR_OBLRSTF) || defined(RCC_CSR2_OBLRSTF) + if (LL_RCC_IsActiveFlag_OBLRST()) last_reset_reason = (reset_reason)(last_reset_reason | OPTION_BYTE_LOADER); +#endif +#ifdef RCC_CSR_PORRSTF + if (LL_RCC_IsActiveFlag_PORRST()) last_reset_reason = (reset_reason)(last_reset_reason | POWER_ON_DOWN); +#endif + + // Clear reset flags + LL_RCC_ClearResetFlags(); +} + +void loop() { + Serial.println("Last reset reason:"); + + if (last_reset_reason & BROWN_OUT) Serial.println(" - Brown-out reset"); + if (last_reset_reason & SOFTWARE_RST) Serial.println(" - Software reset"); + if (last_reset_reason & INDEPENDENT_WDG) Serial.println(" - Independent Watchdog reset"); + if (last_reset_reason & WINDOW_WDG) Serial.println(" - Window Watchdog reset"); + if (last_reset_reason & LOW_POWER) Serial.println(" - Low-power reset"); + if (last_reset_reason & OPTION_BYTE_LOADER) Serial.println(" - Option byte loader reset"); + if (last_reset_reason & NRST_PIN) Serial.println(" - Pin reset (NRST or software)"); //last case so the rest take precedence before issuing NRST + if (last_reset_reason & POWER_ON_DOWN) Serial.println(" - Power on or power down reset"); + if (last_reset_reason == UNKNOWN_RESET) Serial.println(" - Unknown or no flags set"); + last_reset_reason = UNKNOWN_RESET; + + // Trigger software reset on button press + if (digitalRead(USER_BTN_PIN) != default_button_state) { + Serial.println("Button pressed → Triggering reset..."); + delay(300); // Debounce + Reset_My_MCU(); + } + + delay(1000); +} diff --git a/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino b/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino new file mode 100644 index 0000000..605502a --- /dev/null +++ b/examples/Peripherals/Registers/UID_Retrieve/UID_Retrieve.ino @@ -0,0 +1,53 @@ +/* UID Retrieve sketch +* UID (Universal Identifier) is a ID that's etched to each MCU at factory release +* so it's uniquely identifiable. This can help traceability and addressing devices +* without having to craft a database yourself. This sketch retrieves UID, MAC, Device +* and Revision ID of each MCU. Refer to the relevant datasheet to know where are these +* values are stored in the registers. +* The code is provided "as is" with no liability. +*/ + +void setup() { + Serial.begin(115200); + while (!Serial) + ; // Wait for Serial to be ready + + Serial.printf("%s Device Identifiers:\n", BOARD_NAME); + + // Unique Device ID (96 bits / 12 bytes) + uint32_t uid0 = HAL_GetUIDw0(); + uint32_t uid1 = HAL_GetUIDw1(); + uint32_t uid2 = HAL_GetUIDw2(); + + Serial.print("UID: "); + Serial.print(uid2, HEX); + Serial.print("-"); + Serial.print(uid1, HEX); + Serial.print("-"); + Serial.println(uid0, HEX); + + // MAC Address: typically stored in UID for STM32U series + // Use the lower 6 bytes of the 96-bit UID (commonly used) + uint8_t mac[6] = { + (uint8_t)(uid0 >> 0), + (uint8_t)(uid0 >> 8), + (uint8_t)(uid0 >> 16), + (uint8_t)(uid1 >> 0), + (uint8_t)(uid1 >> 8), + (uint8_t)(uid1 >> 16) + }; + + Serial.print("MAC Address: "); + for (int i = 0; i < 6; i++) { + if (mac[i] < 0x10) Serial.print("0"); + Serial.print(mac[i], HEX); + if (i < 5) Serial.print(":"); + } + Serial.println(); + Serial.printf("Device ID: 0x%x\n", HAL_GetDEVID()); + Serial.printf("Revision ID: 0x%x\n", HAL_GetREVID()); +} + +void loop() { + // Nothing here +} diff --git a/library.properties b/library.properties index a70baf0..8d175d9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino Examples -version=1.2.5 +version=1.2.6 author=several maintainer=stm32duino sentence=Provides several examples for the Arduino core for STM32 MCUs.