Ярлыки

_GetPixelIndex (1) _SetPixelIndex (1) 3-phase (1) 800x480 (1) АЦП (1) генератор (1) синхронный усилитель (2) структура (1) учебный курс (1) шаговый двигатель (1) ШИМ (2) accert (1) AD7608 (1) AD8429 (1) ADC (5) amplifer (1) arccos (1) arcsin (1) arctang (2) arctg (3) ARM (2) arm_sqrt_q15 (2) assembler (6) ASSERT (1) atan (2) bit (1) Bitband (1) boot (3) bootlloader (1) BUTTON (1) C (5) C# (1) CAN (2) CC2530 (5) CMSIS (4) command (1) Cordic (1) Core746I (1) CubeMX (4) DBGMCU (2) debug (2) debug.ini (1) delegate (1) Digital Potentiometers (1) DigitalPOT (1) Discovery (1) DMA (9) DMA2D (1) DSP (1) DSP library (1) DWT (1) EFM32 (5) EmWin (9) EXTI (1) FATFS (1) FMC (2) FreeRTOS (2) gl868-dual cmux (1) GPIO (4) GUI (2) GUIBuilder (1) GUIDRV_CompactColor_16 (1) HAL (3) HappyGecko (1) Hard Fault (2) heap (1) I2C (1) ID (1) ILI9320 (1) ILI9325 (1) Initialisation (1) InitLTDC (1) Instrumentithion (1) Interrupt (4) ITR (1) JTAG (1) Keil (5) LCDConf (2) lock-in (1) LTCD (1) LTDC (3) main (1) memory (1) MINI_STM32 Revision 01 (1) nBoot0 (1) NVIC (1) OnePulse (2) OSAL (4) pack (1) phase (1) printf (3) Pulse (1) PWM (12) RCC (2) RCR (1) Register (1) RESET (2) RS232 (3) RSS (1) RTC (3) RTOS-RTX (1) RTT (1) RTX-RTOS (1) SDCard (1) SDRAM (6) Segger (2) SPI (3) sqrt (3) SSD1298 (1) SSD1963 (1) Standart Peripherial Library (3) STANDBAY (1) startup (1) STemWin (8) stepper motor (1) STlink (2) STM32 (17) STM32429ZI (1) STM32Cube (1) STM32DBG.IN (1) STM32F (28) STM32F0 (4) STM32F1 (13) STM32F4 (10) STM32F4 Discovery (1) STM32F407ZG (1) STM32F429 (2) STM32F746 (1) STOP (1) string (1) struct (1) SWD (1) SWD JTAG (1) Synhronization (1) system_stm32f4xx.c (1) SystemInit (1) SysTick (1) task (4) telit (1) TIM (27) typedef (1) UART (1) USART (9) viewer (2) WM_PAINT (1) Z-stack (5) ZigBee (5)

среда, 21 января 2015 г.

TIM PWM Init

For TIM2-TIM5

void PwmInit(void)
{
   //ch1 -PA0
   GPIOA->CRL |= GPIO_CRL_MODE0;  //50Mhz
   GPIOA->CRL &= ~GPIO_CRL_CNF0; //clear CNF[1:0] for PA0 
   GPIOA->CRL |= GPIO_CRL_CNF0_1; //output Push-Pull in alternative function mode
   //ch2 - PA1
   GPIOA->CRL |= GPIO_CRL_MODE1;  //50Mhz
   GPIOA->CRL &= ~GPIO_CRL_CNF1; //clear CNF[1:0] for PA1 
   GPIOA->CRL |= GPIO_CRL_CNF1_1; //output Push-Pull in alternative function mode
   //ch3 - PA2
   GPIOA->CRL |= GPIO_CRL_MODE2;  //50Mhz
   GPIOA->CRL &= ~GPIO_CRL_CNF2; //clear CNF[1:0] for PA2 
   GPIOA->CRL |= GPIO_CRL_CNF2_1; //output Push-Pull in alternative function mode
   //ch4 - PA3
   GPIOA->CRL |= GPIO_CRL_MODE3;  //50Mhz
   GPIOA->CRL &= ~GPIO_CRL_CNF3; //clear CNF[1:0] for PA3 
   GPIOA->CRL |= GPIO_CRL_CNF3_1; //output Push-Pull in alternative function mode
   //TIM2 Settings
   RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
   TIM2->CR1 |= TIM_CR1_ARPE;  //autorelode mode
   TIM2->CCMR1 |= TIM_CCMR1_OC1PE | TIM_CCMR1_OC2PE;  //Output Compare Preload enable
   TIM2->CCMR2 |= TIM_CCMR2_OC3PE | TIM_CCMR2_OC4PE;
   //TIM2->PSC = 71;  //1us
   TIM2->ARR = 8000;  // 8000*14ns = 112us = 8928Hz
   TIM2->CCR1 = 4000; //ch1 1duty cycle = 50%
   TIM2->CCR2 = 4000; //ch2 1duty cycle = 50%
   TIM2->CCR3 = 4000; //ch2 1duty cycle = 50%
   TIM2->CCR4 = 4000; //ch2 1duty cycle = 50%
   //TIM2->CCER |= TIM_CCER_CC2P;  //polarity of output signal
   //Capture/Compare 2 output enable
   TIM2->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
   //Output Compare Mode - 110 - PWM mode 1
   TIM2->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1); 
   TIM2->CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1);
   TIM2->CCMR2 |= (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1);
   TIM2->CCMR2 |= (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1);
   //start counting
   TIM2->CR1 |= TIM_CR1_CEN;  
}


void InitTIM1(int enable)
{
  TIM1->CR1 = TIM_CR1_ARPE | TIM_CounterMode_Up;
  TIM1->ARR = 5*24-1; // период повторения, 0 - останов
  TIM1->PSC = 0;      // прескалер на 1, один тик = 1/24 мкс
  TIM1->RCR = 0;      //TIM_RepetitionCounter;
  
  // OC1
  TIM1->CCR1  = 12;    // 0.5мкс.
  TIM1->CCMR1 = TIM_OCMode_Toggle; //TIM_OCMode_PWM2;  
  TIM1->CCER  = TIM_OCPolarity_High | TIM_OutputState_Enable;
  // OC2
  TIM1->CCR2  = 24;     // 1.0us
  TIM1->CCMR1 |= TIM_OCMode_Toggle << 8;  
  TIM1->CCER  |= (TIM_OCPolarity_High | TIM_OutputState_Enable) <<4;  
  // OC 3
  TIM1->CCR3  = 36;     // 1.5us.
  TIM1->CCMR2 |= TIM_OCMode_PWM1;  
  TIM1->CCER  |= (  TIM_OCPolarity_High | TIM_OutputState_Enable 
                  | TIM_OCNPolarity_Low | TIM_OutputNState_Enable)<<8; 
   // OC4
  TIM1->CCR4  = 24;     // 1us
  TIM1->CCMR2 |= TIM_OCMode_PWM1 << 8;  
  TIM1->CCER  |= (TIM_OCPolarity_High | TIM_OutputState_Enable) <<12;  
  
  TIM1->EGR   = TIM_EGR_UG; // генерируем update event для загрузки всех теневых регистров
  TIM1->BDTR |= TIM_BDTR_MOE + 12; // разрешение выходных сигналов OCx + dead-time 0.5us

  // DMA Init
  TIM1->DIER = TIM_DIER_UDE;
  TIM1->DCR  =  (0<<8) | (&(TIM1->ARR) - &(TIM1->CR1))/sizeof(TIM1->CR1);
  DMA1_Channel5->CCR = 0
    | 0*DMA_CCR1_EN            // Channel enable
    | 0*DMA_CCR1_TCIE          // Transfer complete interrupt enable
    | DMA_CCR1_DIR           // Data transfer direction 1: Mem --> Periph
    | DMA_CCR1_CIRC          // Circular mode
    | 0*DMA_CCR1_PINC          // Peripheral increment mode
    | DMA_CCR1_MINC          // Memory increment mode
    | DMA_PeripheralDataSize_Word  // DMA_CCR1_PSIZE   PSIZE[1:0] bits (Peripheral size)
    | DMA_MemoryDataSize_HalfWord  // DMA_CCR1_MSIZE   MSIZE[1:0] bits (Memory size)
    | (3<<12)  //*DMA_CCR1_PL      // PL[1:0] bits(Channel Priority level)
    | 0*DMA_CCR1_MEM2MEM;    // Memory to memory mode
  
  DMA1_Channel5->CNDTR = 2;
  DMA1_Channel5->CPAR = (uint32_t)&(TIM1->DMAR);
  DMA1_Channel5->CMAR = (uint32_t) dmabuf;
  DMA1_Channel5->CCR |= DMA_CCR1_EN;    // Channel enable
  // end DMA Init

  if(enable) TIM1->CR1 |= TIM_CR1_CEN;   // разрешаем счёт

}


void Timer1_Init (void)
{
    RCC->APB2ENR  |= (1<<0);                     //вкл. тактиров. таймера1
    TIM1->PSC = 20;                                      //делитель
    TIM1->CCMR1 |= (7<<12)|(7<<4);          //+ канал 1 и 2 - ШИМ
    TIM1->CCMR2 |= (7<<12)|(7<<4);          //+ канал 3 и 4 - ШИМ
    TIM1->CCER  |= (1<<12)|(1<<8)|(1<<4)|(1<<0);      //+
    TIM1->BDTR    |= (1<<15);
    TIM1->CCR1 = 0xFFFF;                            //значение ШИМ канал 1 (ТЕМ1.1) чем меньше тем длиннее 1
    TIM1->CCR2 = 0xFFFF;                            //значение ШИМ канал 2 (ТЕМ1.2)
    TIM1->CCR3 = 0xFFFF;                            //значение ШИМ канал 3 (ТЕМ2.1)
    TIM1->CCR4 = 0xFFFF;                            //значение ШИМ канал 4 (ТЕМ2.2)
    TIM1->CR1 |= (1<<0);                            //вкл. таймер 1

}


суббота, 17 января 2015 г.

Контроль правильности входных параметров (FULL_ASSERT)

Все функции библиотеки STM32F10x SPL используют для проверки своих аргументов макрос assert_param.

Этот макрос выполняет проверку выражения с участием проверяемого аргумента функции на равенство нулю. Если значение выражения равно нулю, то вызывается функция-обработчик ошибки аргумента assert_failed, в противном случае (выражение не равно нулю) проверка аргумента проходит успешно.
По умолчанию проверка правильности входных данных выключена и все макросы assert_param ни чего не делают. Что бы использовать проверку необходимо добавить в Defines определение USE_FULL_ASSERT и в коде добавить функцию:
void assert_failed(uint8_t* file, uint32_t line)
{
  while (1){}
}
В ней и зависнет программа, если вы введете что нибудь неправильно. Переменные file и line - это файл и строка, в которой неудачно выполнился assert_param.
Например представим что мы случайно попытались включить тактирование TIM3 на шине APB1:
RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
На самом же деле TIM3 подключен к шине APB1 и код не включит тактирование таймера. И прерывания не будут вызывается. При запуске Debug в функции assert_failed на строке с while нужно поставить точку прерывания, и нажать Resume (F8). В результате макро assert_param найдет ошибку, и программа зависнет в бесконечном while.
?

TIM3 PWM

#include "stm32f10x.h"

// стандартная процедура настройки пинов A06,A07, альтернативный пуш-пулл выход
void pbii_PWM_GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6|GPIO_Pin_7;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void pbii_PWM_RCC_Configuration(void)
{
  /* TIM3 clock enable */ // разрешить клокирование TIM3 и альтернативного ввода-
                          // вывода на порт B
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA and GPIOB clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
}

void pbii_PWM_TIM3_Init(void)
{ // установка начальных значений шима
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  uint16_t CCR1_Val = 333;
  uint16_t CCR2_Val = 249;
  uint16_t PrescalerValue = 0;

   // разрешить клокирование ШИМа
  /* System Clocks Configuration */
  pbii_PWM_RCC_Configuration();
  // установить кофигурацию штырей ввода-вывода для ШИМа
  /* GPIO Configuration */
  pbii_PWM_GPIO_Configuration();
  // инициализация TIM3 режиме ШИМ целиком выдрана из примеров к стандартной
  // библиотеке STM32  используются 2 из 4х каналов ШИМ
  /* -----------------------------------------------------------------------
    TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles:
    The TIM3CLK frequency is set to SystemCoreClock (Hz), to get TIM3 counter
    clock at 24 MHz the Prescaler is computed as following:
     - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density
    and Connectivity line devices and to 72 MHz for Low-Density Value line and
    Medium-Density Value line devices

    The TIM3 is running at  KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
                                                  = 72 MHz / 1800 = 40 KHz
    TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
    TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
  ----------------------------------------------------------------------- */
  /* Compute the prescaler value */
  PrescalerValue = (uint16_t) (SystemCoreClock / 72000000) - 1;
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 1799;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 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_Enable);
  TIM_ARRPreloadConfig(TIM3, ENABLE);

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


int main(void)
{

pbii_PWM_RCC_Configuration();
pbii_PWM_GPIO_Configuration();
pbii_PWM_TIM3_Init();

  while (1)
  {
  }
}

3 phase sinusoidal pulse width modulation (PWM) TIM1

#include "stm32f10x.h"

int i=0;

//sinusoidal data for 256 point 
const u16 PWMdata[256]={
2884,2954,3025,3095,3165,3235,3305,3375,3444,3512, 
3581,3648,3715,3782,3848,3914,3978,4042,4105,4168, 
4229,4290,4349,4408,4466,4522,4578,4633,4686,4738, 
4789,4839,4887,4934,4980,5024,5067,5109,5149,5187, 
5224,5260,5294,5326,5357,5387,5414,5440,5465,5487, 
5508,5528,5545,5561,5575,5588,5598,5607,5614,5614, 
5614,5614,5614,5614,5614,5614,5607,5598,5588,5575, 
5561,5545,5528,5508,5487,5465,5440,5414,5387,5357, 
5326,5294,5260,5224,5187,5149,5109,5067,5024,4980, 
4934,4887,4839,4789,4738,4686,4633,4578,4522,4466, 
4408,4349,4290,4229,4168,4105,4042,3978,3914,3848, 
3782,3715,3648,3581,3512,3444,3375,3305,3235,3165, 
3095,3025,2954,2884,2813,2742,2672,2601,2531,2461, 
2391,2321,2251,2182,2114,2045,1978,1911,1844,1778, 
1712,1648,1584,1521,1458,1397,1336,1277,1218,1160, 
1104,1048,993 ,940 ,888 ,837 ,787 ,739 ,692 ,646 , 
602 ,559 ,517 ,477 ,439 ,402 ,366 ,332 ,300 ,269 , 
239 ,212 ,186 ,161 ,139 ,118 ,98 ,81 ,65 ,51 , 
38 ,28 ,19 ,12 ,10 ,10 ,10 ,10 ,10 ,10 , 
12 ,19 ,28 ,38 ,51 ,65 ,81 ,98 ,118 ,139 , 
161 ,186 ,212 ,239 ,269 ,300 ,332 ,366 ,402 ,439 , 
477 ,517 ,559 ,602 ,646 ,692 ,739 ,787 ,837 ,888 , 
940 ,993 ,1048,1104,1160,1218,1277,1336,1397,1458, 
1521,1584,1648,1712,1778,1844,1911,1978,2045,2114, 
2182,2251,2321,2391,2461,2531,2601,2672,2742,2813, 
2884,2954,3025,3095,3165,3235, 
};
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
TIM_OCInitTypeDef TIM_OCInitStructure; 
GPIO_InitTypeDef GPIO_InitStructure; 
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

ErrorStatus HSEStartUpStatus;

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


int main(void) 

#ifdef DEBUG 
debug(); 
#endif 
/* System Clocks Configuration */ 
RCC_Configuration();

/* NVIC configuration */ 
NVIC_Configuration();

/* GPIO Configuration */ 
GPIO_Configuration();

/* TIM1 Configuration --------------------------------------------------- 
Generates 6 complemantary PWM signals with 4 sinusoidal data duty cycles: 
TIM1CLK = 72 MHz, Prescaler = 0, TIM1 counter clock = 72 MHz 
TIM1 frequency = TIM1CLK/(TIM1_Period + 1) = 
Time Base configuration */

/* TIM1 Peripheral Configuration ----------------------------------------*/ 
/* Time Base configuration */ 
TIM_TimeBaseStructure.TIM_Prescaler = 0; 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_TimeBaseStructure.TIM_Period = 5625-1; 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

/* Channel 3 Configuration in PWM mode */ 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
TIM_OCInitStructure.TIM_Pulse = PWMdata[0];//127; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC3Init(TIM1, &TIM_OCInitStructure);

/* Channel 2 Configuration in PWM mode */ 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
TIM_OCInitStructure.TIM_Pulse = PWMdata[0];//127; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC2Init(TIM1, &TIM_OCInitStructure);

/* Channel 1 Configuration in PWM mode */ 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
TIM_OCInitStructure.TIM_Pulse = PWMdata[5];//127; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC1Init(TIM1, &TIM_OCInitStructure);

/* Automatic Output enable, Break, dead time and lock configuration*/ 
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; 
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; 
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; 
TIM_BDTRInitStructure.TIM_DeadTime = 5; 
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; 
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; 
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
/* TIM1 counter enable */
//clear tim1 interrupt flag 
TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
//TIM1 interrupt source
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
TIM_Cmd(TIM1, ENABLE);

/* Main Output Enable */ 
TIM_CtrlPWMOutputs(TIM1, ENABLE);
while (1) 
{


}

/******************************************************************************* 
* Function Name : RCC_Configuration 
* Description : Configures the different system clocks. 
* Input : None 
* Output : None 
* Return : None 
*******************************************************************************/
void RCC_Configuration(void) 

/* RCC system reset(for debug purpose) */ 
RCC_DeInit();

/* Enable HSE */ 
RCC_HSEConfig(RCC_HSE_ON);

/* Wait till HSE is ready */ 
HSEStartUpStatus = RCC_WaitForHSEStartUp();

if (HSEStartUpStatus == SUCCESS) 

/* Enable Prefetch Buffer */ 
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

/* Flash 2 wait state */ 
FLASH_SetLatency(FLASH_Latency_2);

/* HCLK = SYSCLK */ 
RCC_HCLKConfig(RCC_SYSCLK_Div1);

/* PCLK2 = HCLK */ 
RCC_PCLK2Config(RCC_HCLK_Div1);

/* PCLK1 = HCLK/2 */ 
RCC_PCLK1Config(RCC_HCLK_Div2);

/* ADCCLK = PCLK2/4 */ 
RCC_ADCCLKConfig(RCC_PCLK2_Div6);

/* PLLCLK = 8MHz * 9 = 72 MHz */ 
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

/* Enable PLL */ 
RCC_PLLCmd(ENABLE);

/* Wait till PLL is ready */ 
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) 
{}

/* Select PLL as system clock source */ 
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

/* Wait till PLL is used as system clock source */ 
while (RCC_GetSYSCLKSource() != 0x08) 
{} 
}

/* TIM1, GPIOA and GPIOB clock enable */ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | 
RCC_APB2Periph_GPIOB| 
RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
}
/******************************************************************************* 
* Function Name : GPIO_Configuration 
* Description : Configure the TIM1 Pins. 
* Input : None 
* Output : None 
* Return : None 
*******************************************************************************/ 
void GPIO_Configuration(void) 

GPIO_InitTypeDef GPIO_InitStructure;

/* GPIOA Configuration: Channel 1, 2, 3 and 4 as alternate function push-pull */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* GPIOB Configuration: Channel 1N, 2N and 3N as alternate function push-pull */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_6 | GPIO_Pin_7; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
}

/******************************************************************************* 
* Function Name : NVIC_Configuration 
* Description : Configures Vector Table base location. 
* Input : None 
* Output : None 
* Return : None 
*******************************************************************************/ 
void NVIC_Configuration(void) 

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM 
/* Set the Vector Table base location at 0x20000000 */ 
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
#else /* VECT_TAB_FLASH */ 
/* Set the Vector Table base location at 0x08000000 */ 
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 
#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; 
//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure);
}
#ifdef DEBUG 
/******************************************************************************* 
* Function Name : assert_failed 
* Description : Reports the name of the source file and the source line number 
* where the assert_param error has occurred. 
* Input : - file: pointer to the source file name 
* - line: assert_param error line source number 
* Output : None 
* Return : None 
*******************************************************************************/ 
void assert_failed(u8* file, u32 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

/******************* *****END OF FILE****/

void TIM1_CC_IRQHandler(void)

i++;
TIM_OCInitStructure.TIM_Pulse = PWMdata[i];
TIM_OC1Init(TIM1, &TIM_OCInitStructure); 
TIM_OC2Init(TIM1, &TIM_OCInitStructure); 
TIM_OC3Init(TIM1, &TIM_OCInitStructure);

/* check if array's index reaches the max: 255 */
if (i == 255)
{
i = 0;
}
TIM_ClearFlag(TIM1,TIM_FLAG_CC1);
}

среда, 14 января 2015 г.

STM32F103 External interrupt/event controller

External interrupt/event controller block diagram

Контроллер имеет 18 линий прерывания/событий, из них 16 линий можно подключить к линиям ввода-вывода. Генерирование прерываний/событий возможно по нарастающему и спадающему фронту входного сигнала, так же возможно принудительно (программно) сформировать прерывания/событие) путем записи соответствующего бита регистра Software interrupt event register (EXTI_SWIER):


Подключение GPIO к 16 линиям прерывания осуществляется следующим образом


The four other EXTI lines are connected as follows:
● EXTI line 16 is connected to the PVD output
● EXTI line 17 is connected to the RTC Alarm event
● EXTI line 18 is connected to the USB Wakeup event
● EXTI line 19 is connected to the Ethernet Wakeup event (available only in connectivity
line devices)

В таблице векторов прерываний следующее распределение векторов:
  • EXTI0 – индивидуальный для линии 0
  • EXTI1 – индивидуальный для линии 1
  • EXTI2 – индивидуальный для линии 2
  • EXTI3 – индивидуальный для линии 3
  • EXTI4 – индивидуальный для линии 4
  • EXTI5-9 – общий для линий с 5 по 9
  • EXTI10-15 – общий для линий с 10 по 15

To improve software efficiency, the CMSIS simplifies the NVIC register presentation. In the CMSIS: • The Set-enable, Clear-enable, Set-pending, Clear-pending and Active Bit registers map to arrays of 32-bit integers, so that: – The array ISER[0] to ISER[2] corresponds to the registers ISER0-ISER2 – The array ICER[0] to ICER[2] corresponds to the registers ICER0-ICER2 – The array ISPR[0] to ISPR[2] corresponds to the registers ISPR0-ISPR2 – The array ICPR[0] to ICPR[2] corresponds to the registers ICPR0-ICPR2 – The array IABR[0] to IABR[2] corresponds to the registers IABR0-IABR2. • The 8-bit fields of the Interrupt Priority Registers map to an array of 8-bit integers, so that the array IP[0] to IP[67] corresponds to the registers IPR0-IPR67, and the array entry IP[n] holds the interrupt priority for interrupt n. The CMSIS provides thread-safe code that gives atomic access to the Interrupt Priority Registers. For more information see the description of the NVIC_SetPriority function in NVIC programming hints in Table 41 shows how the interrupts, or IRQ numbers, map onto the interrupt registers and corresponding CMSIS variables that have one bit per interrupt.


  • ISER — Interrupt Set Enable Register. Запись бита в нужную позицию включает прерывание.
  • ICER — Interrupt Clr Enable Register. Запись сюда наоборот выключает прерывание.
Запись 1 в биты этих регистров запрещает/разрешает прерывания. Запись 0 не делает ничего, а чтение возвращает текущее состояние разрешено/запрещено
 
  • ISPR — Interrupt Set Pending Register. Поставить прерывание в ожидание.
  • IСPR — Interrupt Clr Pending Register. Сбросить прерывание с ожидания.
Запись 1 в биты этих регистров ставит/снимает прерывания в очередь на исполнение. Запись 0 не делает ничего, а чтение возвращает текущее состояние прерывания. Ждет он обработки или уже нет. Т.е. если в этом регистре где то стоит бит 1, значит это прерывание еще не вызывалось.
  • IABR — Interrupt active bit registers. Регистр показывающий активно ли в данный момент прерывание. Автоматически ставится когда мы попадаем в обработчик и автоматом же снимается когда мы уходим из него. Этот регистр можно только читать.
External Interrupts
                DCD     WWDG_IRQHandler         ; Window Watchdog      Номер 0
                DCD     PVD_IRQHandler          ; PVD through EXTI Line detect  Номер 1
                DCD     TAMPER_IRQHandler       ; Tamper     Номер 2
                DCD     RTC_IRQHandler          ; RTC           Номер 3

For STM32F2 

 ; External Interrupts
                DCD     WWDG_IRQHandler          ; Window Watchdog
                DCD     PVD_IRQHandler           ; PVD through EXTI Line detect
                DCD     TAMPER_IRQHandler        ; Tamper
                DCD     RTC_IRQHandler           ; RTC
                DCD     FLASH_IRQHandler         ; Flash
                DCD     RCC_IRQHandler            ; RCC
                DCD     EXTI0_IRQHandler          ; EXTI Line 0
                DCD     EXTI1_IRQHandler          ; EXTI Line 1
                DCD     EXTI2_IRQHandler          ; EXTI Line 2
                DCD     EXTI3_IRQHandler          ; EXTI Line 3
                DCD     EXTI4_IRQHandler          ; EXTI Line 4
                DCD     DMAChannel1_IRQHandler    ; DMA Channel 1
                DCD     DMAChannel2_IRQHandler    ; DMA Channel 2
                DCD     DMAChannel3_IRQHandler    ; DMA Channel 3
                DCD     DMAChannel4_IRQHandler    ; DMA Channel 4
                DCD     DMAChannel5_IRQHandler    ; DMA Channel 5
                DCD     DMAChannel6_IRQHandler    ; DMA Channel 6
                DCD     DMAChannel7_IRQHandler    ; DMA Channel 7
                DCD     ADC_IRQHandler            ; ADC
                DCD     USB_HP_CAN_TX_IRQHandler  ; USB High Priority or CAN TX
                DCD     USB_LP_CAN_RX0_IRQHandler ; USB Low  Priority or CAN RX0
                DCD     CAN_RX1_IRQHandler        ; CAN RX1
                DCD     CAN_SCE_IRQHandler        ; CAN SCE
                DCD     EXTI9_5_IRQHandler        ; EXTI Line 9..5
                DCD     TIM1_BRK_IRQHandler       ; TIM1 Break
                DCD     TIM1_UP_IRQHandler        ; TIM1 Update
                DCD     TIM1_TRG_COM_IRQHandler   ; TIM1 Trigger and Commutation
                DCD     TIM1_CC_IRQHandler        ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler           ; TIM2
                DCD     TIM3_IRQHandler           ; TIM3
                DCD     TIM4_IRQHandler           ; TIM4
                DCD     I2C1_EV_IRQHandler        ; I2C1 Event
                DCD     I2C1_ER_IRQHandler        ; I2C1 Error
                DCD     I2C2_EV_IRQHandler        ; I2C2 Event
                DCD     I2C2_ER_IRQHandler        ; I2C2 Error
                DCD     SPI1_IRQHandler           ; SPI1
                DCD     SPI2_IRQHandler           ; SPI2
                DCD     USART1_IRQHandler         ; USART1
                DCD     USART2_IRQHandler         ; USART2
                DCD     USART3_IRQHandler         ; USART3
                DCD     EXTI15_10_IRQHandler      ; EXTI Line 15..10
                DCD     RTCAlarm_IRQHandler       ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler      ; USB Wakeup from suspend

void NVIC_SetPriorityGrouping(uint32_t priority_grouping) // Задать группы/подгруппы приоритетов
void NVIC_EnableIRQ(IRQn_t IRQn)     // Включить IRQn
void NVIC_DisableIRQ(IRQn_t IRQn)    // Выключить IRQn 
uint32_t NVIC_GetPendingIRQ (IRQn_t IRQn)    // Вернуть true (точнее IRQ-Number) если  IRQn в ожидании
void NVIC_SetPendingIRQ (IRQn_t IRQn)    // Поставить IRQn в ожидание 
void NVIC_ClearPendingIRQ (IRQn_tIRQn)    // Выкинуть из очереди на ожидание IRQn 
uint32_t NVIC_GetActive (IRQn_t IRQn)    // Функция "Бля, где это я?" Возвращает номер текущего активного прерывания если такое имеется 
void NVIC_SetPriority (IRQn_t IRQn, uint32_t priority)  // Задать приоритет IRQn
uint32_t NVIC_GetPriority (IRQn_t IRQn)    // Считать приоритет IRQn
void NVIC_SystemReset (void)     // Reset the system

// Разрешаем прерывания в периферии для выводов 1 и 2. 
EXTI->IMR |=(EXTI_IMR_MR1 | EXTI_IMR_MR2);

Регистры настроек

EXTI_IMR – разрешение прерываний на конкретной линии
EXTI_EMR – разрешение событий на конкретной линии
EXTI_RTSR – установить бит для вызова прерывания по нарастающему фронту.
EXTI_FTSR– установить бит для вызова прерывания спаду импульса.
EXTI_SWIER - принудительный (программный) вызов прерывания от конкретной линии
EXTI_PR – регистр флагов. Устанавливаются биты при вызове прерывания от конкретного вывода

Для начала работы с модулем EXTI необходимо выполнить минимальный набор настроек, соблюдая следующую последовательность: 

1 Разрешить внешнее прерывание на определенной линии 
2 Установить вызов прерывания по нарастающему фронту или по спаду 
3 Разрешить прерывания EXTI