22.08.2016, 15:00
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
STM32F103C8T6 Таймер и прерывание по окончании счета
Добрый день!
Хочу запустить таймер с автоматическим перезапуском и выдачей прерывания по окончании счета. Никак не могу получить прерывание. Только начинаю разбираться опыта пока еще ноль. Курение даташита (с моим уровнем английского) не привело ни к какому выводу. Методом тыка попробовал менять параметры, не помогло. Попробовал на основании кода по ШИМ из русскоязычной статьи, но подозреваю что между моментом окончания счета и началом нового цикла должно пройти какое то время, у меня оно равно нулю.
Код:
|
RCC-›APB1ENR |= RCC_APB1ENR_TIM4EN;//разрешить тактирование таймера от внутренней шины
TIM2-›PSC = 8-1; //коффициент предделителя 8000000/8=1000000 Гц (1МГц)
TIM2-›ARR = 1000-1; //счетчик до 1000 тактов
TIM2-›CCMR1 =0x00000068; //устанавливаем режим ШИМ
TIM2-›CCR1 = 0x00000001; //задаем стартовое значение ШИМ
TIM2-›CCER = 0x00000101; //разрешаем выход канала 1
TIM2-›DIER = 0x00000011; //разрешаем обновление прерывания
TIM2-›EGR = 0x00000001; //разрешаем обновление
TIM2-›CNT = 0x00000000; //какой то регистр без которого возмжно не сработает прерывание
TIM2-›CR1 = 0x00000086;
NVIC_SetPriority (TIM2_IRQn,15); //назначаем прерывание
NVIC_EnableIRQ (TIM2_IRQn); //включаем прерывание
TIM2-›CR1 |= 0x00000001; //включаем работу таймера
void TIM2_IRQHandler(void)
{
//TIM2-›CR1 = 0x00000000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
//TIM2-›CR1 = 0x00000001;
} |
|
|
|
|
22.08.2016, 15:28
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
Каламбур какой-то. Включаете тактирование четвертого таймера, конфигурируете второй, а флаг прерывания не сбрасываете. Зачем вам шим? Вам только базовый функционал нужен - чтобы CNT инкременировался.
|
|
|
|
22.08.2016, 15:34
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
Спасибо!
Поправил на тактирование 2-го
RCC-›APB1ENR |= RCC_APB1ENR_TIM2EN;
а каким регистром сбрасывать флаг прерывания?... а так понимаю его надо сбрасывать в теле функции TIM2_IRQHandler()?
В мануале прочитал что режим с автоперезапуском возможен в режиме ШИМ. Поэтому так и перекопипастил
|
|
|
|
22.08.2016, 15:46
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
У вас дебаг работает? Посмотрите в дебаге, значение CNT увеличивается? В прерывание вы попадаете?
Для кучи спрошу, а тактирование порта включено? Пин на выход настроен?
Последний раз редактировалось Easyrider83; 22.08.2016 в 15:49.
|
|
|
Сказали "Спасибо" Easyrider83
|
|
|
22.08.2016, 15:54
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
Как то странно получается... Нашел несколько ошибок, исправил,
TIM2-›PSC = 80-1; //коффициент предделителя увеличил в 10 раз.
и дебагом начал смотреть и наблюдать следующее...
1. при переходе на строчку
NVIC_SetPriority (TIM2_IRQn,15);
программа сразу сваливается в функцию TIM2_IRQHandler() при этом CNT=0, отрабатывает её код и возвращается обратно,
2. доходит до строки TIM2-›CR1 |= 0x00000001; CNT становится больше нуля и программа снова уходит в прерывание TIM2_IRQHandler().
Для наглядности ниже весь код программы:
Код:
|
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "core_cm3.h"
#include "stdint.h"
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
GPIO_InitTypeDef GPIO_InitStructure;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint16_t ADC_Res[6];
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
void TIM2_IRQHandler(void);
int main(void)
{
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
//int t=500000;
while (1)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
for(int i=0;i‹10000;i++);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
for(int i=0;i‹10000;i++);
}
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
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();
}
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();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Инициализация портов А как вход АЦП PA0-PA5*/
GPIO_InitStructure.Pin = (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
/*Инициализация порта PB1 как выход для включения светодиода*/
GPIO_InitStructure.Pin = (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
/*
* настройка TIM3. Выход триггера при обновлении таймера
*/
RCC-›APB1ENR |= RCC_APB1ENR_TIM3EN;
TIM3-›PSC = 80; //коффициент предделителя (был 80)
TIM3-›ARR = 1; //период обновления 1 мс (был 100-1)
TIM3-›CR2 |= TIM_CR2_MMS_1; //выход триггера при обновлении таймера
RCC-›APB1ENR |= RCC_APB1ENR_TIM2EN; //разрешить тактирование таймера от внутренней шины
TIM2-›PSC = 80-1; //коффициент предделителя 8000000/8=1000000 Гц (1МГц)
TIM2-›ARR = 1000-1; //счетчик до 1000 тактов
TIM2-›CCMR1 =0x00000068; //устанавливаем режим ШИМ
TIM2-›CCR1 = 0x00000001; //задаем стартовое значение ШИМ
TIM2-›CCER = 0x00000101; //разрешаем выход канала 1
TIM2-›DIER = 0x00000011; //разрешаем обновление прерывания
TIM2-›EGR = 0x00000001; //разрешаем обновление
TIM2-›CNT = 0x00000000; //если ›0 то сработало прерывание
TIM2-›CR1 = 0x00000086;
NVIC_SetPriority (TIM2_IRQn,15); //назначаем прерывание
NVIC_EnableIRQ (TIM2_IRQn); //включаем прерывание
TIM2-›CR1 |= 0x00000001; //включаем работу таймера
//TIM2-›CR2 |= TIM_CR2_MMS_1; //выход триггера при обновлении таймера
//TIM2-›DIER |= TIM_DIER_UIE; // разрешение генерации события по достижении значения TIM2-›ARR = 1000
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
/*Инициализация порта PB1 как выход для включения светодиода*/
GPIO_InitStructure.Pin = (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/* ADC1 init function */
static void MX_ADC1_Init(void)
{
/* ............................
* АЦП, регулярные каналы IN0 - IN5, запуск от TIM3 TRGO,
* режим сканирования каналов,
* запрос DMA по получению результата канала
*/
RCC-›APB2ENR |= RCC_APB2ENR_ADC1EN ;// APB2Periph_ADC1;
ADC1-›CR2 |= ADC_CR2_ADON; //включение модуля АЦП
ADC1-›CR1 |= ADC_CR1_SCAN; //режим сканирования каналов
ADC1-›CR2 |= ADC_CR2_EXTSEL_2 | ADC_CR2_EXTTRIG | //триггер запуска от TIM3 TRGO,
ADC_CR2_DMA; //разрешено использование DMA
ADC1-›SQR1 |= ADC_SQR1_L_0 | ADC_SQR1_L_2; //число каналов 6
ADC1-›SQR3 = 0 | //последовательность
ADC_SQR3_SQ2_0 | //каналов 0, 1, 2, 3, 4, 5
ADC_SQR3_SQ3_1 |
ADC_SQR3_SQ4_0 | ADC_SQR3_SQ4_1 |
ADC_SQR3_SQ5_2 |
ADC_SQR3_SQ6_0 | ADC_SQR3_SQ6_2;
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* ...........................
* DMA1, Ch1, 16/16 bit, циклич.буфер, инкремент памяти
* Запрос DMA от ADC1, результаты каналов АЦП в регистрах ADC_Res[]
*/
RCC-›AHBENR |= RCC_AHBENR_DMA1EN; //DMA1 затактирован
DMA1_Channel1-›CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | //канал 1, 16/16 бит,
DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; //инкремент памяти, циклич.буфер
DMA1_Channel1-›CPAR = (uint32_t)&ADC1-›DR; //адрес регистра АЦП
DMA1_Channel1-›CMAR = (uint32_t)&ADC_Res[0]; //начальный адрес буфера результатов
DMA1_Channel1-›CNDTR = 6; //кол-во передач по DMA
DMA1_Channel1-›CCR |= DMA_CCR_EN; //DMA канал 1 включен
//----- Запуск преобразований ------------------------
TIM3-›CR1 |= TIM_CR1_CEN; //таймер запущен, АЦП запущен, преобразования выполняются
}
void TIM2_IRQHandler(void)
{
//TIM2-›CR1 = 0x00000000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
//TIM2-›CR1 = 0x00000001;
TIM2-›CNT = 0x00000000;
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
}
/* USER CODE END Error_Handler */
}
void assert_failed(uint8_t* file, uint32_t line)
{
} |
Светодиод на PIN_0 срабатывает
Не понятно, почему прерывание срабатывает еще на стадии конфигурации и повторно при запуске таймера?
Последний раз редактировалось zeon13; 22.08.2016 в 16:33.
|
|
|
|
22.08.2016, 16:41
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
и как то странно в функции прерывания TIM2_IRQHandler(void) строка
TIM2-›CNT = 0x00000000;
не выполняется, пролетает мимо, из-за этого постоянный сброс в эту функцию.
Помогите пожалуйста. моск взрывается, что делать не знаю, вроде все правильно, и в тоже время как то странно работает
Последний раз редактировалось zeon13; 22.08.2016 в 16:43.
|
|
|
|
22.08.2016, 17:02
|
|
Частый гость
Регистрация: 15.04.2008
Адрес: Йошкар-Ола
Сообщений: 39
Сказал спасибо: 47
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
а флаг прерывания кто сбрасывать будет?
|
|
|
|
22.08.2016, 17:30
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
Сообщение от Jeka_T
|
а флаг прерывания кто сбрасывать будет?
|
Код:
|
void TIM2_IRQHandler(void)
{
//TIM2-›CR1 = 0x00000000;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
//TIM2-›CR1 = 0x00000001;
TIM2-›CNT = 0x00000000;
} |
нет? не этот регистр?
|
|
|
|
22.08.2016, 17:33
|
|
Частый гость
Регистрация: 15.04.2008
Адрес: Йошкар-Ола
Сообщений: 39
Сказал спасибо: 47
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
TIM2-›SR = (uint16_t)~TIM_IT_Update;
|
|
|
|
22.08.2016, 17:55
|
|
Частый гость
Регистрация: 10.08.2016
Сообщений: 12
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: STM32F103C8T6 Таймер и прерывание по окончании счета
Сообщение от Jeka_T
|
TIM2-›SR = (uint16_t)~TIM_IT_Update;
|
Спасибо за подсказку.
в моем случае это видимо будет строкой:
TIM2-›SR &= ~TIM_SR_UIF;
Первый раз после инициализации прерывания флаг сбросился на ноль а потом почему то не сбрасывается. Значение SR=0x1E. Валит по циклу функцию прерывания...
Таймер не надо останавливать? Хотя он должен непрерывно крутиться
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 20:43.
|
|