Hello everyone,
We have initilalized all the peripherals and created subsidiary function we need. In this note, we are going to create main.c with the interrupts routines.
First let's remember algorithm flow char to help ourselves to be able to imagine easily in mind. I marked parts we need to handle with red rectangle. Then I will give complete code of main.c and I'll try to explain line by line.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stm32f4xx.h" | |
#include "RHBE.h" | |
volatile static isControlStruct isControl; | |
uint8_t counterMotorRotate, counterABSPulse; | |
int main(){ | |
//Variables are set initial values. | |
isControl.isButton = FALSE; | |
isControl.isMotorRotateEnough = FALSE; | |
isControl.isComplete = FALSE; | |
counterMotorRotate = 0; | |
counterABSPulse = 0; | |
//Button, LED and USART are set. | |
RHBE_InitButtonInterrupt(); | |
RHBE_InitLED(); | |
RHBE_InitUSART(); | |
USART_SendString(USART2, "Program Started\r\n"); | |
while(1){ | |
while(!isControl.isButton); | |
while(!isControl.isMotorRotateEnough); | |
while(!isControl.isComplete); | |
} | |
} | |
/* | |
This interrupt function controls start button. It will set up configuration after button is pressed. | |
*/ | |
void EXTI0_IRQHandler(){ | |
if(EXTI_GetITStatus(EXTI_Line0) == 1){ //Which interrupts flag was set? | |
USART_SendString(USART2, "Motor has been started.\r\n"); | |
RHBE_InitPWM(); //Motor started spinning. | |
RHBE_SetPWMDutyCycle(50); //Duty Cycle was set %50. | |
RHBE_InitFirstTimer(); //Timer has been set to calculate sufficent motor spinning. | |
USART_SendString(USART2, "PWM Init.\r\nTimer Init\r\n"); //User has been informed. | |
EXTI_ClearITPendingBit(EXTI_Line0); //Cleaning interrupt flag. | |
} | |
} | |
/* | |
This interrupt function determines whether motor is spinned enough or not? | |
*/ | |
void TIM2_IRQHandler(){ | |
if (TIM_GetITStatus(TIM2, TIM_IT_Update)){ | |
counterMotorRotate++; | |
if(counterMotorRotate >= 5){ //After some time motor will reach desired speed. | |
TIM_Cmd(TIM2, DISABLE); | |
isControl.isMotorRotateEnough = TRUE; // Value should be False end of program. | |
USART_SendString(USART2, "Motor has been rotated enough.\r\n"); | |
RHBE_InitABSSignalInterrupt(); | |
USART_SendString(USART2, "ABS Interrupt has been set.\r\n"); | |
USART_SendString(USART2, "Encoder Init.\r\n"); | |
RHBE_InitEncoder(); | |
TIM_SetCounter(TIM4, 0); //Encoder counter is set to 0. | |
counterMotorRotate = 0; | |
} | |
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //Cleaning interrupt flag. | |
} | |
} | |
/* | |
This interrupt function is triggered by ABS signal ouput. | |
When ABS complete one pulse, this function will be executed. | |
*/ | |
void EXTI1_IRQHandler(){ | |
uint32_t Encoder; | |
if(EXTI_GetITStatus(EXTI_Line1) == 1){ | |
Encoder = TIM_GetCounter(TIM4); //Get the encoder value between two pulse. | |
TIM_SetCounter(TIM4, 0); // Prepare timer counter for next pulse measurement. | |
counterABSPulse++; | |
if(counterABSPulse <= 96){ | |
if(Encoder > 72 && Encoder < 56){ //if encoder counting exceed our limits throw an error and notify user as Not OK. | |
RHBE_SetPWMDutyCycle(1); | |
isControl.isComplete = TRUE; | |
isControl.isResult = FALSE; | |
isControl.isButton = FALSE; | |
isControl.isMotorRotateEnough = FALSE; | |
USART_SendString(USART2, "NG"); | |
counterABSPulse = 0; | |
} | |
else { // if there is not problem in one revolution, that means part is OK. | |
RHBE_SetPWMDutyCycle(0); //Stop motor. | |
isControl.isResult = TRUE; | |
isControl.isComplete = TRUE; | |
isControl.isButton = FALSE; | |
isControl.isMotorRotateEnough = FALSE; | |
USART_SendString(USART2, "OK"); //Notify user. | |
counterABSPulse = 0; | |
} | |
} | |
EXTI_ClearITPendingBit(EXTI_Line1); //cleaning interrupt flag. | |
} | |
} |
I have created struct to keep some related variables together. These variables are isButton, isMotorRotateEnough, isComplete. Their variable names explain what they are for. Also I have created two variables to use in loops. They are counterMotorRotate and counterABSPulse.
There are variable initialization up to while(1) loop in main function. while loops in while will keep program in the loop until waited action occurs.
void EXTI0_IRQHandler()function is for start button. It will wait until button is pressed then will let microcontroller to create PWM signal for motor spinning. Motor needs to overcome inertia force therefore we need to wait motor to spin a few tour. Timer 2 will play role to count these needed time. When time is up, encoder value will be set to 0 and ABS signal interrupt will be enabled. Also to count encoder pulses timer will be set as two channels input.
void EXTI1_IRQHandler() function will be executed in every ABS signal rising edge. When ABS signal generates rising edge this function will get the encoder value and evalute it according to requirements. Each time when this function executed encoder counter must be set to zero. Otherwise encoder counts over previous value and in the second execution program fails as part not OK.
And done! Here is the demonstration videos.
Comments
Post a Comment