Read IMD M pin
This commit is contained in:
parent
554eecfc94
commit
12422071a5
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef INC_IMD_MONITORING_H
|
||||||
|
#define INC_IMD_MONITORING_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "stm32f3xx_hal.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IMD_STATE_UNKNOWN,
|
||||||
|
IMD_STATE_SHORTCIRCUIT_SUPPLY,
|
||||||
|
IMD_STATE_SHORTCIRCUIT_GND,
|
||||||
|
IMD_STATE_NORMAL,
|
||||||
|
IMD_STATE_UNDERVOLTAGE,
|
||||||
|
IMD_STATE_SST,
|
||||||
|
IMD_STATE_DEV_ERROR,
|
||||||
|
IMD_STATE_GND_FAULT,
|
||||||
|
} IMDState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
IMDState state;
|
||||||
|
uint32_t r_iso;
|
||||||
|
|
||||||
|
uint32_t freq;
|
||||||
|
uint32_t duty_cycle;
|
||||||
|
uint32_t last_high;
|
||||||
|
} IMDData;
|
||||||
|
|
||||||
|
extern IMDData imd_data;
|
||||||
|
|
||||||
|
void imd_init(TIM_HandleTypeDef *htim);
|
||||||
|
|
||||||
|
void imd_update(void);
|
||||||
|
|
||||||
|
#endif // INC_IMD_MONITORING_H
|
|
@ -61,6 +61,8 @@ void Error_Handler(void);
|
||||||
#define HV_MISMATCH_ERR_GPIO_Port GPIOA
|
#define HV_MISMATCH_ERR_GPIO_Port GPIOA
|
||||||
#define RELAY_MISMATCH_ERR_Pin GPIO_PIN_1
|
#define RELAY_MISMATCH_ERR_Pin GPIO_PIN_1
|
||||||
#define RELAY_MISMATCH_ERR_GPIO_Port GPIOA
|
#define RELAY_MISMATCH_ERR_GPIO_Port GPIOA
|
||||||
|
#define IMD_M_Pin GPIO_PIN_2
|
||||||
|
#define IMD_M_GPIO_Port GPIOA
|
||||||
#define IMD_OK_Pin GPIO_PIN_3
|
#define IMD_OK_Pin GPIO_PIN_3
|
||||||
#define IMD_OK_GPIO_Port GPIOA
|
#define IMD_OK_GPIO_Port GPIOA
|
||||||
#define RELAY_CONNECTION_ERR_Pin GPIO_PIN_4
|
#define RELAY_CONNECTION_ERR_Pin GPIO_PIN_4
|
||||||
|
|
|
@ -56,6 +56,7 @@ void DebugMon_Handler(void);
|
||||||
void PendSV_Handler(void);
|
void PendSV_Handler(void);
|
||||||
void SysTick_Handler(void);
|
void SysTick_Handler(void);
|
||||||
void USB_LP_CAN_RX0_IRQHandler(void);
|
void USB_LP_CAN_RX0_IRQHandler(void);
|
||||||
|
void TIM1_BRK_TIM15_IRQHandler(void);
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
/* USER CODE END EFP */
|
/* USER CODE END EFP */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
|
|
||||||
|
#include "imd_monitoring.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "shunt_monitoring.h"
|
#include "shunt_monitoring.h"
|
||||||
#include "slave_monitoring.h"
|
#include "slave_monitoring.h"
|
||||||
|
@ -21,11 +22,17 @@ void can_init(CAN_HandleTypeDef *handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HAL_StatusTypeDef can_send_status() {
|
HAL_StatusTypeDef can_send_status() {
|
||||||
uint8_t data[6];
|
uint8_t data[8];
|
||||||
data[0] = ts_state.current_state | (sdc_closed << 7);
|
data[0] = ts_state.current_state | (sdc_closed << 7);
|
||||||
data[1] = roundf(current_soc);
|
data[1] = roundf(current_soc);
|
||||||
ftcan_marshal_unsigned(&data[2], min_voltage, 2);
|
ftcan_marshal_unsigned(&data[2], min_voltage, 2);
|
||||||
ftcan_marshal_signed(&data[4], max_temp, 2);
|
ftcan_marshal_signed(&data[4], max_temp, 2);
|
||||||
|
data[6] = imd_data.state | (imd_data.ok << 7);
|
||||||
|
if (imd_data.r_iso < 0xFFF) {
|
||||||
|
data[7] = imd_data.r_iso >> 4;
|
||||||
|
} else {
|
||||||
|
data[7] = 0xFF;
|
||||||
|
}
|
||||||
return ftcan_transmit(CAN_ID_AMS_STATUS, data, sizeof(data));
|
return ftcan_transmit(CAN_ID_AMS_STATUS, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include "imd_monitoring.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#define FREQ_TIMER 1000 // Hz
|
||||||
|
|
||||||
|
#define FREQ_TOLERANCE 1 // Hz
|
||||||
|
#define FREQ_NORMAL 10 // Hz
|
||||||
|
#define FREQ_UNDERVOLTAGE 20 // Hz
|
||||||
|
#define FREQ_SST 30 // Hz
|
||||||
|
#define FREQ_DEV_ERROR 40 // Hz
|
||||||
|
#define FREQ_GND_FAULT 50 // Hz
|
||||||
|
|
||||||
|
#define RISO_MIN_DUTY_CYCLE 8 // %
|
||||||
|
#define RISO_MAX 50000 // kOhm
|
||||||
|
|
||||||
|
#define PWM_TIMEOUT 200 // ms
|
||||||
|
|
||||||
|
IMDData imd_data;
|
||||||
|
|
||||||
|
static TIM_HandleTypeDef *htim;
|
||||||
|
|
||||||
|
void imd_init(TIM_HandleTypeDef *handle) {
|
||||||
|
htim = handle;
|
||||||
|
HAL_TIM_IC_Start_IT(htim, TIM_CHANNEL_1);
|
||||||
|
HAL_TIM_IC_Start(htim, TIM_CHANNEL_2);
|
||||||
|
|
||||||
|
imd_data.state = IMD_STATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *handle) {
|
||||||
|
if (handle != htim || htim->Channel != HAL_TIM_ACTIVE_CHANNEL_1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t period = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
|
||||||
|
if (period == 0) {
|
||||||
|
// First edge, ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
imd_data.last_high = HAL_GetTick();
|
||||||
|
|
||||||
|
imd_data.freq = FREQ_TIMER / period;
|
||||||
|
uint32_t high_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
|
||||||
|
imd_data.duty_cycle = (100 * high_time) / period;
|
||||||
|
|
||||||
|
// Check PWM frequency for state determination
|
||||||
|
if (imd_data.freq > FREQ_NORMAL - FREQ_TOLERANCE &&
|
||||||
|
imd_data.freq < FREQ_NORMAL + FREQ_TOLERANCE) {
|
||||||
|
imd_data.state = IMD_STATE_NORMAL;
|
||||||
|
} else if (imd_data.freq > FREQ_UNDERVOLTAGE - FREQ_TOLERANCE &&
|
||||||
|
imd_data.freq < FREQ_UNDERVOLTAGE + FREQ_TOLERANCE) {
|
||||||
|
imd_data.state = IMD_STATE_UNDERVOLTAGE;
|
||||||
|
} else if (imd_data.freq > FREQ_SST - FREQ_TOLERANCE &&
|
||||||
|
imd_data.freq < FREQ_SST + FREQ_TOLERANCE) {
|
||||||
|
imd_data.state = IMD_STATE_SST;
|
||||||
|
} else if (imd_data.freq > FREQ_DEV_ERROR - FREQ_TOLERANCE &&
|
||||||
|
imd_data.freq < FREQ_DEV_ERROR + FREQ_TOLERANCE) {
|
||||||
|
imd_data.state = IMD_STATE_DEV_ERROR;
|
||||||
|
} else if (imd_data.freq > FREQ_GND_FAULT - FREQ_TOLERANCE &&
|
||||||
|
imd_data.freq < FREQ_GND_FAULT + FREQ_TOLERANCE) {
|
||||||
|
imd_data.state = IMD_STATE_GND_FAULT;
|
||||||
|
} else {
|
||||||
|
imd_data.state = IMD_STATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate R_iso
|
||||||
|
if (imd_data.state == IMD_STATE_NORMAL ||
|
||||||
|
imd_data.state == IMD_STATE_UNDERVOLTAGE) {
|
||||||
|
if (imd_data.duty_cycle < RISO_MIN_DUTY_CYCLE) {
|
||||||
|
imd_data.r_iso = RISO_MAX;
|
||||||
|
} else {
|
||||||
|
imd_data.r_iso = (90 * 1200) / (imd_data.duty_cycle - 5) - 1200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void imd_update() {
|
||||||
|
imd_data.ok = HAL_GPIO_ReadPin(IMD_OK_GPIO_Port, IMD_OK_Pin);
|
||||||
|
if (HAL_GetTick() - imd_data.last_high > PWM_TIMEOUT) {
|
||||||
|
if (HAL_GPIO_ReadPin(IMD_M_GPIO_Port, IMD_M_Pin) == GPIO_PIN_SET) {
|
||||||
|
imd_data.state = IMD_STATE_SHORTCIRCUIT_SUPPLY;
|
||||||
|
} else {
|
||||||
|
imd_data.state = IMD_STATE_SHORTCIRCUIT_GND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,14 +22,15 @@
|
||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN Includes */
|
/* USER CODE BEGIN Includes */
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
#include "soc_estimation.h"
|
#include "imd_monitoring.h"
|
||||||
#include "stm32f3xx_hal.h"
|
|
||||||
#include "stm32f3xx_hal_gpio.h"
|
|
||||||
|
|
||||||
#include "shunt_monitoring.h"
|
#include "shunt_monitoring.h"
|
||||||
#include "slave_monitoring.h"
|
#include "slave_monitoring.h"
|
||||||
|
#include "soc_estimation.h"
|
||||||
#include "ts_state_machine.h"
|
#include "ts_state_machine.h"
|
||||||
|
|
||||||
|
#include "stm32f3xx_hal.h"
|
||||||
|
#include "stm32f3xx_hal_gpio.h"
|
||||||
|
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
@ -130,6 +131,7 @@ int main(void) {
|
||||||
shunt_init();
|
shunt_init();
|
||||||
ts_sm_init();
|
ts_sm_init();
|
||||||
soc_init();
|
soc_init();
|
||||||
|
imd_init(&htim15);
|
||||||
HAL_GPIO_WritePin(AMS_NERROR_GPIO_Port, AMS_NERROR_Pin, GPIO_PIN_SET);
|
HAL_GPIO_WritePin(AMS_NERROR_GPIO_Port, AMS_NERROR_Pin, GPIO_PIN_SET);
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
|
@ -147,6 +149,7 @@ int main(void) {
|
||||||
shunt_check();
|
shunt_check();
|
||||||
ts_sm_update();
|
ts_sm_update();
|
||||||
soc_update();
|
soc_update();
|
||||||
|
imd_update();
|
||||||
can_send_status();
|
can_send_status();
|
||||||
|
|
||||||
loop_delay();
|
loop_delay();
|
||||||
|
@ -349,7 +352,7 @@ static void MX_TIM15_Init(void) {
|
||||||
|
|
||||||
/* USER CODE END TIM15_Init 1 */
|
/* USER CODE END TIM15_Init 1 */
|
||||||
htim15.Instance = TIM15;
|
htim15.Instance = TIM15;
|
||||||
htim15.Init.Prescaler = 0;
|
htim15.Init.Prescaler = 16000 - 1;
|
||||||
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
|
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||||
htim15.Init.Period = 65535;
|
htim15.Init.Period = 65535;
|
||||||
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
|
|
|
@ -303,13 +303,16 @@ void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* htim_ic)
|
||||||
/**TIM15 GPIO Configuration
|
/**TIM15 GPIO Configuration
|
||||||
PA2 ------> TIM15_CH1
|
PA2 ------> TIM15_CH1
|
||||||
*/
|
*/
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_2;
|
GPIO_InitStruct.Pin = IMD_M_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF9_TIM15;
|
GPIO_InitStruct.Alternate = GPIO_AF9_TIM15;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(IMD_M_GPIO_Port, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
/* TIM15 interrupt Init */
|
||||||
|
HAL_NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 0, 0);
|
||||||
|
HAL_NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);
|
||||||
/* USER CODE BEGIN TIM15_MspInit 1 */
|
/* USER CODE BEGIN TIM15_MspInit 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM15_MspInit 1 */
|
/* USER CODE END TIM15_MspInit 1 */
|
||||||
|
@ -336,8 +339,10 @@ void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef* htim_ic)
|
||||||
/**TIM15 GPIO Configuration
|
/**TIM15 GPIO Configuration
|
||||||
PA2 ------> TIM15_CH1
|
PA2 ------> TIM15_CH1
|
||||||
*/
|
*/
|
||||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2);
|
HAL_GPIO_DeInit(IMD_M_GPIO_Port, IMD_M_Pin);
|
||||||
|
|
||||||
|
/* TIM15 interrupt DeInit */
|
||||||
|
HAL_NVIC_DisableIRQ(TIM1_BRK_TIM15_IRQn);
|
||||||
/* USER CODE BEGIN TIM15_MspDeInit 1 */
|
/* USER CODE BEGIN TIM15_MspDeInit 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM15_MspDeInit 1 */
|
/* USER CODE END TIM15_MspDeInit 1 */
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
|
|
||||||
/* External variables --------------------------------------------------------*/
|
/* External variables --------------------------------------------------------*/
|
||||||
extern CAN_HandleTypeDef hcan;
|
extern CAN_HandleTypeDef hcan;
|
||||||
|
extern TIM_HandleTypeDef htim15;
|
||||||
/* USER CODE BEGIN EV */
|
/* USER CODE BEGIN EV */
|
||||||
|
|
||||||
/* USER CODE END EV */
|
/* USER CODE END EV */
|
||||||
|
@ -217,6 +218,20 @@ void USB_LP_CAN_RX0_IRQHandler(void)
|
||||||
/* USER CODE END USB_LP_CAN_RX0_IRQn 1 */
|
/* USER CODE END USB_LP_CAN_RX0_IRQn 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function handles TIM1 break and TIM15 interrupts.
|
||||||
|
*/
|
||||||
|
void TIM1_BRK_TIM15_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* USER CODE BEGIN TIM1_BRK_TIM15_IRQn 0 */
|
||||||
|
|
||||||
|
/* USER CODE END TIM1_BRK_TIM15_IRQn 0 */
|
||||||
|
HAL_TIM_IRQHandler(&htim15);
|
||||||
|
/* USER CODE BEGIN TIM1_BRK_TIM15_IRQn 1 */
|
||||||
|
|
||||||
|
/* USER CODE END TIM1_BRK_TIM15_IRQn 1 */
|
||||||
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN 1 */
|
/* USER CODE BEGIN 1 */
|
||||||
|
|
||||||
/* USER CODE END 1 */
|
/* USER CODE END 1 */
|
||||||
|
|
|
@ -38,6 +38,7 @@ BUILD_DIR = build
|
||||||
C_SOURCES = \
|
C_SOURCES = \
|
||||||
Core/Lib/can-halal/can-halal.c \
|
Core/Lib/can-halal/can-halal.c \
|
||||||
Core/Src/can.c \
|
Core/Src/can.c \
|
||||||
|
Core/Src/imd_monitoring.c \
|
||||||
Core/Src/main.c \
|
Core/Src/main.c \
|
||||||
Core/Src/shunt_monitoring.c \
|
Core/Src/shunt_monitoring.c \
|
||||||
Core/Src/slave_monitoring.c \
|
Core/Src/slave_monitoring.c \
|
||||||
|
|
|
@ -86,6 +86,7 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
|
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
|
||||||
|
NVIC.TIM1_BRK_TIM15_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||||
NVIC.USB_LP_CAN_RX0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
NVIC.USB_LP_CAN_RX0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
PA0.GPIOParameters=GPIO_Label
|
PA0.GPIOParameters=GPIO_Label
|
||||||
|
@ -113,6 +114,8 @@ PA14.Mode=Trace_Asynchronous_SW
|
||||||
PA14.Signal=SYS_JTCK-SWCLK
|
PA14.Signal=SYS_JTCK-SWCLK
|
||||||
PA15.Mode=I2C
|
PA15.Mode=I2C
|
||||||
PA15.Signal=I2C1_SCL
|
PA15.Signal=I2C1_SCL
|
||||||
|
PA2.GPIOParameters=GPIO_Label
|
||||||
|
PA2.GPIO_Label=IMD_M
|
||||||
PA2.Locked=true
|
PA2.Locked=true
|
||||||
PA2.Signal=S_TIM15_CH1
|
PA2.Signal=S_TIM15_CH1
|
||||||
PA3.GPIOParameters=GPIO_Label
|
PA3.GPIOParameters=GPIO_Label
|
||||||
|
@ -237,7 +240,7 @@ ProjectManager.StackSize=0x400
|
||||||
ProjectManager.TargetToolchain=Makefile
|
ProjectManager.TargetToolchain=Makefile
|
||||||
ProjectManager.ToolChainLocation=
|
ProjectManager.ToolChainLocation=
|
||||||
ProjectManager.UnderRoot=false
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC2_Init-ADC2-false-HAL-true,4-MX_CAN_Init-CAN-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true
|
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC2_Init-ADC2-false-HAL-true,4-MX_CAN_Init-CAN-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true,6-MX_I2C1_Init-I2C1-false-HAL-true,7-MX_TIM15_Init-TIM15-false-HAL-true
|
||||||
RCC.ADC12outputFreq_Value=16000000
|
RCC.ADC12outputFreq_Value=16000000
|
||||||
RCC.AHBFreq_Value=16000000
|
RCC.AHBFreq_Value=16000000
|
||||||
RCC.APB1Freq_Value=16000000
|
RCC.APB1Freq_Value=16000000
|
||||||
|
@ -274,6 +277,8 @@ RCC.USBFreq_Value=16000000
|
||||||
RCC.VCOOutput2Freq_Value=4000000
|
RCC.VCOOutput2Freq_Value=4000000
|
||||||
SH.S_TIM15_CH1.0=TIM15_CH1,PWM_Input_1
|
SH.S_TIM15_CH1.0=TIM15_CH1,PWM_Input_1
|
||||||
SH.S_TIM15_CH1.ConfNb=1
|
SH.S_TIM15_CH1.ConfNb=1
|
||||||
|
TIM15.IPParameters=Prescaler
|
||||||
|
TIM15.Prescaler=16000-1
|
||||||
USART1.IPParameters=VirtualMode-Asynchronous
|
USART1.IPParameters=VirtualMode-Asynchronous
|
||||||
USART1.VirtualMode-Asynchronous=VM_ASYNC
|
USART1.VirtualMode-Asynchronous=VM_ASYNC
|
||||||
VP_SYS_VS_Systick.Mode=SysTick
|
VP_SYS_VS_Systick.Mode=SysTick
|
||||||
|
|
Loading…
Reference in New Issue