LINUX.ORG.RU

STM32F4 Таймер

 cortex-m4, , stm32f4, stm32f4discovery,


0

1

Здравствуйте, господа. Запускаю на STM32F4Discovery следующую программу:

#include "stm32f4xx.h"

int main()
{	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	GPIO_ResetBits(GPIOD, GPIO_Pin_15);
	
	/*
			HCLK: 168 MHz
			APB1 Prescaler: 4 => CK_PSC = 2 * 42 MHz = 84 MHz
	*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1; // CK_CNT = 1 MHz
	TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // CK_CNT / 1000 = 1 kHz
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
	TIM_ARRPreloadConfig(TIM5, ENABLE);
	TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
	TIM_Cmd(TIM5, ENABLE);
	NVIC_EnableIRQ(TIM5_IRQn);
	
	while (1) {	}
}

void TIM5_IRQHandler()
{
	if (TIM_GetITStatus(TIM5, TIM_IT_Update) == SET){
		TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
		GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
	}
}
Ожидаемого килогерца нет, есть чуть меньше 500 Гц :( Подскажите, пожалуйста, что я упускаю из виду.



Последнее исправление: v0r0n (всего исправлений: 2)

Так все правильно... C частотой 1кГц переключается ножка -> период выходного сигнала 500 Гц.

Период таймера в два раза сократи

mike666
()
Ответ на: комментарий от mike666

Обработчик прерывания должен вызываться каждую 1 мс => каждую мс должен инвертироваться Pin_15. По факту получается что состояние вывода меняется каждые 2 мс.

v0r0n
() автор топика
Ответ на: комментарий от v0r0n

Обработчик прерывания должен вызываться каждую 1 мс => каждую мс должен инвертироваться Pin_15. По факту получается что состояние вывода меняется каждые 2 мс.

головой подумай. вот у тебя таймлайн где T - тики таймера, S - состояние ноги

T: 0 1 2 3 4 5 6 7 8 9
S: 0 1 0 1 0 1 0 1 0 1
exception13 ★★★★★
()
Последнее исправление: exception13 (всего исправлений: 1)
Ответ на: комментарий от v0r0n

Ну ежели прерывание зовется каждые 2 мс, вместо одной то надо смотреть делители, начиная с APB и дальше. Проверить тот ли clock выбран.

Если нужно побыстро завести не разбираясь ( что не кошерно ), можно просто подкрутить период ( или prescaler ) таймера.

mike666
()
Ответ на: комментарий от exception13

ШИМ

#include "stm32f4xx.h"

int main()
{	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4);

	GPIO_ResetBits(GPIOD, GPIO_Pin_15);
	
	/*
			HCLK: 168 MHz
			APB1 Prescaler: 4 => CK_PSC = 2 * 42 MHz = 84 MHz
	*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1; // CK_CNT = 1 MHz
	TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // CK_CNT / 1000 = 1 kHz
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
	TIM_ARRPreloadConfig(TIM4, ENABLE);

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 500;

	TIM_OC4Init(TIM4, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
	
	TIM_Cmd(TIM4, ENABLE);
	
	while (1) {	}
}
Период (2 состояния) чуть более 2 мс.

T: 0 1 2 3 4 5 6 7 8 9

S: 0 1 0 1 0 1 0 1 0 1

T: 0 2 4 6 8

S: 1 0 1 0 1

v0r0n
() автор топика
Ответ на: комментарий от mike666

Да уже, но что-то я похоже упустил...

v0r0n
() автор топика
18 августа 2013 г.

Если я ничего не путаю, то как раз пол килогерца и получается - с частотой в килогерц оно сначала опускает, потом поднимает уровень, т.е. период получается 500 герц которые есть на практике... Вручную не проверял, пока что недоступен осциллограф. =)

Если поднять частоту вдвое, получится искомый килогерц - тогглить просто надо вдвое чаще чтобы получить период нужной частоты.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.