I am trying to use timer peripheral in STM32L073 but i have problems.
I've generated setup code in STM32Cube and using only functions that HAL API provides. Problem is that timer interrupt occurs only once and it should occur always then it overflows. I don't know if timer is even running or my setup is wrong (which I believe it shouldn't be since I am using Cube generated code). Anyone can help?
This is called in main before while loop
void MX_TIM7_Init(void){
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim7.Instance = TIM7;
htim7.Init.Prescaler = 00;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 00;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK) {
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK){
_Error_Handler(__FILE__, __LINE__);
}
}
BaseMspInit Method
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle){
if(tim_baseHandle->Instance==TIM7){
/* USER CODE BEGIN TIM7_MspInit 0 */
/* USER CODE END TIM7_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM7_CLK_ENABLE();
/* TIM7 interrupt Init */
HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
/* USER CODE BEGIN TIM7_MspInit 1 */
/* USER CODE END TIM7_MspInit 1 */
}
}
Then in main I call this
HAL_TIM_Base_Start_IT(&htim7);
which is doing this
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim){
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
/* Enable the Peripheral */
__HAL_TIM_ENABLE(htim);
/* Return function status */
return HAL_OK;
}
and my Interrupt handler calls PeriodElapsedCallback
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
HAL_GPIO_TogglePin(led_GPIO_Port, led_Pin);
}
It compiles there are no errors no warning, in debugger I see this interrupt is triggered only once and then never. Looking forward for answers
P.S. using SEGGER Embedded Studio
Your overflow happens every clock as you did not set ARR
Firstly you need to set these parameters to your destination period
Prescaler for the clock source (check the which bus):
htim7.Init.Prescaler = 00;
How much timer needs to count for ISR occurs:
htim7.Init.Period = 00;
Related
I'm using STM32MP157A-DK1 Discovery kit with STM32MP157A MPU.
My problem is that when I terminate the debug and launch again my code stop in void HardFault_Handler(void); (in stm32mp1xx_it.c). The first debugging time works ok, the problem was in the second debug.
I tried removing HAL_TIM_Base_Start_IT(&htim14); and the problem stopped, but I need the timer. Also tried switching timers and the others also give me the same debugging problem.
I checked the hardware configuration (.ioc file) and it's all in default values except the timers that I'm using.
int main(void) {
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
if(IS_ENGINEERING_BOOT_MODE()){
/* Configure the system clock */
SystemClock_Config();
}
if(IS_ENGINEERING_BOOT_MODE()){
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
}else{
/* IPCC initialisation */
MX_IPCC_Init();
/* OpenAmp initialisation ---------------------------------*/
MX_OPENAMP_Init(RPMSG_REMOTE, NULL);
}
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM14_Init();
/* USER CODE BEGIN 2 */
/*
* Create Virtual UART device
* defined by a rpmsg channel attached to the remote device
*/
log_info("Virtual UART0 OpenAMP-rpmsg channel creation\r\n");
if(VIRT_UART_Init(&huart0) != VIRT_UART_OK){
log_err("VIRT_UART_Init UART0 failed.\r\n");
Error_Handler();
}
log_info("Virtual UART1 OpenAMP-rpmsg channel creation\r\n");
if(VIRT_UART_Init(&huart1) != VIRT_UART_OK){
log_err("VIRT_UART_Init UART1 failed.\r\n");
Error_Handler();
}
//Need to register callback for message reception by channels
if(VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK){ Error_Handler();}
if(VIRT_UART_RegisterCallback(&huart1, VIRT_UART_RXCPLT_CB_ID, VIRT_UART1_RxCpltCallback) != VIRT_UART_OK){ Error_Handler();}
HAL_TIM_Base_Start_IT(&htim14); //Here is the trouble maker
while(1){
OPENAMP_check_for_message();
}
}
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim == &htim14){
//do something
}
}
void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart) {
//log_info("Msg received on VIRTUAL UART0 channel: %s \n\r", (char*) huart->pRxBuffPtr);
}
void VIRT_UART1_RxCpltCallback(VIRT_UART_HandleTypeDef *huart) {
log_info("Msg received on VIRTUAL UART1 channel: %s \n\r", (char*) huart->pRxBuffPtr);
}
I'm using Windows 10, STM32CubeIDE (Version: 1.8.0, Build: 11526_20211125_0815 (UTC)), STM32CubeMX (Version: 6.4.0-RC4, Build: 20211122-2105 (UTC)).
I just put
TIM14->DIER &= ~(TIM_IT_UPDATE);
TIM14->CR1 &= ~(TIM_CR1_CEN);
before call timer initialization
MX_TIM14_Init();
The problem was in Production Mode the A7 core controls all M4's peripherical, so it only reset the interruption when I reset the core A7. This code I use turn off the interrupt to prevent a interrupt call before initialization. You must call it for every peripheric interrupt (check how to disable it, for timers just change the TIM number. Ex: TIM3, TIM17, ...)
Don't know if it's the best way, it's working until now though.
Final main() code:
int main(void) {
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
if(IS_ENGINEERING_BOOT_MODE()){
/* Configure the system clock */
SystemClock_Config();
}
if(IS_ENGINEERING_BOOT_MODE()){
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
}else{
/* IPCC initialisation */
MX_IPCC_Init();
/* OpenAmp initialisation ---------------------------------*/
MX_OPENAMP_Init(RPMSG_REMOTE, NULL);
}
/* USER CODE BEGIN SysInit */
TIM14->DIER &= ~(TIM_IT_UPDATE);
TIM14->CR1 &= ~(TIM_CR1_CEN);
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM14_Init();
/* USER CODE BEGIN 2 */
/*
* Create Virtual UART device
* defined by a rpmsg channel attached to the remote device
*/
log_info("Virtual UART0 OpenAMP-rpmsg channel creation\r\n");
if(VIRT_UART_Init(&huart0) != VIRT_UART_OK){
log_err("VIRT_UART_Init UART0 failed.\r\n");
Error_Handler();
}
log_info("Virtual UART1 OpenAMP-rpmsg channel creation\r\n");
if(VIRT_UART_Init(&huart1) != VIRT_UART_OK){
log_err("VIRT_UART_Init UART1 failed.\r\n");
Error_Handler();
}
//Need to register callback for message reception by channels
if(VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK){ Error_Handler();}
if(VIRT_UART_RegisterCallback(&huart1, VIRT_UART_RXCPLT_CB_ID, VIRT_UART1_RxCpltCallback) != VIRT_UART_OK){ Error_Handler();}
HAL_TIM_Base_Start_IT(&htim14); //Here is the trouble maker
while(1){
OPENAMP_check_for_message();
}
}
I am trying to interface a 'STM32F401RET6 Nucleo-64' microcontroller with an Adafruit I2S microphone in a mono setup. To accomplish this task, I would like to have DMA enabled.
I used the Device Configuration Tool in STM32 Cube IDE to activate I2S3 using the following parameters:
I2S3
Full Duplex Master
Transmission mode: Mode Master Receive;
Communication standard: MSB First (Left Justified);
Data and Frame Format: 24 Bits Data on 32 Bits Frame;
Selected Audio Frequency: 48 kHz;
Clock Source: I2S PLL Clock;
Clock Polarity: Low;
Master clock output disabled.
DMA
SPI_RX3, DMA 1 Stream 2, Peripheral to Memory, High Priority;
FIFO, Threshold = Full, Data Width = Half Word, Burst Size = Single;
In the NVIC settings, interrupts are enabled for both DMA 1 Stream 2 and SPI3.
Next, the Code Generator Tool was used to automatically generate starting code. Some changes were made to this starting code:
Set GPIO_PULL_DOWN so that tri-state always reads in 0;
I already used an oscilloscope to plot the digital data waveform coming from the microphone. This seemed to be correct, i.e., sound triggered the microphone and this was visible in the most significant bits. This makes that the error is in reading in the data into the correct format, if I'm correct.
To perform mono measurements, the datasheet states that one should use a 100k Ohm resistor, which is present in my setup.
In my main.c program, I'm using the HAL function 'HAL_I2S_Receive_DMA' to try to fill my array of 500 samples.
main.c:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
I2S_HandleTypeDef hi2s3;
DMA_HandleTypeDef hdma_spi3_rx;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2S3_Init(void);
static void MX_DMA_Init(void);
int main(void)
{
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2S3_Init();
MX_DMA_Init();
/* Infinite loop */
HAL_StatusTypeDef retval; // return value
volatile int16_t data[500] = {0};
int16_t data_shifted[500];
while (1)
{
retval = HAL_I2S_Receive_DMA(&hi2s3, data, 500);
// for(short i=0; i<500; i++){
// data_shifted[i] = data[i] >> 14;
// }
HAL_Delay(1000);
}
}
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_SCALE2);
/* Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 84;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
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();
}
}
static void MX_I2S3_Init(void)
{
hi2s3.Instance = SPI3;
hi2s3.Init.Mode = I2S_MODE_MASTER_RX;
hi2s3.Init.Standard = I2S_STANDARD_MSB;
hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K;
hi2s3.Init.CPOL = I2S_CPOL_LOW;
hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
if (HAL_I2S_Init(&hi2s3) != HAL_OK)
{
Error_Handler();
}
}
// Enable DMA controller clock
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
}
/*GPIO Initialization Function */
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
}
/* This function is executed in case of error occurrence. */
void Error_Handler(void)
{
/* Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/**
Reports the name of the source file and the source line number
where the assert_param error has occurred.
*/
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) */
}
#endif /* USE_FULL_ASSERT */
When I debug my code and put a breakpoint on line 34 in 'main.c', then the microcontroller memory does not update its values accordingly. All values stay equal to zero. Both DMA Status Flags are set to 1.
I guessing that the problem has something to do with timings, but I wasn't able to solve this problem until now.
Link to complete source code on GitHub
Link to HAL_I2S_Receive_DMA function on GitHub
Thanks in advance.
DMA must be initialized before ADC peripheral, but generated code performs initialization in wrong order. It is well known minor flaw in default configuration of current STM32CubeIDE. Try to change
MX_GPIO_Init();
MX_I2S3_Init();
MX_DMA_Init(); // wrong order
to
MX_GPIO_Init();
MX_DMA_Init(); // right order
MX_I2S3_Init();
To make permanent changes,
Open "Project Manager" (tab near Pinout / Clock Configuration)
Project Manager → Advanced Settings → Generated Function Calls
Use tiny arrow buttons near this list to move MX_DMA_Init() above
MX_I2S3_Init()
Save the project, generated code will have correct order
for my experience,
HAL_I2S_Receive_DMA() function is to configure the address
(if you learn the LL API, you need manually set source/dest address and length of data: [LL_DMA_SetDataLength()])
So, you can move it before While(1) loop.
if you want to read/process the buffer "data", you can use dma interrupt callback function, in HAL API is : HAL_I2S_RxHalfCpltCallback(), HAL_I2S_RxCpltCallback()
=====================================================================
update:
// init method and buff
...
xx_init()
volatile int16_t data[500] = {0};
int16_t data_shifted[500];
...
//
HAL_I2S_Receive_DMA(&hi2s3, &data[0], 250);
while(1){
if (FLAG_half){
FLAG_half=0;
// add your code: data shift [0:250]...
}
if (FLAG_comp){
FLAG_comp=0;
// add your code: data shift [250:500]...
}
} // end while
} end main
HAL_I2S_RxHalfCpltCallback(){
FLAG_half=1;
}
HAL_I2S_RxCpltCallback(){
FLAG_comp=1;
}
I am using a STM32F103 chip and I am trying to configure and use one of the timers. I have used STM32CubeMX to generation code which initializes Timer 2. I start the timer by calling HAL_TIM_Base_Start. Then, in a loop, I print out the current timer value via a call to htim2.Instance->CNT, or alternately by calling the macro __HAL_TIM_GetCounter (which I believe just returns the same value). However, no matter what I do, the count value shows up as zero. I have also tried calling __TIM2_CLK_ENABLE() at the beginning, but it makes no difference.
I have searched for a solution and have found a couple of questions about this issue, but have not found the solution.
Does anyone know what I am doing wrong?
Thanks.
Here is the routine that initializes the timer. This code was generated by STM32CubeMX and I have not modified it:
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
Then in the main I attempt to start the timer and attempt to print out it's value. This is the code that I use to do that:
__TIM2_CLK_ENABLE();;
HAL_TIM_Base_Start(&htim2);
while (true)
{
Serial.println((long) __HAL_TIM_GetCounter(&htim2));
delay(100);
}
The 'Serial' class is a class that I wrote which communicates with my PC via a USB serial port.
Try it without HAL, it's not complicated.
void start_TIM2() {
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->CR1 |= TIM_CR1_EN;
}
uint16_t read_TIM2() {
return TIM2->CNT;
}
Setting the value of
htim2.Init.Period = 0;
zero initializes the auto reload register (ARR) not a very handy default choice of cubeMX, you probably want an ARR value of 0xFFFFFFFF
The accepted answer relies on the ARR value after reset of 0xFFFFFFFF without mentioning it, more luck than wisdom if you ask me
The ARR (htim2.Init.Period) shouldn't be 0. It will try to count uptil...0! Put some 16 bit integer there. Good Luck!
I will show you some formulas to keep in mind: (refer: AN4776)
. Frequency = Fclk(timer) / (prescaler + 1)
For example, you chose prescaler = 0, it implies that your timer finishes counting [0: count) in a period of 1 / 80MHz, in case the SystemClock is configured like this (you should check the value of the clock and the prescaler to determine the Update frequency).
. #1_count(s) = 1 / Frequency
. period(s) = #1_count * (counter + 1)
--> Let's see it with an example:
SystemClock = 72MHz, requires a 1us resolution timer and a 1ms period.
. for a 1us of resolution -> Frequency = 1Mhz
'1MHz = 72MHz / (prescaler + 1)' -> prescaler = 71
. so that the timer interrupts every one millisecond we must calculate how much it should count:
'1ms = 1us * (counter + 1)' -> count = 999
with these values we configure the following:
htim2.Init.Prescaler = 71;
htim2.Init.Period = 999;
where the timer will count from 0: 999 in steps of 1uS.
Your code has two problems, the timer frequency is too high and it only counts from 0: 1, so you will never be able to see the increase in counts.
The code below uses the capture compare feature of TIM1 channel 3 to capture rising edge on PE10, but its not working, the interrupt handler its not called. I am not that good at this embedded stuff, so can somebody tell me if I am settings this correctly ?
#include "STM32/stm32f4xx_tim.h"
void TIM1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
/* TIM1 channel 3 pin (PE.10) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Connect TIM pins to AF2 */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_TIM1);
/* Enable the TIM1 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM1, &TIM_ICInitStructure);
/* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
/* Enable the CC3 Interrupt Request */
TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);
}
void TIM1_CC_IRQHandler(void)
{
// .................
}
int StartCapture()
{
TIM1_Config();
while(1); /* Infinite loop */
}
If your TIM1_CC_IRQHandler() is getting called ONCE, then Dracog71's answer is correct. However, if your IRQHandler() is never firing, then there's something wrong in the initialization.
Here's a list of things you have to get right or the IRQ won't fire.
1) Make sure that the GPIO[A:E] clock is enabled for the pin you are using.
2) Likewise, make sure the clock is enabled for the TIMx you are using. Check where your TIMx lives. If you call RCC_APB2PeriphClockCmd() for a timer that lives on APB1, the compiler won't throw an error, but your timer will never work.
3) Double-check your pin's AF matches the datasheet's Alternative Function Mapping table (eg. AF1 == TIM1_CH3).
4) In your TIM_ICInitStructure, make sure TIM_Channel matches the channel you have chosen (in your case TIM_Channel_3).
5) Configure and enable the correct IRQ channel in the NVIC, eg. NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
6) Enable the interrupt: TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);
7) Enable your timer: TIM_Cmd(TIM1, ENABLE);
Well, I guess my answer isn't required after 6 years. But maybe somebody else facing same problem will find it.
There may be a name conflict if you write in c++. If original prototype of interupt function is defined like C-function, and your implementation is C++function so it's just two different functions with the same name, and interupt will try to call an empty C-function or even may stack in endless loop. So that is why your c++ function may be newer called.
To solve this, just define your function like extern "C".
Maybe the interrupt enters the functions but does not know what to do, or enter ant he flag is still active and just enters once, you're missing the clear interrupt flag, try this:
/**
* #brief Capture Compare Handler
* #param None
* #retval None
*/
void TIM1_CC_IRQHandler()
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET) <-- Add this
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC3); <-- This is important!
//TODO
}
}
I generated my code from STM32CubeMx and wanted to generate a update event every 1µs. I work with the internal clock at 48MHz, which should be with Prescaler:0 and Autoreload:47 result to 1µs.
I use a STM32F030 with TrueStudio V.9.0.0
generated code
/* TIM17 init function */
static void MX_TIM17_Init(void)
{
LL_TIM_InitTypeDef TIM_InitStruct;
/* Peripheral clock enable */
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM17);
/* TIM17 interrupt Init */
NVIC_SetPriority(TIM17_IRQn, 3);
NVIC_EnableIRQ(TIM17_IRQn);
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 47;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
LL_TIM_Init(TIM17, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM17);
}
I added in my init:
LL_TIM_EnableIT_UPDATE(TIM17);
LL_TIM_EnableCounter(TIM17);
In the IRQ_Handler i toggle a PIN:
void TIM17_IRQHandler(void)
{
/* USER CODE BEGIN TIM17_IRQn 0 */
LL_GPIO_TogglePin(LED_D2_2_GPIO_Port,LED_D2_2_Pin);
/* USER CODE END TIM17_IRQn 0 */
/* USER CODE BEGIN TIM17_IRQn 1 */
/* USER CODE END TIM17_IRQn 1 */
}
After flashing my device with the code it generates a Signal with Frequency 889kHz with Pulsewidth of 564ns measured with Oscilloscope. Changes on Prescaler or Autoreload does not affect this output, it stays right away at T_Pulse=564ns or F=889kHz.
Any idea what I am missing here?
Register output from debugging:
CR1:0x81 CR2:0
DIER:0x01 SR:0x03
CCMR1_O/I:0 CCER:0
PSC:0 ARR:0x2f
RCR:0 CCR1:0
BDTR:0 DCR:0
DMAR:0x81
The solution was the clearance of the FLAG UIE in TIM17->SR in the IRQ_Handler.
I was stuck permanently in the IRQ routine.