'2020/01'에 해당되는 글 3건

  1. 2020.01.16 STM32 PID 제어
  2. 2020.01.08 STM32H750 ReadProtection, BrownOutReset 설정
  3. 2020.01.06 STM32H750 내부 온도 센서 값 읽기
2020. 1. 16. 19:58

 

ADC로 전류값을 읽어온 후 180mA로 타겟값을 맞췄습니다. (미제어시 125mA ~ 170mA 정도 소요)

=> arm에서 제공하는 arm_cortexMxxx_math.lib를 사용

 

 

#define TAGET_ADC 1000

 

void PID_ADC(uint8_t *chpADC, uint8_t chSize)
{
Get_RAWADC(s_chpBuf[s_ADCpointer++]);
PID_CurrentControl(Average(s_chpBuf, ADCCNT, 1), TAGET_ADC);

if(s_ADCpointer >= ADCCNT){
s_ADCpointer = 0;
}
}

 

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void Display(void)
{
DEBUGPRINT("ADC_Volt %d, %fV, ", Average(s_chpBuf, ADCCNT, 0), Voltage_Calc(Average(s_chpBuf, ADCCNT, 0)));
DEBUGPRINT("ADC_Curr %d, %fA, ", Average(s_chpBuf, ADCCNT, 1), Current_Calc(Average(s_chpBuf, ADCCNT, 1)));
DEBUGPRINT("ADC_Temp %d, %d \r\n", Average(s_chpBuf, ADCCNT, 2), __LL_ADC_CALC_TEMPERATURE(3300, Average(s_chpBuf, ADCCNT, 2), LL_ADC_RESOLUTION));
}

 

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void Set_DutyCycle(uint32_t D)
{
  uint32_t P;    /* Pulse duration */

if(D == 0){
LL_TIM_OC_SetCompareCH1(TIM1, PWMRANGE);
}
else{
P = PWMRANGE - D;
LL_TIM_OC_SetCompareCH1(TIM1, P);
}
}

 


/* Includes ------------------------------------------------------------------*/
#include "usr_pid.h"
#include "usr_usart.h"
#include "usr_timer.h"
#include "usr_system.h"

/* Private variables ---------------------------------------------------------*/
arm_pid_instance_f32 PID_Current;

/* Current */
#define PID_PARAM_KP 100         /* Proporcional */
#define PID_PARAM_KI 0.2        /* Integral */
#define PID_PARAM_KD 10            /* Derivative */

/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

 


/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void Config_PID(void)
{
/* Set this for your needs */
PID_Current.Kp = PID_PARAM_KP;        /* Proporcional */
PID_Current.Ki = PID_PARAM_KI;        /* Integral */
PID_Current.Kd = PID_PARAM_KD;        /* Derivative */
/* Initialize PID system, float32_t format */
arm_pid_init_f32(&PID_Current, 1);
}


/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void PID_CurrentControl(float a_fCurr, float a_fTargetCurr)
{
float pid_error = 0;
/* Duty cycle for PWM */
float duty = 0;

/* Calculate error */
pid_error = a_fTargetCurr - a_fCurr; 

/* Calculate PID here, argument is error */
/* Output data will be returned, we will use it as duty cycle parameter */
duty = arm_pid_f32(&PID_Current, pid_error);

Set_DutyCycle(duty);
}

 

 
Posted by 초보 HW 엔지니어 로망와니

댓글을 달아 주세요

2020. 1. 8. 11:40

ReadProtection은 설정하고 나면 옵션을 지우고 플래쉬가 삭제되어야만 사용할 수 있으니 주의가 필요합니다.

 

 

#define BORLEVEL OB_BOR_LEVEL1
#define RDPLEVEL OB_RDP_LEVEL_1
#define BOR_FLAG_TIMEOUT 3000

 

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void Config_BOR(void)
{
uint32_t BORTimeout = BOR_FLAG_TIMEOUT; 

FLASH_OBProgramInitTypeDef FLASH_Handle; 

/* Get FLASH_WRP_SECTORS write protection status */
FLASH_Handle.Banks     = FLASH_BANK_1;
HAL_FLASHEx_OBGetConfig(&FLASH_Handle);
DEBUGPRINT("USERConfig %X\r\n", FLASH_Handle.USERConfig); 
DEBUGPRINT("FLASH_Handle.BORLevel %X\r\n", FLASH_Handle.BORLevel); 

if(Get_BORConfig() != BORLEVEL){ 
FLASH_Handle.OptionType = OPTIONBYTE_BOR;
FLASH_Handle.BORLevel = BORLEVEL; 
while (HAL_FLASH_Unlock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_Unlock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_Unlock\r\n"); 

BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Unlock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_OB_Unlock Fail\r\n");break;}

DEBUGPRINT("USERConfig %X\r\n", FLASH_Handle.USERConfig); 
DEBUGPRINT("FLASH_Handle.BORLevel %X\r\n", FLASH_Handle.BORLevel); 
BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASHEx_OBProgram(&FLASH_Handle) != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASHEx_OBProgram Fail\r\n");break;}
DEBUGPRINT("HAL_FLASHEx_OBProgram\r\n"); 

    /* Launch Option bytes loading */
BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Launch() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASHEx_OBProgram Fail\r\n");break;}
DEBUGPRINT("HAL_FLASHEx_OBProgram\r\n"); 
}        
/*
as the  CPU is executing from the Flash Bank1, and the I-Cache is enabled :
Instruction cache must be invalidated after bank switching to ensure that
CPU will fetch correct instructions from the flash.
*/
SCB_InvalidateICache();


BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Lock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_OB_Lock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_OB_Lock\r\n"); 

BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_Lock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_Lock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_Lock\r\n"); 
}
}
}

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
void Config_RDP(void)
{
uint32_t BORTimeout = BOR_FLAG_TIMEOUT; 

FLASH_OBProgramInitTypeDef FLASH_Handle; 

/* Get FLASH_WRP_SECTORS write protection status */
FLASH_Handle.Banks     = FLASH_BANK_1;
HAL_FLASHEx_OBGetConfig(&FLASH_Handle);
DEBUGPRINT("USERConfig %X\r\n", FLASH_Handle.USERConfig); 
DEBUGPRINT("FLASH_Handle.RDPLevel %X \r\n", FLASH_Handle.RDPLevel);       

if(Get_RDPConfig() != RDPLEVEL){ 
FLASH_Handle.OptionType = OPTIONBYTE_RDP; 
FLASH_Handle.RDPLevel = RDPLEVEL; 
while (HAL_FLASH_Unlock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_Unlock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_Unlock\r\n"); 

BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Unlock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_OB_Unlock Fail\r\n");break;}

DEBUGPRINT("USERConfig %X\r\n", FLASH_Handle.USERConfig); 
DEBUGPRINT("FLASH_Handle.RDPLevel %X \r\n", FLASH_Handle.RDPLevel); 
BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASHEx_OBProgram(&FLASH_Handle) != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASHEx_OBProgram Fail\r\n");break;}
DEBUGPRINT("HAL_FLASHEx_OBProgram\r\n"); 

    /* Launch Option bytes loading */
BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Launch() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASHEx_OBProgram Fail\r\n");break;}
DEBUGPRINT("HAL_FLASHEx_OBProgram\r\n"); 
}        
/*
as the  CPU is executing from the Flash Bank1, and the I-Cache is enabled :
Instruction cache must be invalidated after bank switching to ensure that
CPU will fetch correct instructions from the flash.
*/
SCB_InvalidateICache();


BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_OB_Lock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_OB_Lock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_OB_Lock\r\n"); 

BORTimeout = BOR_FLAG_TIMEOUT; 
while (HAL_FLASH_Lock() != HAL_OK){ 
if((BORTimeout--) == 0){DEBUGPRINT("HAL_FLASH_Lock Fail\r\n");break;}
DEBUGPRINT("HAL_FLASH_Lock\r\n"); 
}
}
}


/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
uint32_t Get_USRConfig(void) 
{
FLASH_OBProgramInitTypeDef FLASH_Handle;

FLASH_Handle.Banks     = FLASH_BANK_1;
/* Read option bytes */
HAL_FLASHEx_OBGetConfig(&FLASH_Handle);

return (FLASH_Handle.USERConfig);
}

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
uint32_t Get_BORConfig(void)
{
FLASH_OBProgramInitTypeDef FLASH_Handle;

FLASH_Handle.Banks     = FLASH_BANK_1;
/* Read option bytes */
HAL_FLASHEx_OBGetConfig(&FLASH_Handle);

return (FLASH_Handle.BORLevel);
}

/*******************************************************************************
* Function Name : 
* Parameters    : None
* Return        : None
* Description   : 
*******************************************************************************/
uint32_t Get_RDPConfig(void)
{
FLASH_OBProgramInitTypeDef FLASH_Handle;

FLASH_Handle.Banks     = FLASH_BANK_1;
/* Read option bytes */
HAL_FLASHEx_OBGetConfig(&FLASH_Handle);

return (FLASH_Handle.RDPLevel);

}

 

 

Posted by 초보 HW 엔지니어 로망와니

댓글을 달아 주세요

2020. 1. 6. 23:23

ADC1을 설정하고 ADC를 읽어오다가 내부 온도 센서나 BAT 값을 읽어보려고 설정을 하였지만 값을 제대로 읽어오지 못하였습니다. 왜 안될까 고민하다가 데이터 시트를 펼쳤습니다.

 

!!!???

In addition, there are 5 internal dedicated channels
– The internal reference voltage (VREFINT), connected to ADC3
– The internal temperature sensor (VSENSE), connected to ADC3
– The VBAT monitoring channel (VBAT/4), connected to ADC3

The ADCs are connected to 5 internal analog inputs:
– the internal temperature sensor (VSENSE) is connected to ADC3 VINP/VINN[18]
– the internal reference voltage (VREFINT) is connected to ADC3 VINP/VINN[19]
– the VBAT monitoring channel (VBAT/4) is connected to ADC3 VINP/VINN[17] 

 

ADC3에서 사용가능하네요.(항상 느끼는 거지만 게으름이 사람을 힘들게 할 때가 많네요. 하지만 사람은 망각의 동물이라고 내일되면 다시 잊어버리고 새롭게 삽질을 시작할 것 입니다. 나는 닭이니까...)

 

 

값 확인

DEBUGPRINT("%d\r\n", Get_InternalTemperture());

 

 

온도값 읽어오기

#define VDDA_APPLI                       ((uint32_t)3300)

 

int32_t Get_InternalTemperture(void)
{
int32_t RAW_Temp;

HAL_ADC_PollForConversion(&AdcHandle3, 1000);
RAW_Temp = HAL_ADC_GetValue(&AdcHandle3);
return __HAL_ADC_CALC_TEMPERATURE(VDDA_APPLI, RAW_Temp, LL_ADC_RESOLUTION_16B);
}

 

 

ADC3 설정

void ADC3_Init(void)

{

/* ADC Periph clock enable */
__HAL_RCC_ADC3_CLK_ENABLE();
/* ADC Periph interface clock configuration */
__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);

/*##-1- Configure the ADC peripheral #######################################*/
AdcHandle3.Instance          = ADC3;

if (HAL_ADC_DeInit(&AdcHandle3) != HAL_OK){
/* ADC de-initialization Error */
}

AdcHandle3.Init.ClockPrescaler           = ADC_CLOCK_ASYNC_DIV2;          /* Asynchronous clock mode, input ADC clock divided by 2*/
AdcHandle3.Init.Resolution               = ADC_RESOLUTION_16B;            /* 16-bit resolution for converted data */
AdcHandle3.Init.ScanConvMode             = ENABLE;//DISABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
AdcHandle3.Init.EOCSelection             = ADC_EOC_SINGLE_CONV;           /* EOC flag picked-up to indicate conversion end */
AdcHandle3.Init.LowPowerAutoWait         = DISABLE;                       /* Auto-delayed conversion feature disabled */
AdcHandle3.Init.ContinuousConvMode       = ENABLE;              /* Continuous mode disabled to have only 1 conversion at each conversion trig */
AdcHandle3.Init.NbrOfConversion          = ADC_CONVERTED_DATA_BUFFER_SIZE3;                             /* Parameter discarded because sequencer is disabled */
AdcHandle3.Init.DiscontinuousConvMode    = DISABLE;                       /* Parameter discarded because sequencer is disabled */
AdcHandle3.Init.NbrOfDiscConversion      = 1;                             /* Parameter discarded because sequencer is disabled */
AdcHandle3.Init.ExternalTrigConv         = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */
AdcHandle3.Init.ExternalTrigConvEdge     = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
AdcHandle3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;     /* Regular Conversion data stored in DR register only */
AdcHandle3.Init.Overrun                  = ADC_OVR_DATA_OVERWRITTEN;      /* DR register is overwritten with the last conversion result in case of overrun */
AdcHandle3.Init.OversamplingMode         = DISABLE;                       /* No oversampling */
if (HAL_ADC_Init(&AdcHandle3) != HAL_OK){
}

/* ### - 2 - Start calibration ############################################ */
if (HAL_ADCEx_Calibration_Start(&AdcHandle3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK){
}

/*##-2- Configure ADC regular channel ######################################*/
sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;    /* Sampling time (number of clock cycles unit) */
sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* Single-ended input channel */
sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* No offset subtraction */ 
sConfig.Offset = 0;                                 /* Parameter discarded because offset correction is disabled */

sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;                /* Sampled channel number */
sConfig.Rank         = ADC_REGULAR_RANK_1;          /* Rank of sampled channel number ADCx_CHANNEL */
if (HAL_ADC_ConfigChannel(&AdcHandle3, &sConfig) != HAL_OK){;}

HAL_ADC_Start(&AdcHandle3);

}

 
Posted by 초보 HW 엔지니어 로망와니

댓글을 달아 주세요