Ярлыки

_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)
Показаны сообщения с ярлыком STM32F. Показать все сообщения
Показаны сообщения с ярлыком STM32F. Показать все сообщения

вторник, 13 сентября 2016 г.

STM32F ADC config (CMSIS, HAL SPL)

CMSIS

Настройка преобразования первых 8ми регулярных каналов АЦП по запуску из программы с использованием канала DMA

// настройка ADC1
        RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //  такты на ADC1

        ADC1->SMPR2 |= ADC_SMPR2_SMP0 | ADC_SMPR2_SMP1
        | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP3 | ADC_SMPR2_SMP4
        | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP6 | ADC_SMPR2_SMP7;       // количество циклов преобразования 239.5

        ADC1->SQR1 |= ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0; // длина последовательности регулярных каналов = 8;
        // добавление в последовательность каналов
        ADC1->SQR2 |= ADC_SQR2_SQ8_2 | ADC_SQR2_SQ8_1 | ADC_SQR2_SQ8_0 //канал 7
        | ADC_SQR2_SQ7_2 | ADC_SQR2_SQ7_1;                             // канал 6

        ADC1->SQR3 |=  ADC_SQR3_SQ6_2 | ADC_SQR3_SQ6_0                 //канал 5
        | ADC_SQR3_SQ5_2                                               //канал 4
        | ADC_SQR3_SQ4_1 | ADC_SQR3_SQ4_0                              //канал 3
        | ADC_SQR3_SQ3_1                                               //канал 2
        | ADC_SQR3_SQ2_0;                                              // канал 1
        //канал 0 включен по умолчанию т.к. в младших битах SQ3 0

//      ADC1->CR2 |= ADC_CR2_CONT;      // включаем если нужно непрерывное преобразование последовательности в цикле

        ADC1->CR2 |= ADC_CR2_DMA //включаем работу с DMA
        | ADC_CR2_EXTTRIG //включаем работу от внешнего события
        | ADC_CR2_EXTSEL //выбираем триггером запуска регулярной последовательности событие SWSTART
        | ADC_CR2_JEXTSEL; // выбираем триггером запуска выделенной последовательности событие JSWSTART дабы эти каналы не отнимали у мк времени
        ADC1->CR1 |= ADC_CR1_SCAN; // включаем автоматический перебор всех каналов в последовательности

//макросы для включения/выключения АЦП с DMA
#define ADC_ON ADC1->CR2 |= ADC_CR2_ADON;  \
                                ADC1->CR2 |= ADC_CR2_SWSTART; \
                                DMA1_Channel1->CCR |= DMA_CCR1_TCIE | DMA_CCR1_EN;      //включаем преобразование прерывание DMA
#define ADC_OFF ADC->CR2 &= (~(ADC_CR2_ADON)); \
                                DMA1_Channel1->CCR &= (~(DMA_CCR1_TCIE | DMA_CCR1_EN)); //выключаем преобразование и прерывание DMA
     

===============================================================

STM32 STANDBAY STOP mode

#define RCC_APB1ENR_PWREN ((unsigned long)0x10000000)
#define SCB_SCR_SLEEPONEXIT ((u8)0x02) /*!< Sleep on exit bit */
#define SCB_SCR_SLEEPDEEP ((u8)0x04) /*!< Sleep deep bit */
#define SCB_SCR_WUP ((u16)0x100)
#define PWR_CR_PDDS ((u16)0x0002) /*!< Power Down Deepsleep */
#define PWR_CR_CWUF ((u16)0x0004) /*!< Clear Wakeup Flag */

void GoStandBy(void){

RCC->APB1ENR |= RCC_APB1ENR_PWREN; 

/* Clear Wakeup flag */
PWR->CR |= PWR_CR_CWUF; 
/* Select STANDBY mode */
PWR->CR |= PWR_CR_PDDS; 
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* Wakeup pin enable */
PWR->CSR |= SCB_SCR_WUP;
__wfi(); //команда ухода в сон


Перевод в STOP режим (ADC & DAC):

ADC_Cmd(ADC1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, DISABLE);
DAC_Cmd(DAC_Channel_1,DISABLE);
DAC_Cmd(DAC_Channel_2,DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, DISABLE); 
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);


Stop

Останов процессора является базовым режимом ядра Cortex-M3, поэтому присутствует во всех микроконтроллерах. Он накладывает большие ограничения на работу внутренних схем, вследствие чего является наименее энергозатратным, из «спящих» режимов. Так, в данном режиме, производится остановка практически всей периферии микроконтроллера, а также любого основного тактового генератора. Вариантом режима Stop является случай, когда в работе остается модуль часов реального времени с соответствующим источником частоты. Для обеспечения минимального энергопотребления в данном режиме рекомендуется настройка внутреннего регулятора напряжения, а также отключение систем VrefntBORPVDADCDAC и встроенного датчика температуры. Состояние линий ввода вывода при переходе в режим STOP не изменяется, содержимое памяти и регистров сохраняется.
Для перевода в режим останова необходимо выполнить следующие действия:
  • Установить бит SLEEPDIP в регистре SCB
  • Очистить бит PDDS в регистре PWR_CR
  • Очистить бит WUF в регистре PWR_CSR
  • Настроить регулятор напряжения LPSDSR в регистре PWR_CR
  • Настроить событие или прерывание выхода из режима STOP
  • Подать команду WFI или WFE

Stadby

Режим ожидания стоит несколько особняком от других вариантов пониженного энергопотребления по причине отключения процессора и памяти. Фактически данный режим равноценен состоянию сброса. Содержимое памяти и всех регистров за исключением PWR_CSR теряется. Все порты ввода/вывода переводятся в высокоимпедансное состояние за исключением следующих линий, отвечающих за пробуждение процессора:
  • вход сброса
  • RTC_AF1 (PC13), если он сконфигурирован как вход для функций Wakeup (WKUP2), защиты данных (tamper), захвата времени (time-stamp), или как выход тревоги по таймеру (RTC Alarm), или тактовый выход RTC clock.
  • PA0 и PE6, если они сконфигурированы в качестве входов сигнала пробуждения WKUP.
Выход из режима ожидания выполняется при поступлении сигналов сброса, внешних сигналов пробуждения (WKUP), событий часов реального времени, событий несанкционированного доступа к данным или записи временной метки.
Для перевода в режим останова необходимо выполнить следующие действия:

  • Установить бит SLEEPDIP в регистре SCB
  • Включить бит PDDS в регистре PWR_CR
  • Очистить бит WUF в регистре PWR_CSR
  • Очистить флаги источников пробуждения
  • Подать команду WFI или WFE
Чтобы отладчик работал со спящими режимами нужно установить следующие биты
#if defined(DEBUG)
  DBGMCU_Config(DBGMCU_SLEEP, ENABLE);
  DBGMCU_Config(DBGMCU_STOP, ENABLE);
  DBGMCU_Config(DBGMCU_STANDBY, ENABLE);
#endif


понедельник, 1 августа 2016 г.

STM32 config

В STM32 перед тем как что то использовать НЕОБХОДИМО РАЗРЕШИТЬ это что то . По умолчанию все находится в отключенном состоянии . Поэтому любая инициализация периферии должна начинаться со строчек типа этого даже если напрямую в мануале нет об этом упоминаний 

/* Enable ADCx, DMA and GPIO clocks ****************************************/ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

Если используются прерывания то необходимо также настроить контроллер по типу этого 

static void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* Configure the preemption priority and subpriority:
- 1 bits for pre-emption priority: possible value are 0 or 1 
- 3 bits for subpriority: possible value are 0..7
- Lower values gives higher priority 
*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

/* Enable the WAKEUP_BUTTON_EXTI_IRQn Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = WAKEUP_BUTTON_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ubPreemptionPriorityValue;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Enable the KEY_BUTTON_EXTI_IRQn/TAMPER_BUTTON_EXTI_IRQn Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = BUTTON_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

и не забыть создать обработчик прерывания 


/**
* @brief This function handles External line 0 interrupt request.
* @param None
* @retval None
*/
void EXTI0_IRQHandler(void)
{
/* Generate SysTick exception */
SCB->ICSR |= 0x04000000;

/* Clear WAKEUP_BUTTON_EXTI_LINE pending bit */
EXTI_ClearITPendingBit(WAKEUP_BUTTON_EXTI_LINE);
}

в противном случае программа будет вываливаться в какой нить обработчик системных ошибок типа BusFault_Handler,MemManage_Handler,HardFault_Handler в зависимости от того как построена система в каждом конкретном случае . 

вторник, 29 декабря 2015 г.

STM32F pulse packet






HAL & CMSIS Timer Interrupt

HAL library helps us to handle all the checking and clearing status flag bits so we don’t have to worry about them again, just use the following function as an interrupt handler routine.


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance==TIM3) //check if the interrupt comes from TIM3
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
}
}

This Callback function is sharing among all timers interrupt. If you are using more than one Time base interrupt, you need to check the source of the interrupt before executing any command. For example, if you use TIM3 and TIM6 time base interrupt, the Callback function should be like this:


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   if (htim->Instance==TIM3)
      {
      //do something here
      }
   if (htim->Instance==TIM6)
      {
      //do something else here
      }
}

void TIM2_IRQHandler(void) //Функция обработчика прерывания от таймера 6
  {
    TIM2->SR &= ~TIM_SR_UIF; //Сбрасываем бит вызова прерывания. 
    GPIOC->ODR ^= GPIO_ODR_ODR8;//Инвертируем состояние вывода - зажигаем/гасим светодиод
  }
int main()
{
  NVIC_SetPriority(TIM2_IRQn, 1); //Приоритет прерывания
  NVIC_EnableIRQ(TIM2_IRQn); //Разрешаем обработку прерывания от таймера 2
  
  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //Тактирование порта C
  GPIOC->CRH |= GPIO_CRH_MODE8_0;//Вывод PC8 порта C - выход
  GPIOC->CRH &= ~GPIO_CRH_CNF8;//Режим Push-Pull для вывода PC8 порта C
  
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;//Тактирование таймера TIM2
  TIM2->PSC = 16799;//Настройка предделителя таймера
  TIM2->ARR = 5000;//Загружаем число миллисекунд в регистр автоперезагрузки
  TIM2->DIER |= TIM_DIER_UIE; //Разрешаем прерывание при переполнении счетчика
  TIM2->CR1 |= TIM_CR1_CEN;//Запускаем счет
  
  while(1);
}

#include "stm32f10x.h"
uint8_t i=0;
int main(void) 
{
  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;  // Enable PORTC Periph clock
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;  // Enable TIM2 Periph clock
  // Clear PC8 and PC9 control register bits
  GPIOC->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_CNF8 |
                 GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
  // Configure PC.8 and PC.9 as Push Pull output at max 10Mhz
  GPIOC->CRH |= GPIO_CRH_MODE8_0 | GPIO_CRH_MODE9_0;
  TIM2->PSC = SystemCoreClock / 1000 - 1; // 1000 tick/sec
  TIM2->ARR = 1000;  // 1 Interrupt/sec (1000/100)
  TIM2->DIER |= TIM_DIER_UIE; // Enable tim2 interrupt
  TIM2->CR1 |= TIM_CR1_CEN;   // Start count
  NVIC_EnableIRQ(TIM2_IRQn);  // Enable IRQ
  while(1); // Infinity loop
}
void TIM2_IRQHandler(void)
{
  TIM2->SR &= ~TIM_SR_UIF; //Clean UIF Flag
  if (1 == (i++ & 0x1)) {
    GPIOC->BSRR = GPIO_BSRR_BS8;   // Set PC8 bit
    GPIOC->BSRR = GPIO_BSRR_BR9;   // Reset PC9 bit
  } else {
    GPIOC->BSRR = GPIO_BSRR_BS9;   // Set PC9 bit
    GPIOC->BSRR = GPIO_BSRR_BR8;   // Reset PC8 bit
  }
}



воскресенье, 27 декабря 2015 г.

STM32F PWM phase shift

Counter mode to Center-aligned mode 3 (CMS[1:0]=11 in TIM1_CR1). And then use PWM mode 1 for TIM1_CH1 (OC1M = 0110 in TIM1_CCMR1) and PWM mode 2 for TIM1_CH2 (OC2M = 0111). Now they'll share the same frequency and if you use the same pulse length in TIM1_CCR1 and TIM1_CCR2 they´ll have the same duty cycle as well.

    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3;
    TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
    
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);


STM32F Timer Synchronization



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

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)
  {
  }
}

вторник, 30 декабря 2014 г.

Debug MCU configuration register (DBGMCU_CR)

DBGMCU_CR is mapped on the External PPB bus at address 0xE0042004 - задает режим работы отладчика

Address: 0xE004 2004
Only 32-bit access supported
POR Reset: 0x0000 0000 (not reset by system reset)




Bit 31 Reserved, must be kept at reset value.
Bits 30:25 DBG_TIMx_STOP: TIMx counter stopped when core is halted (x=9..14)
0: The clock of the involved timer counter is fed even if the core is halted, and the outputs
behave normally.
1: The clock of the involved timer counter is stopped when the core is halted, and the outputs
are disabled (as if there were an emergency stop in response to a break event).
Bits 24:22 Reserved, must be kept at reset value.
Bit 21 DBG_CAN2_STOP: Debug CAN2 stopped when core is halted
0: Same behavior as in normal mode
1: CAN2 receive registers are frozen
Bits 20:17 DBG_TIMx_STOP: TIMx counter stopped when core is halted (x=8..5)
0: The clock of the involved timer counter is fed even if the core is halted, and the outputs
behave normally.
1: The clock of the involved timer counter is stopped when the core is halted, and the outputs
are disabled (as if there were an emergency stop in response to a break event).
Bit 16 DBG_I2C2_SMBUS_TIMEOUT: SMBUS timeout mode stopped when Core is halted
0: Same behavior as in normal mode
1: The SMBUS timeout is frozen
Bit 15 DBG_I2C1_SMBUS_TIMEOUT: SMBUS timeout mode stopped when Core is halted
0: Same behavior as in normal mode
1: The SMBUS timeout is frozen
Bit 14 DBG_CAN1_STOP: Debug CAN1 stopped when Core is halted
0: Same behavior as in normal mode
1: CAN1 receive registers are frozen
Bits 12:11 DBG_TIMx_STOP: TIMx counter stopped when core is halted (x=4..1)
0: The clock of the involved Timer Counter is fed even if the core is halted
1: The clock of the involved Timer counter is stopped when the core is halted
Bit 9 DBG_WWDG_STOP: Debug window watchdog stopped when core is halted
0: The window watchdog counter clock continues even if the core is halted
1: The window watchdog counter clock is stopped when the core is halted
Bit 8 DBG_IWDG_STOP: Debug independent watchdog stopped when core is halted
0: The watchdog counter clock continues even if the core is halted
1: The watchdog counter clock is stopped when the core is halted
Bits 7:5 TRACE_MODE[1:0] and TRACE_IOEN: Trace pin assignment control
– With TRACE_IOEN=0:
TRACE_MODE=xx: TRACE pins not assigned (default state)
– With TRACE_IOEN=1:
– TRACE_MODE=00: TRACE pin assignment for Asynchronous Mode
– TRACE_MODE=01: TRACE pin assignment for Synchronous Mode with a
TRACEDATA size of 1
– TRACE_MODE=10: TRACE pin assignment for Synchronous Mode with a
TRACEDATA size of 2
– TRACE_MODE=11: TRACE pin assignment for Synchronous Mode with a
TRACEDATA size of 4
Bits 4:3 Reserved, must be kept at reset value.
Bit 2 DBG_STANDBY: Debug Standby mode
0: (FCLK=Off, HCLK=Off) The whole digital part is unpowered.
From software point of view, exiting from Standby is identical than fetching reset vector
(except a few status bit indicated that the MCU is resuming from Standby)
1: (FCLK=On, HCLK=On) In this case, the digital part is not unpowered and FCLK and
HCLK are provided by the internal RC oscillator which remains active. In addition, the MCU
generate a system reset during Standby mode so that exiting from Standby is identical than
fetching from reset
Bit 1 DBG_STOP: Debug Stop mode
0: (FCLK=Off, HCLK=Off) In STOP mode, the clock controller disables all clocks (including
HCLK and FCLK). When exiting from STOP mode, the clock configuration is identical to the
one after RESET (CPU clocked by the 8 MHz internal RC oscillator (HSI)). Consequently,
the software must reprogram the clock controller to enable the PLL, the Xtal, etc.
1: (FCLK=On, HCLK=On) In this case, when entering STOP mode, FCLK and HCLK are
provided by the internal RC oscillator which remains active in STOP mode. When exiting
STOP mode, the software must reprogram the clock controller to enable the PLL, the Xtal,
etc. (in the same way it would do in case of DBG_STOP=0)
Bit 0 DBG_SLEEP: Debug Sleep mode
0: (FCLK=On, HCLK=Off) In Sleep mode, FCLK is clocked by the system clock as previously
configured by the software while HCLK is disabled.
In Sleep mode, the clock controller configuration is not reset and remains in the previously
programmed state. Consequently, when exiting from Sleep mode, the software does not
need to reconfigure the clock controller.
1: (FCLK=On, HCLK=On) In this case, when entering Sleep mode, HCLK is fed by the same
clock that is provided to FCLK (system clock as previously configured by the software).



#define    DBGMCU_CR         *(volatile unsigned long *)0xE0042004

DBGMCU_CR = 0x7;

среда, 19 ноября 2014 г.

TIM (таймеры STM32F)

В STM32F по умолчанию периферия продолжает "тикать" в реальном времени, пока происходит останов под отладчиком или пошаговые прохождения по программе. Чтобы остановить периферию (в твоем случае - Таймер), необходимо установить при инициализации системы нужный бит в узле отладки, что можно сделать либо библиотечной функцией:


DBGMCU_Config (DBGMCU_TIM3_STOP, ENABLE);  // stop timer3 while debugging

либо на "регистровом" уровне программирования:


DBGMCU->CR |= DBGMCU_TIM3_STOP;

Конечно, внешний измеряемый сигнал остановить нельзя, но под отладчиком, по крайней мере, не будет выбега таймера.

среда, 25 июня 2014 г.

printf

Функция printf уже реализована в стандартной библиотеке непосредственному использованию ее мешает, то, что библиотека не знает, куда отправлять получившийся текст, - в USB-CDC, Ethernet, UART .  В нашем случае мы перенаправим ее в  ITM. Для данной задачи необходимо реализовать всего одну функцию: int fputc(int c, FILE *stream). В ней  будем отправлять всё в отладочный порт. Для этого где-то в CMSIS есть объявление и реализация функции ITM_SendChar, которая записывает символ в нулевой порт трассировщика, чтоб передать его в отладчик.

#include <stm32f4xx.h>
#include <stdio.h>

int fputc(int c, FILE *stream)
{
    return ITM_SendChar(c);
}
int main(void)
{    
    while(1)
    {
       printf("Hello world!");
    }

}

пятница, 6 июня 2014 г.

RTC initialisation (инициализация часов) STM32F (STM32F103)

#include "stm32F10x.h"
#include "rtc.h"

//************************** Часы реального времени **************************

//****************************************************************************
//             Инициализация часов                            //
//****************************************************************************  
int  RtcInit  (void)
{
  //разрешить тактирование модулей управления питанием и управлением
  //резервной областью - enable APB1 clocks
  RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
  // disable backup domain write protection
//разрешить доступ к области резарвных данных
  PWR->CR |= PWR_CR_DBP;
  //если часы выключены - инициализировать их
//Bit 15 RTCEN: RTC clock enable
//Set and cleared by software.
//0: RTC clock disabled
//1: RTC clock enabled
if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN)
{
//выполнить сброс области резервных данных
// reset Backup Domain
//Bit 16 BDRST: Backup domain software reset
//Set and cleared by software.
//0: Reset not activated
//1: Resets the entire Backup domain
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
//выбрать источником тактовых импульсов внешний кварц 32768 и подать тактирование
//Bit 15 RTCEN: RTC clock enable
//Set and cleared by software.
//0: RTC clock disabled
//1: RTC clock enabled
//Bits 9:8 RTCSEL[1:0]: RTC clock source selection
//Set by software to select the clock source for the RTC. Once the RTC clock source has been selected,
// it cannot be changed anymore unless the Backup domain is reset. The BDRST bit can be used to reset them.
//00: No clock
//01: LSE oscillator clock used as RTC clock10: LSI oscillator clock used as RTC clock
//11: HSE oscillator clock divided by 128 used as RTC clock
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE;
//установка маски разрешения секундных прерываний
//Bit 0 SECIE: Second interrupt enable
//0: Second interrupt is masked.
//1: Second interrupt is enabled.
RTC->CRH |= RTC_CRH_SECIE; ///!!!!!!!!!!!!SECOND INTERRUPT ENABLE
//Bit 4 CNF: Configuration flag
//This bit must be set by software to enter in configuration mode so as to allow new values to
//be written in the RTC_CNT, RTC_ALR or RTC_PRL registers. The write operation is only
//executed when the CNF bit is reset by software after has been set.
//0: Exit configuration mode (start update of RTC registers).
//1: Enter configuration mode.
RTC->CRL |= RTC_CRL_CNF;
//If the input clock frequency (fRTCCLK) is 32.768 kHz, write 7FFFh in this register to get a
//signal period of 1 second.
RTC->PRLH = 0;
RTC->PRLL = 0x8000;         //тактирование от внешнего кварца

AFIO->EVCR =0xAD; //PC13-calibration clock output enable

BKP->RTCCR |= BKP_RTCCR_CCO; //Setting this bit outputs the
//RTC clock with a frequency divided by 64 on the TAMPER pin
BKP->RTCCR |= BKP_RTCCR_ASOS | BKP_RTCCR_ASOE;
//0: Exit configuration mode (start update of RTC registers).
RTC->CRL &= ~RTC_CRL_CNF;
    //установить бит разрешения работы и дождаться установки бита готовности
RCC->BDCR |= RCC_BDCR_LSEON;
while ((RCC->BDCR & RCC_BDCR_LSEON) != RCC_BDCR_LSEON){}

//while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY); //вариант

//Bit 3 RSF: Registers synchronized flag
//This bit is set by hardware at each time the RTC_CNT and RTC_DIV registers are updated
//and cleared by software. Before any read operation after an APB1 reset or an APB1 clock
//stop, this bit must be cleared by software, and the user application must wait until it is set to
//be sure that the RTC_CNT, RTC_ALR or RTC_PRL registers are synchronized.
//0: Registers not yet synchronized.
//1: Registers synchronized.
RTC->CRL &= (uint16_t)~RTC_CRL_RSF;
while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){}
return 0;
}
   return 1;
}

воскресенье, 18 мая 2014 г.

RTC STM32F1xx

Calibration clock output


RTC clock calibration register (BKP_RTCCR). 

Bit 7 CCO: Calibration clock output
0: No effect
1: Setting this bit outputs the RTC clock with a frequency divided by 64 on the TAMPER pin.
The TAMPER pin must not be enabled while the CCO bit is set in order to avoid unwanted Tamper detection.
Note: This bit is reset when the V DD supply is powered off.

Event control register (AFIO_EVCR).

Bits 31:8 Reserved

Bit 7 EVOE: Event output enable
Set and cleared by software. When set the EVENTOUT Cortex output is connected to the
I/O selected by the PORT[2:0] and PIN[3:0] bits.

Bits 6:4 PORT[2:0]: Port selection
Set and cleared by software. Select the port used to output the Cortex EVENTOUT signal.
Note: The EVENTOUT signal output capability is not extended to ports PF and PG.
000: PA selected
001: PB selected
010: PC selected
011: PD selected
100: PE selected

Bits 3:0 PIN[3:0]: Pin selection (x = A .. E)
Set and cleared by software. Select the pin used to output the Cortex EVENTOUT signal.
0000: Px0 selected
0001: Px1 selected
0010: Px2 selected
0011: Px3 selected
...
1111: Px15 selected

Programm realisation for STM32F103:

AFIO->EVCR =0xAD; //PC13-calibration clock output enable
BKP->RTCCR |= BKP_RTCCR_CCO; //Setting this bit outputs the
//RTC clock with a frequency divided by 64 on the TAMPER pin


пятница, 2 мая 2014 г.

DWT - Data Watchpoint and Trace unit

  В STM32 регистры, используя которые, можно достаточно просто осуществлять подсчет времени исполнения различных участков кода.
 Один из этих регистров – DWT_CYCCNT, расположенный по адресу 0xE0001004, представляет собой счетчик тактов микроконтроллера. Чтобы запустить его на счет, необходимо установить младший бит (CYCCNTENA) регистра DWT_CONTROL.

#define    DWT_CYCCNT       *(volatile unsigned long *)0xE0001004
#define    DWT_CONTROL   *(volatile unsigned long *)0xE0001000
#define    SCB_DEMCR         *(volatile unsigned long *)0xE000EDFC

  SCB_DEMCR |= 0x01000000;
  DWT_CONTROL|= 1; // enable the counter
  DWT_CYCCNT  = 0;
  for(i=0;i<1000;i++){};
  time=DWT_CYCCNT;


=======================================================

#define    DWT_CYCCNT       *(volatile uint32_t *)0xE0001004
#define    DWT_CONTROL     *(volatile uint32_t *)0xE0001000
#define    SCB_DEMCR         *(volatile uint32_t *)0xE000EDFC

static inline uint32_t DWT_Get(void)
{
    return DWT_CYCCNT;
}
void init_dwt()
{
    SCB_DEMCR  |= 0x01000000;
    DWT_CYCCNT  = 0;
    DWT_CONTROL|= 1;                    // enable the counter
}

int main(void)
{
init_dwt();
DWT_CYCCNT=0;                             // сброс счётчика цилов процессора
DoSome();
uint32_t cycles=DWT_CYCCNT;      // чтение количества циклов
}
===========================================================
организация  задержки

uint32_t DWT_Get(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;return DWT_CYCCNT;
}
__inline
uint8_t DWT_Compare(int32_t tp)
{
&nbsp;&nbsp;&nbsp;&nbsp;return (((int32_t)DWT_Get() - tp) < 0);
}

void DWT_Delay(uint32_t us) // microseconds
{
&nbsp;&nbsp;&nbsp;&nbsp;int32_t tp = DWT_Get() + us * (SystemCoreClock/1000000);
&nbsp;&nbsp;&nbsp;&nbsp;while (DWT_Compare(tp));
}
==========================================================
uint32_t DWT_Get(void)
{
    return DWT_CYCCNT;
}
__inline
uint8_t DWT_Compare(int32_t tp)
{
    return (((int32_t)DWT_Get() - tp) < 0);
}

void DWT_Delay(uint32_t us) // microseconds
{
    int32_t tp = DWT_Get() + us * (SystemCoreClock/1000000));
    while (DWT_Compare(tp));

}


If your Cortex M microcontroller  have DWT  (Data Watchpoint and Trace) unit, you can use its register to count the number of cycles in which some code is executed. This could be useful for performance measuring. Simple cycle counter on ARM microcontroller  having DWT unit could be implemented like this:

#include <stdint.h>

volatile uint32_t count = 0;

// addresses of registers
volatile uint32_t *DWT_CONTROL = (uint32_t *)0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *)0xE0001004; 
volatile uint32_t *DEMCR = (uint32_t *)0xE000EDFC; 

// enable the use DWT
*DEMCR = *DEMCR | 0x01000000;

// Reset cycle counter
*DWT_CYCCNT = 0; 

// enable cycle counter
*DWT_CONTROL = *DWT_CONTROL | 1 ; 

// some code here
// .....

// number of cycles stored in count variable
count = *DWT_CYCCNT;

The DWT is an optional debug unit that provides watchpoints, data tracing, and system profiling for the processor.A full DWT contains four comparators that you can configure as 
  • hardware watchpoint
  • an ETM trigger
  • a PC sampler event trigger
  • a data address sampler event trigger.

The first comparator, DWT_COMP0, can also compare against the clock cycle counter, CYCCNT. You can also use the second comparator, DWT_COMP1, as a data comparator. A reduced DWT contains one comparator that you can use as a watchpoint or as a trigger. It does not support data matching. The DWT if present contains counters for:

  • clock cycles (CYCCNT)
  • folded instructions
  • Load Store Unit (LSU) operations 
  • sleep cycles 
  • CPI, that is all instruction cycles except for the first cycle
  • interrupt overhead.

Note
An event is generated each time a counter overflows.
You can configure the DWT to generate PC samples at defined intervals, and to generate interrupt event information.
The DWT provides periodic requests for protocol synchronization to the ITM and the TPIU, if the your implementation includes the Cortex-M3 TPIU.

Lists the DWT registers. Depending on the implementation of your processor, some of these registers might not be present. Any register that is configured as not present reads as zero.


a. Possible reset values are:
0x40000000 if four comparators for watchpoints and triggers are present
0x4F000000 if four comparators for watchpoints only are present
0x10000000 if only one comparator is present
0x1F000000 if one comparator for watchpoints and not triggers is present
0x00000000 if DWT is not present.

DWT registers are described in the ARMv7M Architecture Reference Manual. Peripheral Identification. Component Identification registers are described in the ARM CoreSight Components Technical Reference Manual.

Note
• Cycle matching functionality is only available in comparator 0.
• Data matching functionality is only available in comparator 1.
• Data value is only sampled for accesses that do not produce an MPU or bus fault. The PC is sampled irrespective of any faults. The PC is only sampled for the first address of a burst.
• The FUNCTION field in the DWT_FUNCTION1 register is overridden for comparators given by DATAVADDR0 and DATAVADDR1 if DATAVMATCH is also set in DWT_FUNCTION1. The comparators given by DATAVADDR0 and DATAVADDR1 can then only perform address comparator matches for comparator 1 data matches.
• If the data matching functionality is not included during implementation it is not possible to set DATAVADDR0, DATAVADDR1, or DATAVMATCH in DWT_FUNCTION1. This means that the data matching functionality is not available in the implementation. Test the availability of data matching by writing and reading the DATAVMATCH bit in DWT_FUNCTION1. If this bit cannot be set then data matching is unavailable.
• PC match is not recommended for watchpoints because it stops after the instruction. It mainly guards and triggers the ETM.