I'm trying to start a STM32L576VGT with FreeRTOS.
I have a led blinking from a task and now I'm trying to set a PWM on, freq and duty is not important now, is a "hello world pwm".
All is done using CubeMx, and I'm been unable to make it work.
tim.c generated with CubeMx for TIM15
/* TIM15 init function */
void MX_TIM15_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
htim15.Instance = TIM15;
htim15.Init.Prescaler = 47999;
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
htim15.Init.Period = 200;
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim15.Init.RepetitionCounter = 0;
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_PWM_Init(&htim15) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim15, &sBreakDeadTimeConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim15);
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM15)
{
/* USER CODE BEGIN TIM15_MspInit 0 */
/* USER CODE END TIM15_MspInit 0 */
/* TIM15 clock enable */
__HAL_RCC_TIM15_CLK_ENABLE();
/* USER CODE BEGIN TIM15_MspInit 1 */
/* USER CODE END TIM15_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(timHandle->Instance==TIM15)
{
/* USER CODE BEGIN TIM15_MspPostInit 0 */
/* USER CODE END TIM15_MspPostInit 0 */
/**TIM15 GPIO Configuration
PB15 ------> TIM15_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_TIM15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM15_MspPostInit 1 */
/* USER CODE END TIM15_MspPostInit 1 */
}
}
main in main.c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_QUADSPI_Init();
MX_LPUART1_UART_Init();
MX_SPI2_Init();
MX_I2C1_Init();
MX_TIM15_Init();
/* USER CODE BEGIN 2 */
// DISP_diplay_init();
HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_2);
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
I'm using TIM15 because the PCB is already done and it is the one is connected to the output i want to control.
Thanks,
Guillermo
Have you tried with different values on sConfigOC.Pulse = 0;?
Related
I'm using the STM B-L475E-IOT01A2 discovery board and I'm trying to get it to print a value to its serial port via uart. So far I haven't been successful. It builds fine, and doesn't error (tested with some LEDs) but nothing prints to the serial (tested with screen /dev/ttyACM0 9600). Here is my code, most of it is auto generated by CubeMX.
/** file: usart.c **/
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
/** file: main.c **/
int main(void)
{
HAL_UART_MspInit(&huart1);
MX_USART1_UART_Init();
while(1) {
HAL_UART_Transmit(&huart1, (uint8_t *)"Testing 123", 11, 100);
HAL_Delay(1000);
}
}
i am using the Nucleo64 STM32F446 board and i am trying to read out 3 temperature sensors with the polling method and via DMA but with both methods i can get only 1 correct value. The voltage at every ADC Input is the same. I cannot find the mistake.
Here i drop the polling method: (I just followed this Youtube Tut: https://www.youtube.com/watch?v=5l-b6lsubBE )
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
#include <math.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
double Temp1 = 0;
double Temp2 = 0;
double Temp3 = 0;
double resistance1;
double resistance2;
double resistance3;
uint16_t ADC_VAL[3];
void ADC_Select_CH1(void){
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
void ADC_Select_CH2(void){
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
void ADC_Select_CH3(void){
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
uint16_t x =0;
uint16_t y =0;
uint16_t z =0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
ADC_Select_CH1();
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
ADC_VAL[0] = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
ADC_Select_CH2();
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
ADC_VAL[1] = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
ADC_Select_CH3();
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
ADC_VAL[2] = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
x = ADC_VAL[0];
y = ADC_VAL[1];
z = ADC_VAL[2];
int resolution = 4096;
resistance1 = 10000*((x/(double)resolution)/(1-(x/(double)resolution)));
resistance2 = 10000*((y/(double)resolution)/(1-(y/(double)resolution)));
resistance3 = 10000*((z/(double)resolution)/(1-(z/(double)resolution)));
Temp1 = 1/((1/298.15)+((double)1/3435)*log((double)resistance1/10000));
Temp2 = 1/ ((1/298.15)+((double)1/3435)*log((double)resistance2/10000));
Temp3 = 1/ ((1/298.15)+((double)1/3435)*log((double)resistance3/10000));
Temp1 = Temp1 - 273.15;
Temp2 = Temp2 - 273.15;
Temp3 = Temp3 - 273.15;
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 180;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief ADC1 Initialization Function
* #param None
* #retval None
*/
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
// /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
// */
// sConfig.Channel = ADC_CHANNEL_1;
// sConfig.Rank = 1;
// sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
// Error_Handler();
// }
// /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
// */
// sConfig.Channel = ADC_CHANNEL_2;
// sConfig.Rank = 2;
// sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
// Error_Handler();
// }
// /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
// */
// sConfig.Channel = ADC_CHANNEL_3;
// sConfig.Rank = 3;
// sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
// Error_Handler();
// }
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : LD2_Pin */
GPIO_InitStruct.Pin = LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#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 CODE BEGIN 6 */
/* 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) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
i used PA7 and PA4 instead of PA2 & PA3 for the ADC conversion and it's working. It seems that on this Nucleo Board PA2 & PA3 is not suitable for this task.
Trying to make simple PWM transmitter i faced with a problem. I have TIM2 with Channel2 (in PWM Generation mode) on board NUCLEO F042K6 and USART1 connected to the board in Async mode (USART works in DMA).
I wanted to make a PWM transmitter that uses a circular buffer that can be filled with one character or several characters at once. The plan was that when the user enters a character (or several characters), the idle line callback is processed, in which a function is called that stores the data in a cyclic buffer. After saving, the data transferred to the buffer is passed to the function PWM_SendChar(...) to convert the data into bits and transfer them over the PWM line. But the problem is when the program goes into PWM_SendChar(...) the callback HAL_TIM_PWM_PulseFinishedCallback(...) isn't called and program stucks in infinite while loop because variable used as a flag for detecting the end of single pulse (PWM_data_sent_flag) wasn't set to value 1.
However, if I use HAL_UART_Recieve(...) func in while(1) loop (located in main(void)) to recieve a char from user program works fine without stucking in while loop in TIM callback. Ofc, for this method I don't use HAL_UARTEx_RxEventCallback(...) and cycle buffer.
Thats's why I think the problem is in USART idle line detection and please help me solve it.
Code Example
Global variable used for waiting the end of pulse:
volatile uint16_t PWM_data_sent_flag = 0;
PWM timer callback:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM2) {
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_2);
PWM_data_sent_flag = 1;
}
}
Callback for USART idle line:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart == &huart1) {
// Function_to_save_input_char_in_cycle_buffer() is called
}
}
Function used to send char as a PWM signal (emited after Function_to_save_input_char_in_cycle_buffer() completed):
void PWM_SendChar(char ch) {
for (int i = 0, mv = 7; i <= 7; ++i, --mv) {
uint8_t bit = (ch & (1 << mv)) ? 1 : 0;
// PWM_LOW_PERCENT encodes bit with zero value, PWM_HIGH_PERCENT encodes bit with value one
uint16_t duty_cycle = bit == 0 ? PWM_LOW_PERCENT : PWM_HIGH_PERCENT;
// Change TIM2 CCR2 value according to bit's value
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,
GET_PERCENT_VALUE(TIM2->ARR, duty_cycle));
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
// Program comes to this cycle and doesn't leave it
while (!PWM_data_sent_flag)
;
PWM_data_sent_flag = 0;
}
}
USART receive to idle launch (half data transmitted callback disabled):
int main(void) {
// Init code
// ...
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart1, (uint8_t*) ring_buf.buff,
ARRAY_LEN(ring_buf.buff)) != HAL_OK) {
Error_Handler();
}
// Disable half word transmitted callback
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
while(1) {
}
}
TIM2 settings:
static void MX_TIM2_Init(void) {
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
TIM_MasterConfigTypeDef sMasterConfig = { 0 };
TIM_OC_InitTypeDef sConfigOC = { 0 };
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 48000 - 1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 100 - 1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig)
!= HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2)
!= HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
USART1 settings:
static void MX_USART1_UART_Init(void) {
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
DMA settings:
static void MX_DMA_Init(void) {
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel4_5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
}
I have two STM32L432 nucleos which communicate via CAN.
One STM32 is running FreeRTOS and the other isn't.
The one that isn't can both receive and transmit correctly via CAN.
The one that is running FreeRTOS can only transmit via CAN.
The CAN configuration on the two are identical.
Have tried calling NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); before osKernelInitialize(); is called as stated in https://www.freertos.org/RTOS-Cortex-M3-M4.html however the function isn't recognized so I've changed it to
NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 ); which compiles.
So the question is why arren't the CAN RX interrupt triggering on the Nucleo running FreeRTOS?
Nucleo running FreeRTOS:
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "gpsdriver.h"
#include "DCMotorDriver.h"
#include "mpu6050_driver.h"
#include "Transmit_driver.h"
#include "partcl_driver.h"
#include "circle_queue.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PACKAGE_SIZE 8
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan1;
I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
/* Definitions for taskGPS */
osThreadId_t taskGPSHandle;
const osThreadAttr_t taskGPS_attributes = {
.name = "taskGPS",
.stack_size = 500 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for taskDCMotor */
osThreadId_t taskDCMotorHandle;
const osThreadAttr_t taskDCMotor_attributes = {
.name = "taskDCMotor",
.stack_size = 500 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for taskMpu6050 */
osThreadId_t taskMpu6050Handle;
const osThreadAttr_t taskMpu6050_attributes = {
.name = "taskMpu6050",
.stack_size = 500 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for taskParTcl */
osThreadId_t taskParTclHandle;
const osThreadAttr_t taskParTcl_attributes = {
.name = "taskParTcl",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* USER CODE BEGIN PV */
CAN_TxHeaderTypeDef CanTxHeader;
CAN_RxHeaderTypeDef CanRxHeader;
CAN_FilterTypeDef CanFilter;
struct Queue queueCANRX ={0,0,{0}};
GPS_FIX_DATA data = { 0 };
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_CAN1_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM2_Init(void);
void task_gps(void *argument);
void task_dcmotor(void *argument);
void task_mpu6050(void *argument);
void task_partcl(void *argument);
/* USER CODE BEGIN PFP */
void WatchdogHandler(){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
}
// This function is called from the CAN1_RX0_IRQHandler in STM32L4xx_it.c file
void receiveData() {
uint8_t buffer[PACKAGE_SIZE] = {0};
while (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) > 0) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
if (!QueueFull(&queueCANRX)) { // Hvis køen ikke er fuld - Hvis der er en plads til at modtage en besked
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &CanRxHeader, buffer); // Modtag beskeden og læg den i buffer
placeData_1(buffer);
/*
for(int i = 0; i < PACKAGE_SIZE; i++){
EnterQueue(&queueCANRX, buffer[i]); // Læg buffer ind i modtager-queuen
}*/
}
}
}
void placeData_1(uint8_t *p){
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_CAN1_Init();
MX_I2C1_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
NVIC_SetPriorityGrouping( NVIC_PRIORITYGROUP_4 ); //NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
//NVIC_SetPriorityGrouping( 0 );
HAL_CAN_Start(&hcan1);
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of taskGPS */
taskGPSHandle = osThreadNew(task_gps, NULL, &taskGPS_attributes);
/* creation of taskDCMotor */
taskDCMotorHandle = osThreadNew(task_dcmotor, NULL, &taskDCMotor_attributes);
/* creation of taskMpu6050 */
taskMpu6050Handle = osThreadNew(task_mpu6050, NULL, &taskMpu6050_attributes);
/* creation of taskParTcl */
taskParTclHandle = osThreadNew(task_partcl, NULL, &taskParTcl_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
gps_init(&huart1, hdma_usart1_rx.Instance);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 36;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Enable MSI Auto calibration
*/
HAL_RCCEx_EnableMSIPLLMode();
}
/**
* #brief CAN1 Initialization Function
* #param None
* #retval None
*/
static void MX_CAN1_Init(void)
{
/* USER CODE BEGIN CAN1_Init 0 */
uint32_t ext_id = 0x00000000; // Den største værdi der kan være på MSB er 1
uint32_t mask = 0xFFFFFFE0;
CanFilter.FilterMode = CAN_FILTERMODE_IDMASK; // Vi vælger at bruge mask mode
CanFilter.FilterIdHigh = (ext_id & 0x1FFFFFFF) >> 13; // (ext_id << 3) >> 16; // Da vi har 32 bit ID, er dette de 16 MSB af ID
CanFilter.FilterIdLow = (ext_id << 3) | CAN_ID_EXT; // Da vi har 32 bit ID, er dette de 16 LSB af ID
CanFilter.FilterMaskIdHigh = (mask & 0x1FFFFFFF) >> 13;// << 5; // Maskens 16 MSB
CanFilter.FilterMaskIdLow = (mask << 3);// << 5 | 0x10; // Maskens 16 LSB
CanFilter.FilterScale = CAN_FILTERSCALE_32BIT; // ID er et 32 bit-tal
CanFilter.FilterActivation = ENABLE; // Vi aktiverer filteret
CanFilter.FilterBank = 0; // Vi vælger filter 0 ud af 14 mulige filtre
CanFilter.FilterFIFOAssignment = CAN_FILTER_FIFO0; // Vi vælger FIFO0 til forskel for FIFO1
CanTxHeader.DLC = PACKAGE_SIZE; // Der kommer 8 byte som data i beskeden
CanTxHeader.ExtId = 0x00000000; // 32 bit ID (29 er identifier)
CanTxHeader.IDE = CAN_ID_EXT; // Vi har et extended ID = 32 bit til forskel fra standard på 16 bit (11 er identifier)
CanTxHeader.RTR = CAN_RTR_DATA; // Vi sender data
CanTxHeader.TransmitGlobalTime = DISABLE; // Der skal IKKE sendes et timestamp med hver besked
CanRxHeader.DLC = PACKAGE_SIZE;
CanRxHeader.ExtId = 0x0;
CanRxHeader.IDE = CAN_ID_EXT;
CanRxHeader.RTR = CAN_RTR_DATA;
CanRxHeader.FilterMatchIndex = 0x00;
/* USER CODE END CAN1_Init 0 */
/* USER CODE BEGIN CAN1_Init 1 */
/* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 18;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_7TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_8TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = ENABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN1_Init 2 */
while (HAL_CAN_ConfigFilter(&hcan1, &CanFilter) != HAL_OK) {}
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_Start(&hcan1);
/* USER CODE END CAN1_Init 2 */
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x10808DD3;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* #brief TIM2 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 5000;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/**
* #brief USART1 Initialization Function
* #param None
* #retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PA0 PA1 PA2 PA3
PA4 PA5 PA6 PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PA8 */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : LD3_Pin */
GPIO_InitStruct.Pin = LD3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD3_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PH3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/* USER CODE BEGIN Header_task_gps */
/**
* #brief Function implementing the taskGPS thread.
* #param argument: Not used
* #retval None
*/
/* USER CODE END Header_task_gps */
void task_gps(void *argument)
{
/* USER CODE BEGIN 5 */
gps_init(&huart1, hdma_usart1_rx.Instance);
/* Infinite loop */
for (;;) {
//sendGPS(&hcan1, &CanTxHeader);
//int8_t result = readGPS(&data);
osDelay(1000);
}
osThreadTerminate(NULL);
/* USER CODE END 5 */
}
/* USER CODE BEGIN Header_task_dcmotor */
/**
* #brief Function implementing the taskDCMotor thread.
* #param argument: Not used
* #retval None
*/
/* USER CODE END Header_task_dcmotor */
void task_dcmotor(void *argument)
{
/* USER CODE BEGIN task_dcmotor */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END task_dcmotor */
}
/* USER CODE BEGIN Header_task_mpu6050 */
/**
* #brief Function implementing the taskMpu6050 thread.
* #param argument: Not used
* #retval None
*/
/* USER CODE END Header_task_mpu6050 */
void task_mpu6050(void *argument)
{
/* USER CODE BEGIN task_mpu6050 */
HAL_StatusTypeDef status = MPU_Init(&hi2c1);
/* Infinite loop */
for (;;) {
float temp = MPU_Read_Temp();
Axes3 accel = MPU_Read_Accel();
Axes3 gyro = MPU_Read_Gyro();
osDelay(900);
}
/* USER CODE END task_mpu6050 */
}
/* USER CODE BEGIN Header_task_partcl */
/**
* #brief Function implementing the taskParTcl thread.
* #param argument: Not used
* #retval None
*/
/* USER CODE END Header_task_partcl */
void task_partcl(void *argument)
{
/* USER CODE BEGIN task_partcl */
partcl_init();
/* Infinite loop */
for(;;)
{
//partcl_update();
osDelay(1);
}
/* USER CODE END task_partcl */
}
/**
* #brief Period elapsed callback in non blocking mode
* #note This function is called when TIM7 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* #param htim : TIM handle
* #retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
Nucleo NOT running FreeRTOS:
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "circle_queue.h"
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PACKAGE_SIZE 8
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
CAN_FilterTypeDef CanFilter;
CAN_RxHeaderTypeDef CanRxHeader;
CAN_TxHeaderTypeDef CanTxHeader;
struct Queue queueCANRX ={0,0,{0}};
//GPS DATA ID'S
uint32_t GPS_ID1 = 0x1;
uint32_t GPS_ID2 = 0x2;
uint32_t GPS_ID3 = 0x3;
uint32_t GPS_ID4 = 0x4;
// Recieved GPS data from CubeSAT
float GPS_LAT = 0.;
char GPS_LAT_DIR = '$';
float GPS_LON = 0.;
char GPS_LON_DIR = '$';
uint8_t GPS_QUALITY = 0;
uint8_t GPS_HOURS = 0;
uint8_t GPS_MINUTES = 0;
uint8_t GPS_SEC = 0;
float GPS_HDOP = 0;
float GPS_ALTITUDE = 0.;
float GPS_H_GEOID = 0;
//Recieved MPU data from CubeSAT
float MPU_ACCELX = 0.;
float MPU_ACCELY = 0.;
float MPU_ACCELZ = 0.;
float MPU_GYROX = 0.;
float MPU_GYROY = 0.;
float MPU_GYROZ = 0.;
float MPU_TEMP = 0.;
//Recieved MOTOR data from CubeSAT
uint8_t MOTOR_DUTYCYCLE = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_CAN1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t sendDataArray[PACKAGE_SIZE] = {2, 2, 2, 2, 2, 2, 2, 2};
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 36;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Enable MSI Auto calibration
*/
HAL_RCCEx_EnableMSIPLLMode();
}
/**
* #brief CAN1 Initialization Function
* #param None
* #retval None
*/
static void MX_CAN1_Init(void)
{
/* USER CODE BEGIN CAN1_Init 0 */
uint32_t ext_id = 0x00000000; // Den største værdi der kan være på MSB er 1
uint32_t mask = 0xFFFFFFE0;
CanFilter.FilterMode = CAN_FILTERMODE_IDMASK; // Vi vælger at bruge mask mode
CanFilter.FilterIdHigh = (ext_id & 0x1FFFFFFF) >> 13; // (ext_id << 3) >> 16; // Da vi har 32 bit ID, er dette de 16 MSB af ID
CanFilter.FilterIdLow = (ext_id << 3) | CAN_ID_EXT; // Da vi har 32 bit ID, er dette de 16 LSB af ID
CanFilter.FilterMaskIdHigh = (mask & 0x1FFFFFFF) >> 13;// << 5; // Maskens 16 MSB
CanFilter.FilterMaskIdLow = (mask << 3);// << 5 | 0x10; // Maskens 16 LSB
CanFilter.FilterScale = CAN_FILTERSCALE_32BIT; // ID er et 32 bit-tal
CanFilter.FilterActivation = ENABLE; // Vi aktiverer filteret
CanFilter.FilterBank = 0; // Vi vælger filter 0 ud af 14 mulige filtre
CanFilter.FilterFIFOAssignment = CAN_FILTER_FIFO0; // Vi vælger FIFO0 til forskel for FIFO1
CanRxHeader.DLC = PACKAGE_SIZE;
CanRxHeader.ExtId = 0x0;
CanRxHeader.IDE = CAN_ID_EXT;
CanRxHeader.RTR = CAN_RTR_DATA;
CanRxHeader.FilterMatchIndex = 0x00;
CanTxHeader.DLC = PACKAGE_SIZE; // Der kommer 8 byte som data i beskeden
CanTxHeader.ExtId = 0x00000000; // 32 bit ID (29 er identifier)
CanTxHeader.IDE = CAN_ID_EXT; // Vi har et extended ID = 32 bit til forskel fra standard på 16 bit (11 er identifier)
CanTxHeader.RTR = CAN_RTR_DATA; // Vi sender data
CanTxHeader.TransmitGlobalTime = DISABLE; // Der skal IKKE sendes et timestamp med hver besked
/* USER CODE END CAN1_Init 0 */
/* USER CODE BEGIN CAN1_Init 1 */
__HAL_RCC_CAN1_CLK_ENABLE();
/* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 18;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_7TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_8TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = ENABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN1_Init 2 */
while (HAL_CAN_ConfigFilter(&hcan1, &CanFilter) != HAL_OK) {}
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_Start(&hcan1);
/* USER CODE END CAN1_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|LD3_Pin|GPIO_PIN_7, GPIO_PIN_RESET);
/*Configure GPIO pin : PA6 */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 LD3_Pin PB7 */
GPIO_InitStruct.Pin = GPIO_PIN_0|LD3_Pin|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PB6 */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void receiveData() {
uint8_t buffer[PACKAGE_SIZE] = {0};
while (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) > 0) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
if (!QueueFull(&queueCANRX)) { // Hvis køen ikke er fuld - Hvis der er en plads til at modtage en besked
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &CanRxHeader, buffer); // Modtag beskeden og læg den i buffer
placeData_1(buffer);
/*
for(int i = 0; i < PACKAGE_SIZE; i++){
EnterQueue(&queueCANRX, buffer[i]); // Læg buffer ind i modtager-queuen
}*/
}
}
}
void transmitData(struct Queue *Data)
{
int writePointer = Data -> pointWR;
int readPointer = Data -> pointRD;
char str[3] = {0};
uint8_t tempo = 0;
int bytesToRead = writePointer - readPointer;
for (int i = 0 ; i < bytesToRead ; i++){
if ((i % 255) == 0) HAL_UART_Transmit(&huart2, "___", 3, 100);
LeaveQueue(Data, &tempo);
sprintf(str, "%d", tempo);
HAL_UART_Transmit(&huart2, &str, strlen(str), 100);
}
}
/* USER CODE END 4 */
I am using a STM32F103. I am trying to dynamically enable and disable a DMA transfer and a PWM signal, which are controlled by a timer. The timer is very unstable, and the result changes from reboot to reboot. The code runs the function CAM_startLineTransfer() which should enable the DMA transfer and PWM signal.
void CAM_startLineTransfer(CAM_HandleTypeDef *cam) {
// init DMA
while (cam->requestDataTimer->Instance->CNT <= 60) {}
HAL_TIM_PWM_Start(cam->requestDataTimer, cam->requestDataChannel);
HAL_TIM_OC_Start(cam->DMATimer, cam->DMAChannel);
__HAL_DMA_DISABLE_IT(cam->hdma, DMA_IT_HT);
cam->status = RECEIVING;
}
When the DMA has transferred 640 bytes, an interrupt should be triggered.
void DMA1_Channel1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_tim2_ch3);
CAM_stopLineTransfer(&hcam);
transmitBuffer();
}
The function CAM_stopLineTransfer() should disable the DMA and the PWM signal, but NOT the timer itself. The timer should keep counting.
void CAM_stopLineTransfer(CAM_HandleTypeDef *cam) {
// abort DMA
HAL_TIM_OC_Stop(cam->DMATimer, cam->DMAChannel);
while (cam->requestDataTimer->Instance->CNT <= 60) {}
HAL_TIM_PWM_Stop(cam->requestDataTimer, cam->requestDataChannel);
cam->status = WAITING;
}
However, the timer is very unstable, and sometimes the entire timer is disabled, sometimes the interrupt is not called. What is happening? Here, the entire main program is.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "camera.h"
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim2;
DMA_HandleTypeDef hdma_tim2_ch3;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
CAM_HandleTypeDef hcam;
uint8_t cameraData[640] = {10};
Picture pic1;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void CAM_Handle_Init(CAM_HandleTypeDef *cam);
/* USER CODE END PFP */
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
CAM_Handle_Init(&hcam);
CAM_init(&hcam);
HAL_TIM_OC_Start_DMA(&htim2, TIM_CHANNEL_3, &(GPIOA->IDR), hcam.pic->width);
CAM_getReg(&hcam, 0x12);
CAM_getReg(&hcam, 0x1E);
CAM_getReg(&hcam, 0x13);
CAM_getReg(&hcam, 0x3F);
CAM_getReg(&hcam, 0x71);
for (int i = 0; i < 10; i++) {
CAM_takePicture(&hcam);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
CAM_update(&hcam);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* #brief TIM2 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 6-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 120 -1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM2;
sConfigOC.Pulse = 60;
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
HAL_TIM_OC_MspInit(&htim2);
HAL_TIM_PWM_MspInit(&htim2);
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/**
* #brief USART1 Initialization Function
* #param None
* #retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
/*Configure GPIO pin : PC14 */
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB10 PB11
PB12 PB13 PB14 PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PB4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void CAM_Handle_Init(CAM_HandleTypeDef *cam) {
cam->I2C_Address = 0x21;
cam->destination = cameraData;
cam->hdma = &hdma_tim2_ch3;
cam->pic = &pic1;
cam->requestDataTimer = &htim2;
cam->requestDataChannel = TIM_CHANNEL_2;
cam->DMATimer = &htim2;
cam->DMAChannel = TIM_CHANNEL_3;
cam->source = &(GPIOA->IDR);
cam->status = STANDBY;
cam->I2C_Handler = &hi2c1;
cam->pic->x = 0;
cam->pic->y = 0;
cam->pic->height = 480;
cam->pic->width = 640;
}
void transmitBuffer() {
HAL_UART_Transmit(&huart1, cameraData, 640, HAL_MAX_DELAY);
}
/* USER CODE END 4 */
I just saw that you used DMA_Channel instead of Timer_Channel:
HAL_TIM_OC_Start(cam->DMATimer, cam->DMAChannel);