stm32f030f4p6 ШИМ (PWM)

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

Столкнулся с проблемой. Не работает ШИМ. Возможно я ЧДНТ.
Контроллер: stm32f030f4p6.
Среда разработки: Keil5
Использую либу SPL.
Программатор: отладочная плата stm32f3discovery.(ОП)
У контроллера запитаны ноги VDDA и VDD от 3v на одном из разъемов от ОП.
GND от ОП подключено к VSS контроллера.
SWDIO и SWCLK подключены соответственно. Reset не подключаю, тк ногу с резетом не трограю.
Контроллер прошивается без проблем.
Описание сути:
Хочу заставить работать ШИМ на ноге PA6. Судя по даташиту PA6 - это третий таймер с первым каналом TIM3_CH1.
Соответственно включаем тактирование переферии GPIOA, и таймера TIM3. После инициализации и настройки - я не вижу никаких сигналов на ноге PA6. В отладчике вижу, что таймер работает, каунтер бежит и сбрасывается после достижения настроенного периода. Нога PA6 инициализирована на работу как альтернативная функция GPIO_Mode_AF, сконфигурировано на использование альтернативной функции GPIO_AF_1, опять же судя по даташиту TIM3 именно на AF1.
Отдельная настройка ноги PA6 в режим выхода GPIO_Mode_OUT для теста дает понять, что порт работает и программно управляется, при GPIO_SetBits(GPIOA,GPIO_Pin_6) напряжение на ноге появляется.
Отдельно хочу заметить, при замере напряжения между VDD(+3v) и ногой PA6 при инициализации порта как GPIO_Mode_AF, тестер показыват +3v, что говорит о том, что уровень ноги равен GND, то бишь ток течет как в GND.(может тут я не совсем корректно выразился, но, думаю, суть ясна).
Код прилагаю ниже с комментариями:
Спойлер

Код: Выделить всё

#include "stm32f0xx.h" 
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_tim.h"

#define TIMER_PRESCALER		4800000000 // частота ядра 48мГц, не знаю почему, пришлось добавить нулей лишних, чтобы таймер тикал каждую секунду.

uint16_t previousState;
GPIO_InitTypeDef port;
TIM_TimeBaseInitTypeDef timer;
TIM_OCInitTypeDef timerPWM;
uint16_t buttonPreviousState;
TIM_BDTRInitTypeDef bdtr;

void initAll()
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 
    port.GPIO_Mode = GPIO_Mode_AF;
    port.GPIO_OType = GPIO_OType_PP;
    port.GPIO_Pin = GPIO_Pin_6;
    port.GPIO_PuPd = GPIO_PuPd_DOWN;
    port.GPIO_Speed = GPIO_Speed_Level_3;
    GPIO_Init(GPIOA, &port);
		
    GPIO_PinAFConfig(GPIOA,GPIO_Pin_6,GPIO_AF_1);
 
    TIM_TimeBaseStructInit(&timer);
    timer.TIM_Prescaler = TIMER_PRESCALER;
    timer.TIM_Period = 16; // сделаем период 16 тиков
    TIM_TimeBaseInit(TIM3, &timer);	
 
    TIM_OCStructInit(&timerPWM);
    timerPWM.TIM_Pulse = 8; //делим 16 напополам, получаем 8 тиков напряжение на ногу подается и 8 не подается.
    timerPWM.TIM_OCMode = TIM_OCMode_PWM1;
    timerPWM.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OC1Init(TIM3, &timerPWM);      // инициализируем на 1 канал TIM3
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // тут что-то взятое откуда-то
	
    // тут дальше тоже невнятный для меня блок кода.
    TIM_BDTRStructInit(&bdtr);
    bdtr.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    TIM_BDTRConfig(TIM3, &bdtr);
}


int main()
{
    SystemInit();
    initAll();
    TIM_Cmd(TIM3, ENABLE);
	
    TIM3->CCR1 = 8; // продублируем настройку  timerPWM.TIM_Pulse = 8;
    while(1)
    {
    	__NOP();
    }		
}

Ну и собственно вопрос, что я мог упустить или в каком направлении можно дальше посмотреть, чтобы решить вопрос.
Пока вижу только один вариант - сделать прерывание по обнулению счетичка и дергать ногой программно, что я бы сильно не хотел!!!
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

в каком направлении можно дальше посмотреть, чтобы решить вопрос
посмотрите как в примерах STM32SnippetsF0 сделано + почитать документацию
Спойлер

Код: Выделить всё

/**
  * @brief  This function configures the TIMx as PWM mode 1
  *         and enables the peripheral clock on TIMx and on GPIOA.
  *         It configures GPIO PA8 as Alternate function for TIM1_CH1
  *         To use another timer, channel or GPIO, the RCC and GPIO configuration 
  *         must be adapted according to the datasheet.
  *         In case of other timer, the interrupt sub-routine must also be renamed
  *         with the right handler and the NVIC configured correctly.
  * @param  None
  * @retval None
  */
__INLINE void ConfigureTIMxAsPWM_EdgeAligned(void)
{
  /* (1) Enable the peripheral clock of Timer x */
  /* (2) Enable the peripheral clock of GPIOA */
  /* (3) Select alternate function mode on GPIOA pin 8 */
  /* (4) Select AF2 on PA8 in AFRH for TIM1_CH1 */
  
  RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; /* (1) */
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN; /* (2) */  
  GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER8)) | (GPIO_MODER_MODER8_1); /* (3) */
  GPIOA->AFR[1] |= 0x02; /* (4) */
  
  /* (1) Set prescaler to 47, so APBCLK/48 i.e 1MHz */ 
  /* (2) Set ARR = 8, as timer clock is 1MHz the period is 9 us */
  /* (3) Set CCRx = 4, , the signal will be high during 4 us */
  /* (4) Select PWM mode 1 on OC1  (OC1M = 110),
         enable preload register on OC1 (OC1PE = 1) */
  /* (5) Select active high polarity on OC1 (CC1P = 0, reset value),
         enable the output on OC1 (CC1E = 1)*/
  /* (6) Enable output (MOE = 1)*/
  /* (7) Enable counter (CEN = 1)
         select edge aligned mode (CMS = 00, reset value)
         select direction as upcounter (DIR = 0, reset value) */  
  /* (8) Force update generation (UG = 1) */
  
  TIMx->PSC = 47; /* (1) */
  TIMx->ARR = 8; /* (2) */
  TIMx->CCR1 = 4; /* (3) */
  TIMx->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE; /* (4) */
  TIMx->CCER |= TIM_CCER_CC1E; /* (5) */
  TIMx->BDTR |= TIM_BDTR_MOE; /* (6) */
  TIMx->CR1 |= TIM_CR1_CEN; /* (7) */
  TIMx->EGR |= TIM_EGR_UG; /* (8) */
}
http://www.st.com/web/en/catalog/tools/ ... ppetsf0-pr
Реклама
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

Спасибо, методом проб и ошибок нашел проблему.

GPIO_PinAFConfig(GPIOA,GPIO_Pin_6,GPIO_AF_1); - не выставляла вообще ничего в AFRL регистр порта А.

Ну и собсно ошибка была следущая:
Необходимо:
GPIO_PinAFConfig(GPIOA,GPIO_Pin_6,GPIO_AF_1);
Заменить на:
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_1);
То бишь GPIO_Pin_6 на GPIO_PinSource6. Где логика у тех кто писал сие, ппц...
Ответить

Вернуться в «ARM»