Программирование 32-х разрядных МК

dosikus
Offline
Зарегистрирован: 11.03.2017

nik182 пишет:

 

В ИАР лучший отладчик. 

 

Лучший дебаггер это Ozone. Ни кайло ни тем более яр и рядом не лежали ...

https://www.segger.com/products/development-tools/ozone-j-link-debugger/

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Наверное Вещь. Только очень редкий зверёк в нашем зоопарке. Ни разу не встречал живьём человека с ним работающего. Только читал хвалебные отзывы. Писал про те, которые использовал для отладки сам.

mixail844
Offline
Зарегистрирован: 30.04.2012

nik182 пишет:
Да. Наверное Вещь. Только очень редкий зверёк в нашем зоопарке. Ни разу не встречал живьём человека с ним работающего. Только читал хвалебные отзывы. Писал про те, которые использовал для отладки сам.

я с ним работал ,правда не на постоянной основе ,а только что бы отладить баг который приводит к Hard Fault .a в Atolllic True Studio , callstack не всегда виден в этом случае

dosikus
Offline
Зарегистрирован: 11.03.2017

Ozone , SES и RTT лучший инструментарий для разработки и отладки.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Уж не знаю в чем дело, но сегодня до 21 МГц измеряет))

b707
Offline
Зарегистрирован: 26.05.2017

а можно тоже спросить?

Пытаюсь запустить пример TIM/OCToggle из Peripheral library

Плата blue_pill stm32f103c8t6, пишу в  IAR 8.30

вот код

/**
  ******************************************************************************
  * @file    TIM/OCToggle/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
__IO uint16_t CCR1_Val = 32768;
__IO uint16_t CCR2_Val = 16384;
__IO uint16_t CCR3_Val = 8192;
__IO uint16_t CCR4_Val = 4096;
uint16_t PrescalerValue = 0;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

int main(void)
{
 
       
  /* System Clocks Configuration */
  RCC_Configuration();

  /* NVIC Configuration */
  NVIC_Configuration();

  /* GPIO Configuration */
  GPIO_Configuration();

  /* ---------------------------------------------------------------------------
    TIM3 Configuration: Output Compare Toggle Mode:
    TIM3CLK = SystemCoreClock / 2,
    The objective is to get TIM3 counter clock at 12 MHz:
     - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    CC1 update rate = TIM3 counter clock / CCR1_Val = 366.2 Hz
    CC2 update rate = TIM3 counter clock / CCR2_Val = 732.4 Hz
    CC3 update rate = TIM3 counter clock / CCR3_Val = 1464.8 Hz
    CC4 update rate = TIM3 counter clock / CCR4_Val = 2929.6 Hz
  ----------------------------------------------------------------------------*/
  /* Compute the prescaler value */
  PrescalerValue = (uint16_t) (SystemCoreClock / 12000000) - 1;

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* Output Compare Toggle Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  TIM_OC3Init(TIM3, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;

  TIM_OC4Init(TIM3, &TIM_OCInitStructure);

  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);

  /* TIM IT enable */
  TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
  //TIM_ITConfig(TIM3, TIM_IT_CC1 , ENABLE);

  while (1)
  {}
}


void RCC_Configuration(void)
{
  /* PCLK1 = HCLK/4 */
  RCC_PCLK1Config(RCC_HCLK_Div4);

  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB|
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
}


void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

#ifdef STM32F10X_CL
  /*GPIOB Configuration: TIM3 channel1, 2, 3 and 4 */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);	

#else
  /* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
}

/**
  * @brief  Configure the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

void TIM3_IRQHandler(void)
{
	uint16_t capture = 0;
  /* TIM3_CH1 toggling with frequency = 183.1 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
    capture = TIM_GetCapture1(TIM3);
    TIM_SetCompare1(TIM3, capture + CCR1_Val );
  }

  /* TIM3_CH2 toggling with frequency = 366.2 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    capture = TIM_GetCapture2(TIM3);
    TIM_SetCompare2(TIM3, capture + CCR2_Val);
  }

  /* TIM3_CH3 toggling with frequency = 732.4 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
    capture = TIM_GetCapture3(TIM3);
//TIM_SetCompare3(TIM3, capture + CCR3_Val);
    //TIM_SetCompare3(TIM3, CCR3_Val);
  }

  /* TIM3_CH4 toggling with frequency = 1464.8 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
    capture = TIM_GetCapture4(TIM3);
    TIM_SetCompare4(TIM3, capture + CCR4_Val);
  }
   
}
#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 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) */

  while (1)
  {}
}

#endif

Проблема в том, что на выходе всез четырех каналов получаю меандр с одной и той же частотой - в 2 раза ниже частоты таймера. То есть  инвертирование состояния  пина происходит только один раз за цикл таймера. То ли не срабатывает прерывание Output Compare, то ли срабатывает, но почему-то значение регистра сравнения не увеличивается. К сожалению, осцил у меня одноканальный, поэтому посмотреть, туглятся ли все каналы одновременно при переполнении общего счетчика таймера или каждый в свое время по сравнению- не могу.

Собрал аналогичный проект в Stm32Cube через Hal - получил ровно такой же результат, выходы каналов меняют состояние один раз за цикл.

Я явно чего-то не понимаю.

Добавка - проблема касается только режима OCToggle, OC Active работает, PWM тоже.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, у меня от халовских портянок мозг взрывыется 8-\     В сиэмсис перепиши :)

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

 В сиэмсис перепиши :)

а приведенный код разве не в сиэмсис ? - я их пока с трудом отличаю

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, дык HAL это . Пример сиэмсис в #829

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

b707, дык HAL это . Пример сиэмсис в #829

ага, понял.

dosikus
Offline
Зарегистрирован: 11.03.2017

dimax пишет:

b707, дык HAL это . 

 

Это не хал . это SPL.

Хотя такое же г....

 

Много примеров для таймеров есть в сниппетсах для F0 ...

nik182
Offline
Зарегистрирован: 04.05.2015

Toggle это переключит туда в одном цикле - сюда в другом. В сумме частота должна получится ровно в 2 раза ниже, что и имеем. И из манула на f103  Figure 83. Output compare mode, toggle on OC1. Смотреть там.

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

Toggle это переключит туда в одном цикле - сюда в другом. В сумме частота должна получится ровно в 2 раза ниже, что и имеем.

Это все верно, если регистр сравнения остается постоянным - будет одно совпадаение за цикл. Но в этом примере при каждом совпадении задется новое значение CCR, так что событие Output Compare за один цикл таймера происходит несколько раз.

Например, счетчик считает до 65535. В начале ставим CCR1 = 1024, по совпадению увеличиваем еще на 1024. то есть ставим 2048 и так далее

В итоге Toggle будет вызываться за цикл 64 раза и частота должна быть в 32 раза больше частоты таймера. Подробнее см комментарии в строчках 47-56 и код обработчика прерывания TIM3 в строчках 171-207

проблема состоит именно в том, что это "умножение частоты" не работает

dosikus
Offline
Зарегистрирован: 11.03.2017

b707, 

а теперь внимательно прочтите readme.txt  что в в папке с проектом.

Какое на "умножение частоты" , да еще "32 раза больше частоты таймера" ?

Ух и буйная же у вас фантазия.

This example shows how to configure the TIM3 peripheral to generate four different 
signals with four different frequencies.
The TIM3 CCR1 register value is equal to 32768: 
CC1 update rate = TIM3 counter clock / CCR1_Val = 366.2 Hz,
so the TIM3 Channel 1 generates a periodic signal with a frequency equal to 183.1 Hz.
 
The TIM3 CCR2 register is equal to 16384:
CC2 update rate = TIM3 counter clock / CCR2_Val = 732.4 Hz
so the TIM3 channel 2 generates a periodic signal with a frequency equal to 366.3 Hz.
 
The TIM3 CCR3 register is equal to 8192:
CC3 update rate = TIM3 counter clock / CCR3_Val = 1464.8 Hz
so the TIM3 channel 3 generates a periodic signal with a frequency equal to 732.4 Hz.
 
The TIM3 CCR4 register is equal to 4096:
CC4 update rate = TIM3 counter clock / CCR4_Val =  2929.6 Hz
so the TIM3 channel 4 generates a periodic signal with a frequency equal to 1464.8 Hz.
 
Перевести, или сами?

 

b707
Offline
Зарегистрирован: 26.05.2017

dosikus пишет:

This example shows how to configure the TIM3 peripheral to generate four different 
signals with four different frequencies.

выделил для вас. Так что это я у вас должен спросить :
 
"вам перевести или как?"
nik182
Offline
Зарегистрирован: 04.05.2015

Посмотрел. На каждое прерывание дергает ногой. Туда-сюда. 

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

Посмотрел. На каждое прерывание дергает ногой. Туда-сюда. 

в смысле - опробовали на макете? - работает, частоты на каналах получаются разные?

nik182
Offline
Зарегистрирован: 04.05.2015

На натуре. Осциллограф было лень доставать. Частоту измерял тестером. Она прыгала одинаково на каждой ноге от 27 до 96 Гц. Смотрел в отладчике на ноги. Каждое прерывание меняло уровень ноги на противоположный.  

dosikus
Offline
Зарегистрирован: 11.03.2017

b707 пишет:

dosikus пишет:

This example shows how to configure the TIM3 peripheral to generate four different 
signals with four different frequencies.

выделил для вас. Так что это я у вас должен спросить :
 
"вам перевести или как?"

И все же придется переводить :

Этот пример показывает как сконфигурировать периферию TIM3 ДЛЯ ГЕНЕРАЦИИ 4Х СИГНАЛОВ С 4МЯ РАЗЛИЧНЫМИ ЧАСТОТАМИ.

Вот только у каждого канала - своя фиксированная частота...

Дальше будем спорить?

Или вам до кучи на пальцах объяснить механизм работы таймера и режим compare?

 

b707
Offline
Зарегистрирован: 26.05.2017

спасибо, хотя ничего и непонятно... Частота должна быть разной на каждой ноге, но не должна "прыгать"

b707
Offline
Зарегистрирован: 26.05.2017

dosikus пишет:

Вот только у каждого канала - своя фиксированная частота...

так я с этим и не спорю, мне это полностью понятно.

Но только у меня на всех каналах - одна и та же частота

dosikus
Offline
Зарегистрирован: 11.03.2017

Завтра время будет посмотрю.

Однако как быть с этим?

В итоге Toggle будет вызываться за цикл 64 раза и частота должна быть в 32 раза больше частоты таймера. 

проблема состоит именно в том, что это "умножение частоты" не работает

 

nik182
Offline
Зарегистрирован: 04.05.2015

Взял не Вашу программу, а стандартный пример из поставки IAR c:\Program Files (x86)\IAR Systems\Embedded Workbench 7.4\arm\examples\ST\STM32F10x\stm32f10x_stdperiph_lib\Project\STM32F10x_StdPeriph_Examples\TIM\tim.eww запустил - все четыре частоты частоты на месте. Ничего не прыгает. тестер показывает 183 366 732 1464 Гц на ногах А6 А7 В0 В1. Сравнивайте со своим. main и it

/**
  ******************************************************************************
  * @file    TIM/OCToggle/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_OCToggle
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
__IO uint16_t CCR1_Val = 32768;
__IO uint16_t CCR2_Val = 16384;
__IO uint16_t CCR3_Val = 8192;
__IO uint16_t CCR4_Val = 4096;
uint16_t PrescalerValue = 0;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     
       
  /* System Clocks Configuration */
  RCC_Configuration();

  /* NVIC Configuration */
  NVIC_Configuration();

  /* GPIO Configuration */
  GPIO_Configuration();

  /* ---------------------------------------------------------------------------
    TIM3 Configuration: Output Compare Toggle Mode:
    TIM3CLK = SystemCoreClock / 2,
    The objective is to get TIM3 counter clock at 12 MHz:
     - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    CC1 update rate = TIM3 counter clock / CCR1_Val = 366.2 Hz
    CC2 update rate = TIM3 counter clock / CCR2_Val = 732.4 Hz
    CC3 update rate = TIM3 counter clock / CCR3_Val = 1464.8 Hz
    CC4 update rate = TIM3 counter clock / CCR4_Val = 2929.6 Hz
  ----------------------------------------------------------------------------*/
  /* Compute the prescaler value */
  PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* Output Compare Toggle Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  TIM_OC3Init(TIM3, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* Output Compare Toggle Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;

  TIM_OC4Init(TIM3, &TIM_OCInitStructure);

  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);

  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);

  /* TIM IT enable */
  TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

  while (1)
  {}
}

/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
  /* PCLK1 = HCLK/4 */
  RCC_PCLK1Config(RCC_HCLK_Div4);

  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB|
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
}

/**
  * @brief  Configure the TIM3 Pins.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

#ifdef STM32F10X_CL
  /*GPIOB Configuration: TIM3 channel1, 2, 3 and 4 */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);	

#else
  /* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
}

/**
  * @brief  Configure the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

#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 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) */

  while (1)
  {}
}

#endif
/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
/**
  ******************************************************************************
  * @file    TIM/OCToggle/stm32f10x_it.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and peripherals
  *          interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_OCToggle
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t capture = 0;
extern __IO uint16_t CCR1_Val;
extern __IO uint16_t CCR2_Val;
extern __IO uint16_t CCR3_Val;
extern __IO uint16_t CCR4_Val;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M3 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
  * @brief  This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {}
}

/**
  * @brief  This function handles Memory Manage exception.
  * @param  None
  * @retval None
  */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {}
}

/**
  * @brief  This function handles Bus Fault exception.
  * @param  None
  * @retval None
  */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {}
}

/**
  * @brief  This function handles Usage Fault exception.
  * @param  None
  * @retval None
  */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {}
}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{}

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
void SVC_Handler(void)
{}

/**
  * @brief  This function handles PendSV_Handler exception.
  * @param  None
  * @retval None
  */
void PendSV_Handler(void)
{}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{}

/******************************************************************************/
/*            STM32F10x Peripherals Interrupt Handlers                        */
/******************************************************************************/

/**
  * @brief  This function handles TIM3 global interrupt request.
  * @param  None
  * @retval None
  */
void TIM3_IRQHandler(void)
{
  /* TIM3_CH1 toggling with frequency = 183.1 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
    capture = TIM_GetCapture1(TIM3);
    TIM_SetCompare1(TIM3, capture + CCR1_Val );
  }

  /* TIM3_CH2 toggling with frequency = 366.2 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    capture = TIM_GetCapture2(TIM3);
    TIM_SetCompare2(TIM3, capture + CCR2_Val);
  }

  /* TIM3_CH3 toggling with frequency = 732.4 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
    capture = TIM_GetCapture3(TIM3);
    TIM_SetCompare3(TIM3, capture + CCR3_Val);
  }

  /* TIM3_CH4 toggling with frequency = 1464.8 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
    capture = TIM_GetCapture4(TIM3);
    TIM_SetCompare4(TIM3, capture + CCR4_Val);
  }
}

/******************************************************************************/
/*                 STM32F10x Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f10x_xx.s).                                            */
/******************************************************************************/

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
/*void PPP_IRQHandler(void)
{
}*/

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

 

b707
Offline
Зарегистрирован: 26.05.2017

dosikus пишет:

В итоге Toggle будет вызываться за цикл 64 раза и частота должна быть в 32 раза больше частоты

эти 32 и 64 - исключительно как пример . Реальная разница частот определяется исключительно отношением ARR / CCRx

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

Взял не Вашу программу, а стандартный пример из поставки IAR c:\Program Files (x86)\IAR Systems\Embedded Workbench 7.4\arm\examples\ST\STM32F10x\stm32f10x_stdperiph_lib\Project\STM32F10x_StdPeriph_Examples\TIM\tim.eww запустил - все четыре частоты частоты на месте. Ничего не прыгает. тестер показывает 183 366 732 1464 Гц на ногах А6 А7 В0 В1. 

понятно, это она и есть, я только со значениями прескалера и CCRx игрался, чтобы убедится, что они хотя бы влияют на выход :) так что у меня частоты уже другие должны быть. Но у меня на всех 4х выходах одна частота.

Думаю, я скорее всего где-то напортачил при создании шаблона проекта для ИАРа... Шаблон из этой же SPL почему-то не собирается, не хватает части файлов - пришлось их собирать по инету.

ладно, попробую написать это же на CMSIS. как Димакс посоветовал

nik182
Offline
Зарегистрирован: 04.05.2015

Не вижу разницы между CMSIS SPL HAL и LL. Последние три это просто обёртки над CMSIS написанные разными командами индийцев и соответственно имеют разные аббревиатуры на одни и те же регистры ARM. Выучил все четыре последовательно. Из обёрток самая чистая - SPL. Никогда не было проблем. Потом сделали куб и HAL - попробовали сделать абстракцию повыше. В результате оказалось много лишнего кода и плохой прямой доступ к регистрам. Я столкнулся с тем, что на HAL невозможно тонко настраивать таймеры и пришлось писать часть инициализации на CMSIS. Тогда придумали LL драйвера и как вишенка на торте миксирование HAL и LL . Сейчас все проекты начинаю с куба. Ставлю разной периферии либо HAL либо LL драйвера в зависимости надо мне лезть в тонкости регистров или нет. В результате получается проект с полной инициализацией нужной периферии, всеми файлами и необходимыми библиотеками, который компилируется сразу. Дописывать приходится только запуск модулей и логику программы. На CMSIS меня всегда напрягало высчитывать циферки при инициализации ног. Ни разу не встречал, что бы МК работал не так, как описано в мануале. Поэтому играться уже не тянет. Последние игры были с запуском АЦП от четвёртого таймера. Фишка была в том, что на SPL работало, а на HAL и LL нет. Даже когда в конце концов сумел добиться на LL такого же состояния регистров как на SPL всё равно АЦП отказывалось запускаться. Пришлось менять последовательность применения LL команд - помогло. Встречал в сети сообщения, что шаблон инициализации RTC на stm32f4 на LL драйверах не запускает RTC. На HAL всё работает. Это всё я к тому, что в CMSIS все регистры имеют имена как в мануале на процессор. Берем мануал. Открываем описание последовательности команд для инициализации периферии - всегда есть точное описание что и в какой последовательности делать. Там же написаны имена регистров и их побитное описание. Собираем команды. Но на HAL будет  быстрее в несколько раз конечный результат. 

Это всё не относится к программированию в аддонах ардуины. Аддоны делают инициализацию сами. Поэтому чуть чуть подправить то, что нужно себе с помощью CMSIS самый простой и быстрый способ. Здесь я с Димой согласен полностью. Больше ничего не надо. 

P.S. Спасибо. Исправил.              

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Хорошо расписали, плюсую.
Только CMSYS слегка "режет слух", правильно CMSIS (Cortex Microcontroller Software Interface Standard).
Можно ещё вспомнить MicroXplorer (предшественник Куба), который генерил инициализацию для SPL.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, всё таки во мне взыграло любопытство, и "перевёл" эту  тарабарщину на человеческий cmsis/ардуино. Написал на 1-ом таймере, по аналогии можно на любой переделать. Таки да, на выходах 4 разных частоты, вроде особо не джиттерит даже..

/* пример для F103C8 генерации одним таймером нескольких частот за счёт перепрограммирования 
 *  регистров сранения в прерываниях. Выходы PA8,9,10,11 Частоты с данными параметрами
 *  549,36Hz 1098Hz 2197 Hz 4394Hz компилить в ардуине (аддон от STM) без UART и без USB
 */
uint16_t CCR1_Val = 32768;
uint16_t CCR2_Val = 16384;
uint16_t CCR3_Val = 8192;
uint16_t CCR4_Val = 4096;
void setup() {
HardwareTimer *MyTim = new HardwareTimer(TIM1);
RCC->APB2ENR|=(1<<11)|(1<<2); //tim1, gpioa clock enable
GPIOA->CRH&=~0xFFFF;
GPIOA->CRH|=0xBBBB; //PA8,9,10,11 output altfunc
TIM1->CCER=(1<<12)|(1<<8)|(1<<4)|(1<<0);//pin enable 
TIM1->CCMR1=(3<<12)|(3<<4);//toogle mode 
TIM1->CCMR2=(3<<12)|(3<<4);//toogle mode
TIM1->PSC=1;
TIM1->ARR=65535;
TIM1->CCR1=CCR1_Val;
TIM1->CCR2=CCR2_Val;
TIM1->CCR3=CCR3_Val;
TIM1->CCR4=CCR4_Val;
TIM1->BDTR=1<<14;//output enable
TIM1->CR1=1;
MyTim->attachInterrupt(1,tim1_ch1);
MyTim->attachInterrupt(2,tim1_ch2);
MyTim->attachInterrupt(3,tim1_ch3);
MyTim->attachInterrupt(4,tim1_ch4);
}
void tim1_ch1() {TIM1->CCR1+=CCR1_Val;}
void tim1_ch2() {TIM1->CCR2+=CCR2_Val;}
void tim1_ch3() {TIM1->CCR3+=CCR3_Val;}
void tim1_ch4() {TIM1->CCR4+=CCR4_Val;}

void loop(){}

 

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

b707, всё таки во мне взыграло любопытство, и "перевёл" эту  тарабарщину на человеческий cmsis/ардуино. Написал на 1-ом таймере, по аналогии можно на любой переделать.

Спасибо, хотя это немного неудачная аналогия, потому что, насколько я понял, у ТИМ1 отдельные векторы прерывания на каждый канал, а у ТИМ3 - одно прерывание на все.

В моем случае именно это сыграло роль - при самостоятельном написании через HAL и Куб я неверно определил источник прерывания при входе в TIM3_IRQHandler, поэтому прерывание по совпадению не работало. Когда нашел ошибку - все запустилось.

Но это при сборке через СТМ-Куб

А вот приведенный выше пример из SPL так и не идет. Хотел посмотеть в отладчике, почему так происходит - но IAR не дает поставить брекпойнт внутри обработчика IRQ. Наверно это правильно, прерывание же не совсем код. Не подскажете, как посмотреть регистры таймера в момент вызова прерывания?

nik182
Offline
Зарегистрирован: 04.05.2015

Как это не даёт точку останова в прерывании? Обязательное условие - программа должна быть скомпилирована без ошибок и прерывание должно быть в объектном коде. Если какая то часть программы не вызывается то точку туда поставить нельзя. Число точек ограничено. Нельзя поставить больше какого то числа точек (у меня 5). Вот пример. Точка стоит. Я прерывания ловлю. Проблем нет.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707 пишет:

 у ТИМ1 отдельные векторы прерывания на каждый канал, а у ТИМ3 - одно прерывание на все.

Тут есть нюас -ардуина не даёт сесть на голый вектор. Поэтому я вынужденно использовал её функцию обработки прерывания. А функция сама разбирается с каналами, и сама программирует регистр DIER. Т.е. при переходе на другой таймер ничего хитрого менять не надо.

b707 пишет:

при самостоятельном написании через HAL и Куб я неверно определил источник прерывания при входе в TIM3_IRQHandler, поэтому прерывание по совпадению не работало. Когда нашел ошибку - все запустилось.

Вот поэтому я пишу в CMSIS, когда вся программа 10 строк а не на 200  -ошибку найти легче :)

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

Как это не даёт точку останова в прерывании? Обязательное условие - программа должна быть скомпилирована без ошибок и прерывание должно быть в объектном коде.

простите, неверно выразился. Поставить точку дает, но при запуске появляется сообщение "Некоторые брекпойнты будут удалены из отладки" (вольный перевод, точной формулировки сейчас посмотреть не могу) И точка пропадает.

Программа скомпилирована без ошибок и даже без предупреждений...

mixail844
Offline
Зарегистрирован: 30.04.2012

b707 пишет:

nik182 пишет:

Как это не даёт точку останова в прерывании? Обязательное условие - программа должна быть скомпилирована без ошибок и прерывание должно быть в объектном коде.

простите, неверно выразился. Поставить точку дает, но при запуске появляется сообщение "Некоторые брекпойнты будут удалены из отладки" (вольный перевод, точной формулировки сейчас посмотреть не могу) И точка пропадает.

Программа скомпилирована без ошибок и даже без предупреждений...

незнаю насколько "умны" разные среды разработки , но каждый раз когда писалась такое ("некоторыe брейк поинты будут удалены") ,то код куда была поставлена точка остановки , десйтвительно не исполнялся

b707
Offline
Зарегистрирован: 26.05.2017

mixail844 пишет:

незнаю насколько "умны" разные среды разработки , но каждый раз когда писалась такое ("некоторыe брейк поинты будут удалены") ,то код куда была поставлена точка остановки , десйтвительно не исполнялся

а это идея, которая обьяснила бы все...

А из-за чего прерывание может не исполнятся, так что даже компилятор это видит? - единственное. что приходит в голову - имя обработчика не прописано в хидере или прописано неверно... Надо будет покопаться внимательно.

mixail844
Offline
Зарегистрирован: 30.04.2012

dimax пишет:

b707, всё таки во мне взыграло любопытство, и "перевёл" эту  тарабарщину на человеческий cmsis/ардуино. Написал на 1-ом таймере, по аналогии можно на любой переделать. Таки да, на выходах 4 разных частоты, вроде особо не джиттерит даже..

/* пример для F103C8 генерации одним таймером нескольких частот за счёт перепрограммирования 
 *  регистров сранения в прерываниях. Выходы PA8,9,10,11 Частоты с данными параметрами
 *  549,36Hz 1098Hz 2197 Hz 4394Hz компилить в ардуине (аддон от STM) без UART и без USB
 */
uint16_t CCR1_Val = 32768;
uint16_t CCR2_Val = 16384;
uint16_t CCR3_Val = 8192;
uint16_t CCR4_Val = 4096;
void setup() {
HardwareTimer *MyTim = new HardwareTimer(TIM1);
RCC->APB2ENR|=(1<<11)|(1<<2); //tim1, gpioa clock enable
GPIOA->CRH&=~0xFFFF;
GPIOA->CRH|=0xBBBB; //PA8,9,10,11 output altfunc
TIM1->CCER=(1<<12)|(1<<8)|(1<<4)|(1<<0);//pin enable 
TIM1->CCMR1=(3<<12)|(3<<4);//toogle mode 
TIM1->CCMR2=(3<<12)|(3<<4);//toogle mode
TIM1->PSC=1;
TIM1->ARR=65535;
TIM1->CCR1=CCR1_Val;
TIM1->CCR2=CCR2_Val;
TIM1->CCR3=CCR3_Val;
TIM1->CCR4=CCR4_Val;
TIM1->BDTR=1<<14;//output enable
TIM1->CR1=1;
MyTim->attachInterrupt(1,tim1_ch1);
MyTim->attachInterrupt(2,tim1_ch2);
MyTim->attachInterrupt(3,tim1_ch3);
MyTim->attachInterrupt(4,tim1_ch4);
}
void tim1_ch1() {TIM1->CCR1+=CCR1_Val;}
void tim1_ch2() {TIM1->CCR2+=CCR2_Val;}
void tim1_ch3() {TIM1->CCR3+=CCR3_Val;}
void tim1_ch4() {TIM1->CCR4+=CCR4_Val;}

void loop(){}

 

dimax,скажите ,  почему вы не используете полную CMSIS овскую нотацию ? 
 вместо
TIM1->CCMR1=(3<<12)|(3<<4);//toogle mode 
 TIM1->CCMR1 = ((TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2M_1) << TIM_CCMR1_OC2M) | ( (TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 ) << TIM_CCMR1_OC1M) ; // хоть и длиней ,но более читабельней 

 

 

dosikus
Offline
Зарегистрирован: 11.03.2017

b707, Еще одни грабли :

Если проект был выбран в плюсах то надо было хэндлер прерывания обрамлять в   extern "C" {.......}

 

mixail844. 

им лень определения из хэдера скопипастить, а в " родной" не завезли ...

b707
Offline
Зарегистрирован: 26.05.2017

dosikus пишет:

b707, Еще одни грабли :

Если проект был выбран в плюсах то надо было хэндлер прерывания обрамлять в   extern "C" {.......}

 

mixail844. 

им лень определения из хэдера скопипастить, а в " родной" не завезли ...

Ага. спасибо, проект был выбран как С++, а я и не обратил внимания. Extern линковку добавил.

А вот что я должен был скопипастить их хидера - это я не понял, зачем мне копипастить, если я весь хидер целиком подключаю в проект

dosikus
Offline
Зарегистрирован: 11.03.2017

b707 пишет:

А вот что я должен был скопипастить их хидера - это я не понял, зачем мне копипастить, если я весь хидер целиком подключаю в проект

 

Это к dimax и к его рукоблудии на аурдунье...

И это, ну ни хидер ни разу , хэддер или хедер , заголовок короче , а хидер - скрывальщик...

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

mixail844 пишет:

dimax,скажите ,  почему вы не используете полную CMSIS овскую нотацию ? 

2 причины. (1) люблю краткость :) (2) все дефайны всё равно не запомнить, а куда-то подглядывать -только отвлекать мозг лишней нагрузкой.

mixail844 пишет:

вместо
TIM1->CCMR1=(3<<12)|(3<<4);//toogle mode 
 TIM1->CCMR1 = ((TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2M_1) << TIM_CCMR1_OC2M) | ( (TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 ) << TIM_CCMR1_OC1M) ; // хоть и длиней ,но более читабельней 

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

 

dosikus
Offline
Зарегистрирован: 11.03.2017

dimax, можно так оформлять...

TIM2->CCMR1  = TIM_CCMR1_OC1M_2 
	    |  TIM_CCMR1_OC1M_1
	    |  TIM_CCMR1_OC1PE
	    |  TIM_CCMR1_OC2M_2 
	    |  TIM_CCMR1_OC2M_1
	    |  TIM_CCMR1_OC2PE;
						
TIM2->CCMR2  = TIM_CCMR2_OC3M_2 
	    |  TIM_CCMR2_OC3M_1
	    |  TIM_CCMR2_OC3PE
	    |  TIM_CCMR2_OC4M_2 
	    |  TIM_CCMR2_OC4M_1
	    |  TIM_CCMR2_OC4PE;
						
TIM2->CCER   = TIM_CCER_CC1E
            |  TIM_CCER_CC2E
	    |  TIM_CCER_CC3E
	    |  TIM_CCER_CC4E; 

 

 

dosikus
Offline
Зарегистрирован: 11.03.2017

dimax пишет:

2 причины. (1) люблю краткость :) (2) все дефайны всё равно не запомнить, а куда-то подглядывать -только отвлекать мозг лишней нагрузкой.
 

Если знать нотацию можно и ни куда и не подглядывать, главное запомнить:

TIM_CCMR1_OC1M

Домен_Регистр_Бит 

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

начал новый проект в Keil5, решил начать делать вес по науке C, что то ругается на определение функции, ниже три файла

//main.c
#include "stm32f30x.h"
#include "dmfcomm.h"

void startDmfDevice(void) {
    current_millis = 1;
}

int main(void) {
    testbyte = 1;
    initDmfDevice();
    startDmfDevice();
    while (1){
    }
}

-

//dmfcomm.h

#ifndef DMFCOMM_H
#define DMFCOMM_H

extern unsigned long current_millis;

extern unsigned char initDmfDevice(void);

unsigned char testbyte = 0;

#endif

-

//dmfcomm.cpp

unsigned long current_millis;

unsigned char initDmfDevice(void) {
    current_millis = 0;
}

void SysTick_Handler(void)
{
    ++current_millis;
}


- ошибка

.\Objects\dmf4stm01.axf: Error: L6218E: Undefined symbol initDmfDevice (referred from main.o).

 

b707
Offline
Зарегистрирован: 26.05.2017

andycat пишет:

.\Objects\dmf4stm01.axf: Error: L6218E: Undefined symbol initDmfDevice (referred from main.o).

 

в файле dmfcomm.h в описании функции уберите extern, оно тут лишнее

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

b707 пишет:

andycat пишет:

.\Objects\dmf4stm01.axf: Error: L6218E: Undefined symbol initDmfDevice (referred from main.o).

 

в файле dmfcomm.h в описании функции уберите extern, оно тут лишнее

пробовал, убрал еще раз - не помогло (

ошибка та же

b707
Offline
Зарегистрирован: 26.05.2017

andycat пишет:

ошибка та же

а исходник ( dmfcomm.cpp ) подключили к проекту? - он ведь сам не подключится и включения .h файла недостаточно

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

b707 пишет:

andycat пишет:

ошибка та же

а исходник ( dmfcomm.cpp ) подключили к проекту? - он ведь сам не подключится и включения .h файла недостаточно

конечно, в списке файлов проекта есть, все хорошо, причем я попробовал в  dmfcomm.h добавить тестовую переменную - главный модуль main.c все отлично видит

b707
Offline
Зарегистрирован: 26.05.2017

уточняю - .cpp надо подключить, а не .h

Если подключили - тогда последнее что могу посоветовать - сначала Clean, потом Rebuild All или как там в кейле...

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Спасибо, починил:

переименовал из .cpp в .c , переподключил к проекту и все заработало

странно...не понимаю (

 

b707
Offline
Зарегистрирован: 26.05.2017

andycat пишет:

Спасибо, починил:

переименовал из .cpp в .c , переподключил к проекту и все заработало

странно...не понимаю (

ну это что-то очень похожее на то. что было у меня пятью сообщениями выше.

При C++ линковке оптимизатор почему-то может выкинуть процедуру из кода, при С- линковке - нет. Почему. если честно. я пока не понял, хотя сегодня с утра почитал на эту тему заметку на СтэкОверфлоу

Правда. мне казалось. что это не относится к случаям, когда процедура вызывается явно, как у вас в main()

Может кто-то из старших пояснит...

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

думаю все таки я что то криво сделал изначально в проекте, возможно с настройками путей компилияции откуда брать исходники, постараюсь сделать все с нуля, если повториться вопрос - обязательно напишу.