/**VARIABLE DUTY CYCLE BY EXTERNAL REFERENCE**/
#include "stm32f0xx.h"
#include "stm32f0_discovery.h"
#define LED_BLUE_GPIO GPIOC
#define LED_BLUE_PIN 8
#define LED_YELLOW_PIN 9
//---------------------------------------------------------------------
unsigned char flag_1s=0;
unsigned int Duty_cycle_boost=0,Duty_cycle_buck=0;
//---------------------------------------------------------------------
/** @addtogroup STM32F0_Discovery_Peripheral_Examples
* @{
*/
/** @addtogroup ADC_DMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_Address 0x40012440
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t Boost_Ref_mv = 0, Buck_Ref_mv = 0, Boost_feedbak_output=0;
__IO uint16_t RegularConvData_Tab[3];
/* Private function prototypes -----------------------------------------------*/
void ADC1_CH_DMA_Config(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
/** @addtogroup STM32F0_Discovery_Peripheral_Examples
* @{
*/
/** @addtogroup TIM_PWM_Output
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t TimerPeriod = 0;
uint16_t Channel1Pulse = 0, Channel2Pulse = 0, Channel3Pulse = 0, Channel4Pulse = 0;
/* Private function prototypes -----------------------------------------------*/
void TIM_Config(void);
/* Private functions ---------------------------------------------------------*/
int main (void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* ADC1 channel with DMA configuration */
ADC1_CH_DMA_Config();
//RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
RCC->AHBENR |=RCC_AHBENR_GPIOCEN; // CONFIGURE CLOCK FOR PORT C
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //ENABLED CLOCK FOR TIMER 3
RCC -> AHBENR |=(1<<19); // ENABLE CLOCK FOR PORT C
GPIOC -> MODER |=(1<<18); //ENABLE PIN 9 OF PORT C
GPIOC -> MODER |=(1<<16); //ENABLE PIN 8 OF PORT C
//STM_EVAL_LEDInit(LED3); // LED 8 INITIALIZATION
//STM_EVAL_LEDInit(LED4); // LED 9 INITILIZATION
TIM3->PSC = 23999; // Set prescaler to 24 000 (PSC + 1)
TIM3->ARR = 2000; // Auto reload value 1000 (FOR 1 SECOND DELAY)
TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
TIM3->CR1 = TIM_CR1_CEN;// Enable timer
NVIC_EnableIRQ(TIM3_IRQn); // Enable interrupt from TIM3 (NVIC level)
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* TIM Configuration */
TIM_Config();
/* TIM1 Configuration ---------------------------------------------------
Generate PWM signals with 4 different duty cycles:
TIM1 input clock (TIM1CLK) is set to APB2 clock (PCLK2)
=> TIM1CLK = PCLK2 = SystemCoreClock
TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
SystemCoreClock is set to 48 MHz for STM32F0xx devices
The objective is to generate 4 PWM signal at 17.57 KHz:
- TIM1_Period = (SystemCoreClock / 17570) - 1
The channel 1 and channel 1N duty cycle is set to 50%
The channel 2 and channel 2N duty cycle is set to 37.5%
The channel 3 and channel 3N duty cycle is set to 25%
The channel 4 duty cycle is set to 12.5%
The Timer pulse is calculated as follows:
- ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f0xx.c file.
Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
function to update SystemCoreClock variable value. Otherwise, any configuration
based on this variable will be incorrect.
----------------------------------------------------------------------- */
/* Compute the value to be set in ARR regiter to generate signal frequency at 17.57 Khz */
// TimerPeriod = (SystemCoreClock / 17570 ) - 1;
TimerPeriod = (SystemCoreClock / 99000 ) - 1; // TO SET THE FREQUENCY
/* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */
//Channel1Pulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);
// Channel1Pulse = (uint16_t) (((uint32_t) Duty_cycle * (TimerPeriod - 1)) / 100);
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
//RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //ENABLED CLOCK FOR TIMER 3
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2, 3 and 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
while (1)
{
/**WHEN CONTROLLER ENDS UP WITH THE CONTING DEFINED ABOVE VALUE IE;1000 (FOR 1SECONDS) THEN IT FLAGS TO 1 WHICH WILL CALLED
THE INTERRUPT, AND IT IS GOIN INTO THE "void TIM3_IRQHandler(void) "TO COMPLETE THE INTEREPT REQUEST **/
if( flag_1s)
{
flag_1s=0;
//LED_BLUE_GPIO->ODR ^= (1 << 8); // toggle LED state
//LED_BLUE_GPIO->ODR ^= (1 << 9); // toggle led state
/* Test DMA1 TC flag */
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
/* Clear DMA TC flag */
DMA_ClearFlag(DMA1_FLAG_TC1);
/* Convert temperature sensor voltage value in mv (CONVERT BOOST volt REF IN mv)*/
Boost_Ref_mv = (uint32_t)((RegularConvData_Tab[0]* 3000) / 0xFFF);
/*Convert Vref voltage value in mv * ADC CHANNEL 1 /*/
Boost_feedbak_output = (uint32_t)((RegularConvData_Tab[1]* 3000) / 0xFFF); // NOT USED NOW
//Boost_feedbak_output = (uint32_t)((RegularConvData_Tab[2]* 3000) / 0xFFF); // for output feedback
// Duty_cycle=((90-10)* TempSensVoltmv/3000)+10;
if (Boost_feedbak_output<1500)
{
if(Boost_Ref_mv>500)
{
Duty_cycle_boost=90-(80* Boost_Ref_mv/3000);
//Duty_cycle_buck=90-(80* Buck_Ref_mv/3000);
Channel1Pulse = (uint16_t) (((uint32_t) Duty_cycle_boost * (TimerPeriod - 1)) / 100);// realise the duty cycle FOR PIN PA8
//Channel2Pulse = (uint16_t) (((uint32_t) Duty_cycle_buck * (TimerPeriod - 1)) / 100);// realise the duty cycle FOR PIN PA9
//LED_BLUE_GPIO->ODR ^= (1 << 8); // toggle LED state
// CONFIGURE CHANNEL 1 & CHANNEL 2
TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse =0;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
LED_BLUE_GPIO->ODR |= (1 << 8);// blue led on
//TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
//TIM_OC2Init(TIM1, &TIM_OCInitStructure);
}
else
{
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
LED_BLUE_GPIO->BRR |= (1 << 8);// blue led on
}
}
else
{
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
LED_BLUE_GPIO->BRR |= (1 << 8);// blue led on
}
/* else if (Buck_Ref_mv>500)
{
Duty_cycle_buck=90-(80* Buck_Ref_mv/3000);
Channel2Pulse = (uint16_t) (((uint32_t) Duty_cycle_buck * (TimerPeriod - 1)) / 100);// realise the duty cycle FOR PIN PA9
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
LED_BLUE_GPIO->ODR |= (1 << 9);// yellow led on
}*/
/*
if(TempSensVoltmv>=0xbb5)
{
LED_BLUE_GPIO->ODR ^= (1 << 8); // toggle LED state
LED_BLUE_GPIO->BRR|=(1<<9);
}
else if(TempSensVoltmv==0)
{
LED_BLUE_GPIO->ODR ^= (1 << 9); // toggle led state
LED_BLUE_GPIO->BRR|=(1<<8);
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
}*/
//LED_BLUE_GPIO->ODR ^= (1 << 8); // toggle LED state
//TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
//TIM_OC1Init(TIM1, &TIM_OCInitStructure);
/* TIM1 counter enable */
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
}
}
void ADC1_CH_DMA_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
/* DMA1 Channel1 Config */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RegularConvData_Tab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/* Enable ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
/* Configure the ADC1 in continous mode withe a resolutuion equal to 12 bits */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(ADC1, &ADC_InitStructure);
/* Convert the ADC1 temperature sensor with 55.5 Cycles as sampling time */
//ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor , ADC_SampleTime_55_5Cycles);
/* Convert the ADC1 Vref with 55.5 Cycles as sampling time */
//ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_55_5Cycles); // CONFIGURED PA1 AS A ADC CHANNEL 1 for boost
//ADC_VrefintCmd(ENABLE);
ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_55_5Cycles);// CONFIGURED PA2 AS A ADC CHANNEL 2 for buck
// ADC_TempSensorCmd(ENABLE);
//ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_55_5Cycles); //Configured for boost feedback from output
/* ADC Calibration */
ADC_GetCalibrationFactor(ADC1);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait the ADCEN falg */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
/* ADC1 regular Software Start Conv */
ADC_StartOfConversion(ADC1);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
void TIM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOA Clocks enable */
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA, ENABLE);
/* GPIOA Configuration: Channel 1, 2, 3 and 4 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_2);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
void TIM3_IRQHandler(void) // INTERRUPT SERVICE ROUTINE CALL FROM WHILE
{
TIM3->SR &= ~TIM_SR_UIF; // clear UIF=Update Interrupt Flag
flag_1s=1; // IT SETS THE FLAG=1, SO IT WILL ENTER IN WHILE LOOP AS IF LOOP PASS IN THE MAIN FUNCTION
}