on 2022-09-06 12:57 AM
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #define OFFSET 50 /* USER CODE END Includes */ /* USER CODE BEGIN PV */ volatile uint8_t Sine_Table[360] = { 50, 51, 52, 53, 53, 54, 55, 56, 57, 58, 59, 60, 60, 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 70, 70, 71, 72, 73, 73, 74, 75, 76, 76, 77, 78, 79, 79, 80, 81, 81, 82, 83, 83, 84, 85, 85, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 97, 97, 97, 96, 96, 96, 95, 95, 95, 94, 94, 93, 93, 92, 92, 91, 91, 90, 90, 89, 89, 88, 88, 87, 87, 86, 85, 85, 84, 83, 83, 82, 81, 81, 80, 79, 79, 78, 77, 76, 76, 75, 74, 73, 73, 72, 71, 70, 70, 69, 68, 67, 66, 65, 65, 64, 63, 62, 61, 60, 60, 59, 58, 57, 56, 55, 54, 53, 53, 52, 51, 50, 49, 48, 47, 47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 38, 37, 36, 35, 35, 34, 33, 32, 31, 30, 30, 29, 28, 27, 27, 26, 25, 24, 24, 23, 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 23, 24, 24, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 47, 48, 49 }; uint8_t ResetString[] = "**************\r\n* Set Values *\r\n**************\r\n\n" uint8_t FrequencyString[] = "*Choose Frequency*: \r\n"; uint8_t AmplitudeString[] = "*Choose Amplitude*: \r\n"; uint8_t FrequencyBuffer[3]; uint8_t AmplitudeBuffer[3]; uint8_t FrequencyIndex = 0; uint8_t AmplitudeIndex = 0; uint16_t SineAmplitude = 100; uint16_t ButtonON = 0; /* USER CODE END PV */The next step is to initialize the PWM and UART functions. After the peripherals initialization and before the main while loop, the PWM start function and the UART transmit and the receive functions will be called–please refer to the comments “USER CODE BEGIN” to facilitate the location to copy and paste:
/* USER CODE BEGIN 2 */ //Start the PWM in Timer 3 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); //Transmit the restart message in the UART HAL_UART_Transmit(&huart2, ResetString, sizeof(ResetString), 100); //Transmit the Frequency requirement string HAL_UART_Transmit(&huart2, FrequencyString, sizeof(FrequencyString), 100); //Receive the Frequency value HAL_UART_Receive_IT(&huart2, FrequencyBuffer, 1); /* USER CODE END 2 */Now, it is time to recreate the callback functions. In the /* USER CODE BEGIN 4 */ area, use the PWM callback with the following characteristics:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { static uint16_t i = 0; //If the index is higher than the sine table size, //it returns to the initial position in the table if(i > 360) i = 0; //If the index is lower than the sine table size, //it keeps walking through it else i++; //Put the sine table's values in the pulse pointer, as the Duty Cycle TIM3->CCR2 = Sine_Table[i]; }The pulse value is updated to complete the loop cycle of the sine wave with a direct register access instead of calling the HAL function, thus the TIM3 CCR2 manipulation.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint16_t i = 0; //Temporary Sine variable static signed int TempSine = 0; //If the index is higher than the sine table size, //it returns to the initial position in the table if(i > 360) i = 0; //If the index is lower than the sine table size, //it keeps walking through it else i++; //Put aside the offset so the sine table can be multiplied TempSine = Sine_Table[i] - OFFSET; //Multiply the sine values to the desirable amplitude percentage TempSine *= SineAmplitude; //As the values will be received in percentage, //it is necessary to divide it by 100 TempSine /= 100; //Add the offset again TempSine += OFFSET; //Put the new values in the pulse pointer, as the Duty Cycle TIM3->CCR2 = TempSine; }The next callback function will be the User’s Button external interrupt callback. As mentioned before, the button alternates from “frequency” to “amplitude” parameter when pressed:
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin) { //There will be a string for visual organization purpose HAL_UART_Transmit(&huart2, (uint8_t *)"----\r\n\n", size of("----\r\n\n"), 100); //Transmit the Amplitude String every time the button is pressed HAL_UART_Transmit(&huart2, AmplitudeString, sizeof(AmplitudeString), 100); //Abort the reception not to overwrite the buffer HAL_UART_AbortReceive_IT(&huart2); //Receive the new amplitude value HAL_UART_Receive_IT(&huart2, &AmplitudeBuffer[0], 1); //This callback is associated with the flag created ButtonON = 1; }The last callback to be implemented is the UARTs receive complete, this one collects the values of frequency and amplitude:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //UART { uint16_t SineFrequency; //If the User's Button is not activated, then this loop happens if (ButtonON != 1){ HAL_UART_Transmit(&huart2, &FrequencyBuffer[FrequencyIndex], 1,100); //if the frequency index is the same size as the buffer's value, then: If(FrequencyIndex >= (sizeof(FrequencyBuffer)-1)){ //The index returns to the initial position FrequencyIndex = 0; //There will be a string for visual organization purpose HAL_UART_Transmit(&huart2, (uint8_t *)"\r\n\n", size of("\r\n\n"), 100); //The frequency variable updates its value to the value received SineFrequency = ((FrequencyBuffer[0]-0x30)*100) + ((FrequencyBuffer[1]-0x30)*10) + (FrequencyBuffer[2]-0x30); //The auxiliary timer frequency is modified accordingly uint16_t AuxTimerFreq = SineFrequency * 360; //The counter period is modified based on the new auxiliary timer frequency uint16_t CounterPeriod = (1000000)/(AuxTimerFreq - 1); //The new value will officially updated htim6.Init.Period = CounterPeriod; //There will be an initialization function HAL_TIM_Base_Init(&htim6); //The timer is started with the new values HAL_TIM_Base_Start_IT(&htim6); //The frequency string is activated again to keeps it in loop HAL_UART_Transmit(&huart2, FrequencyString, sizeof(FrequencyString), 100); //Receive the Frequency value HAL_UART_Receive_IT(&huart2, FrequencyBuffer, 1); //If the frequency index is lower than the buffer's value, then: } else { //The index keeps walking through the buffer size until it is completed FrequencyIndex++; //The receive frequency function is activated until the buffer is completed HAL_UART_Receive_IT(&huart2, &FrequencyBuffer[FrequencyIndex], 1); } } //If the User's Button is activated, then this loop happens else{ HAL_UART_Transmit(&huart2, &AmplitudeBuffer[AmplitudeIndex], 1, 100); //if the amplitude index is the same size as the buffer's value, then: if(AmplitudeIndex >= (sizeof(AmplitudeBuffer)-1)){ //The index returns to the initial position AmplitudeIndex = 0; //There will be a string for visual organization purpose HAL_UART_Transmit(&huart2, (uint8_t *)"\r\n\n", sizeof("\r\n\n"), 100); //The amplitude variable updates its value to the value received SineAmplitude = ((AmplitudeBuffer[0]-0x30)*100) + ((AmplitudeBuffer[1]-0x30)*10) + (AmplitudeBuffer[2]-0x30); //This loop takes any value higher than 100 and set it to 100, which is the maximum value possible if(SineAmplitude > 100) SineAmplitude = 100; //This will return the flag to 0, so it can switch back to the frequency loop ButtonON = 0; //The frequency string is activated again to keeps it in loop HAL_UART_Transmit(&huart2, FrequencyString, sizeof(FrequencyString), 100); //The value of the frequency can be updated again HAL_UART_Receive_IT(&huart2, FrequencyBuffer, 1); } //If the amplitude index is lower than the buffer's value, then: else { //The index keeps walking through the buffer size until it is completed AmplitudeIndex++; //The receive amplitude function is activated until the buffer is completed HAL_UART_Receive_IT(&huart2, &AmplitudeBuffer[AmplitudeIndex], 1); } } }