void TIM2_IRQHandler(void) { int d, mv; //handle power 1 d = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); ict_vget_1 = d2mv(d); //printf("%d\n",ict_vget_1); mv = ict_vget_1 - ict_vexp_1; ict_vout_1 -= mv; d = mv2d(ict_vout_1); if(d < 0) d = 0; DAC_SetChannel1Data(DAC_Align_12b_R, d); //handle power 2 d = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2); ict_vget_2 = d2mv(d); //printf("%d\n",ict_vget_2); mv = ict_vget_2 - ict_vexp_2; ict_vout_2 -= mv; d = mv2d(ict_vout_2); if(d < 0) d = 0; DAC_SetChannel2Data(DAC_Align_12b_R, d); //handle I1&I2 d = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3); ict_iget_1 = d2mA(d); d = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_4); ict_iget_2 = d2mA(d); //printf("I1 = %d I2 = %d\n", i1, i2); ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE); TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); }
void SVPWM_3ShuntCurrentReadingCalibration(void) { static u16 bIndex; /* ADC1 Injected group of conversions end interrupt disabling */ ADC_ITConfig(ADC1, ADC_IT_JEOC, DISABLE); hPhaseAOffset=0; hPhaseBOffset=0; hPhaseCOffset=0; /* ADC1 Injected conversions trigger is given by software and enabled */ ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None); ADC_ExternalTrigInjectedConvCmd(ADC1,ENABLE); /* ADC1 Injected conversions configuration */ ADC_InjectedSequencerLengthConfig(ADC1,3); ADC_InjectedChannelConfig(ADC1, PHASE_A_ADC_CHANNEL,1,SAMPLING_TIME_CK); ADC_InjectedChannelConfig(ADC1, PHASE_B_ADC_CHANNEL,2,SAMPLING_TIME_CK); ADC_InjectedChannelConfig(ADC1, PHASE_C_ADC_CHANNEL,3,SAMPLING_TIME_CK); /* Clear the ADC1 JEOC pending flag */ ADC_ClearFlag(ADC1, ADC_FLAG_JEOC); ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE); /* ADC Channel used for current reading are read in order to get zero currents ADC values*/ for(bIndex=0; bIndex <NB_CONVERSIONS; bIndex++) { while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC)) { } hPhaseAOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1)>>3); hPhaseBOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_2)>>3); hPhaseCOffset += (ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_3)>>3); /* Clear the ADC1 JEOC pending flag */ ADC_ClearFlag(ADC1, ADC_FLAG_JEOC); ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE); } SVPWM_InjectedConvConfig( ); }
void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) != RESET) { /* Start ADC1 Software Conversion */ //ADC_SoftwareStartConvCmd(ADC3, ENABLE); ADC_SoftwareStartInjectedConvCmd(ADC3, ENABLE); /* Clear the EXTI Line 1 */ EXTI_ClearITPendingBit(EXTI_Line1); } }
void ict_Init(void) { led_Init(); led_flash(LED_GREEN); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DAC_InitTypeDef DAC_InitStructure; RCC_ADCCLKConfig(RCC_PCLK2_Div8); /*72Mhz/8 = 9Mhz*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOC| RCC_APB2Periph_GPIOA, ENABLE); // IO config GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_4| GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // DAC config DAC_StructInit(&DAC_InitStructure); DAC_Init(DAC_Channel_1, &DAC_InitStructure); DAC_Cmd(DAC_Channel_1, ENABLE); DAC_StructInit(&DAC_InitStructure); DAC_Init(DAC_Channel_2, &DAC_InitStructure); DAC_Cmd(DAC_Channel_2, ENABLE); /* ADC1 config, Power Ouput Voltage sampling, V1 = ADC1_CH2 = PA2 = ADC123_IN2 V2 = ADC2_CH7 = PA7 = ADC12_IN7 */ ADC_DeInit(ADC1); ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 0; ADC_Init(ADC1, &ADC_InitStructure); ADC_InjectedSequencerLengthConfig(ADC1, 4); ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_55Cycles5); //9Mhz/(71.5 + 12.5) = 107.1Khz ADC_InjectedChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_55Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 3, ADC_SampleTime_55Cycles5); //I0 ADC_InjectedChannelConfig(ADC1, ADC_Channel_6, 4, ADC_SampleTime_55Cycles5); //I1 ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE); /* ADC2 config, current sampling & over current protection * I1 = ADC1_CH1 = PA1 = ADC123_IN1 */ ADC_DeInit(ADC2); ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_Init(ADC2, &ADC_InitStructure); ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_71Cycles5); //9Mhz/(71.5 + 12.5) = 107.1Khz ADC_Cmd(ADC2, ENABLE); ADC_ResetCalibration(ADC2); while (ADC_GetResetCalibrationStatus(ADC2)); ADC_StartCalibration(ADC2); while (ADC_GetCalibrationStatus(ADC2)); ADC_AnalogWatchdogThresholdsConfig(ADC2, mA2d(100), 0x000); ADC_AnalogWatchdogSingleChannelConfig(ADC2, ADC_Channel_1); ADC_AnalogWatchdogCmd(ADC2, ADC_AnalogWatchdog_SingleRegEnable); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //START ADC_ITConfig(ADC2, ADC_IT_AWD, ENABLE); ADC_SoftwareStartConvCmd(ADC2, ENABLE); /* ADC3 config, current sampling & over current protection * I2 = ADC2_CH6 = PA6 = ADC12_IN6 */ ADC_DeInit(ADC3); ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_Init(ADC3, &ADC_InitStructure); ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 1, ADC_SampleTime_71Cycles5); //9Mhz/(71.5 + 12.5) = 107.1Khz ADC_Cmd(ADC3, ENABLE); ADC_ResetCalibration(ADC3); while (ADC_GetResetCalibrationStatus(ADC3)); ADC_StartCalibration(ADC3); while (ADC_GetCalibrationStatus(ADC3)); ADC_SoftwareStartConvCmd(ADC3, ENABLE); ADC_AnalogWatchdogThresholdsConfig(ADC3, mA2d(100),0x000); ADC_AnalogWatchdogSingleChannelConfig(ADC3, ADC_Channel_6); ADC_AnalogWatchdogCmd(ADC3, ADC_AnalogWatchdog_SingleRegEnable); NVIC_InitStructure.NVIC_IRQChannel = ADC3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //START ADC_ITConfig(ADC3, ADC_IT_AWD, ENABLE); ADC_SoftwareStartConvCmd(ADC3, ENABLE); // TIM config TIM_TimeBaseStructure.TIM_Period = 100 - 1; //Fclk = 10KHz /100 = 100Hz TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; //prediv to 72MHz to 10KHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); GPIO_ResetBits(GPIOD, GPIO_Pin_12); GPIO_ResetBits(GPIOD, GPIO_Pin_13); mbi5025_Init(&ict_mbi5025); mbi5025_EnableOE(&ict_mbi5025); }
/******************************************************************************* * Function Name : SysTickHandler * Description : This function handles SysTick Handler - runs at 100hz. * Input : None * Output : None * Return : None *******************************************************************************/ __attribute__((externally_visible)) void SysTickHandler(void) { static float I,old_pressure; static uint16_t Enabled_iterations; //Note, this is going to break if we spend long periods with +ive pressure set static uint32_t Last_Button_Press; //Holds the timestamp for the previous button press static uint8_t System_state_counter; //Holds the system state counter static uint8_t tmpindex; //Temp sensor decimator //FatFS timer function disk_timerproc(); //Incr the system uptime Millis+=10; if(ADC_GetFlagStatus(ADC2, ADC_FLAG_JEOC)) { //We have adc2 converted data from the injected channels ADC_ClearFlag(ADC2, ADC_FLAG_JEOC); //Clear the flag if(Pressure_Offset) //Only run the filter when we are sure the sensor is calibrated Reported_Pressure=filterloop(conv_diff(ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1)));//convert injected channel 1 //Now handle the pressure controller if(Pressure_control&0x7F) {//If active pressure control is enabled //run a PI controller on the air pump motor if(Pressure_Setpoint>0 && ( Button_hold_tim>(BUTTON_TURNOFF_TIME-BUTTON_MULTIPRESS_TIMEOUT) || !Button_hold_tim ) ) { // A Negative setpoint or prolonged button press forces a dump of air float error=Pressure_Setpoint-Reported_Pressure;//Pressure_Setpoint is a global containing the target diff press if(Enabled_iterations++>I_HOLDOFF) { I+=error*PRESSURE_I_CONST;//Constants defined in main.h if(I>PRESSURE_I_LIM) //Enforce limits I=PRESSURE_I_LIM; if(I<-PRESSURE_I_LIM) I=-PRESSURE_I_LIM; } int16_t a=PRESSURE_P_CONST*error+I+PRESSURE_D_CONST*(Reported_Pressure-old_pressure); if(a>0) //Make sure we are actually turning the motor on Set_Motor((int16_t)a); //Set the motor gpio dir & pwm duty } else { Enabled_iterations=0; //Make sure this is reset if(abs(Reported_Pressure)>PRESSURE_MARGIN) Set_Motor(-1); //Set a dump to rapidly drop to zero pressure else Set_Motor(0); } } else if(!Pressure_control) //If the most significant bit isnt set Set_Motor(0); //Sets the Rohm motor controller to idle (low current shutdown) state //Check the die temperature - not possible on adc1 :-( //Device_Temperature=convert_die_temp(ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_3));//The on die temperature sensor #if BOARD>=3 if(Sensors&(1<<THERMISTOR_SENSOR)) Device_Temperature=convert_thermistor_temp(ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_3)); #endif //Could process some more sensor data here old_pressure=Reported_Pressure; //Set the old pressure record here for use in the D term } ADC_SoftwareStartInjectedConvCmd(ADC2, ENABLE); //Trigger the injected channel group //Read any I2C bus sensors here (100Hz) if(Sensors&(1<<TEMPERATURE_SENSOR)) { TMP102_Reported_Temperature=GET_TMP_TEMPERATURE; if(!tmpindex--) { //Every 30ms tmpindex=3; //Jobs|=1<<TMP102_CONFIG; I2C1_Request_Job(TMP102_READ); //Request a TMP102 read if there is one present I2C1_Request_Job(TMP102_CONFIG); //Need to do this to set one shot bit is set high again to start a new single convertion //Some sort of i2c error here } } //Now process the control button functions if(Button_hold_tim ) { //If a button press generated timer has been triggered if(GET_BUTTON) { //Button hold turns off the device if(!--Button_hold_tim) { shutdown_filesystem(); shutdown(); //Turn off the logger after closing any open files } } else { //Button released - this can only ever run once per press RED_LED_OFF; //Turn off the red LED - used to indicate button press to user if(Button_hold_tim<BUTTON_DEBOUNCE) { //The button has to be held down for longer than the debounce period Last_Button_Press=Millis; if(++System_state_counter>=SYSTEM_STATES) System_state_counter=0;//The system can only have a limited number of states } Button_hold_tim=0; //Reset the timer here } } if(Last_Button_Press&&(Millis-Last_Button_Press>BUTTON_MULTIPRESS_TIMEOUT)&&!Button_hold_tim) {//Last press timed out and button is not pressed if(!(System_state_Global&0x80)) //The main code has unlocked the global using the bit flag - as it has processed System_state_Global=0x80|System_state_counter;//The previous state update System_state_counter=0; //Reset state counter here Last_Button_Press=0; //Reset the last button press timestamp, as the is no button press in play } }
/** * Initialize the ADC peripherals and internal state of the driver */ void adc_init(void) { NVIC_InitTypeDef nvic; GPIO_InitTypeDef gpio; ADC_InitTypeDef adc; /* enable ADC1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); /* Configure and enable ADC interrupt */ nvic.NVIC_IRQChannel = ADC1_2_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 0; nvic.NVIC_IRQChannelSubPriority = 0; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); /* GPIOA: ADC Channel 0, 1, 2, 3 as analog input * Ch 3 -> Battery Voltage * Ch 4 -> Current * Ch 5 -> Temperature */ gpio.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; gpio.GPIO_Mode = GPIO_Mode_AIN; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio); adc_data.battery_voltage = 0; adc_data.current = 0; adc_data.temp = 0; /* Configure ADC1 */ adc.ADC_Mode = ADC_Mode_Independent; adc.ADC_ScanConvMode = ENABLE; adc.ADC_ContinuousConvMode = ENABLE; adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; adc.ADC_DataAlign = ADC_DataAlign_Right; adc.ADC_NbrOfChannel = 0; ADC_Init(ADC1, &adc); ADC_InjectedSequencerLengthConfig(ADC1, 3); ADC_InjectedChannelConfig(ADC1, ADC_CHANNEL_BATTERY_VOLTAGE, 1, ADC_SampleTime_239Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_CHANNEL_CURRENT, 2, ADC_SampleTime_239Cycles5); ADC_InjectedChannelConfig(ADC1, ADC_CHANNEL_TEMP, 3, ADC_SampleTime_239Cycles5); /* ADC1 injected external trigger configuration */ ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None); /* Enable ADC1 JEOC interrupt */ ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration */ while (ADC_GetResetCalibrationStatus(ADC1) == SET) ; /* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while (ADC_GetCalibrationStatus(ADC1) == SET) ; /* Start ADC1 Software Conversion */ ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE); /* Register adc as a timed callback */ sys_tick_timer_register(adc_conv_trigger, 1000); }
/** * Trigger timer callback */ void adc_conv_trigger(int id) { /* Start ADC1 Software Conversion */ ADC_SoftwareStartInjectedConvCmd(ADC1, ENABLE); }