Ярлыки

_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 октября 2016 г.

STM32F ADC with DMA on CMSIS

void DMA2_Stream4_IRQHandler(void)
{
        
GPIOD->ODR        ^=((1<<12)|(1<<13)|(1<<14)|(1<<15));
}
uint16_t BUFF[100];int main(void)
{
    
SystemInit();
//*********************GPIO*************************
        
RCC->AHB1ENR    |= RCC_AHB1ENR_GPIOAEN;
        
RCC->AHB1ENR    |= RCC_AHB1ENR_GPIODEN;
        
GPIOA->MODER    |= GPIO_MODER_MODER6;        //ADC1 CH6 PA6


//*********************TIM3*************************
        
RCC->APB1ENR    |= RCC_APB1ENR_TIM3EN;        // тактирование таймера
        
TIM3->PSC         160-1;                    // предделитель
        
TIM3->ARR         1000-1;                    // переполнение
        
TIM3->CR2         |= TIM_CR2_MMS_1;            // output (TRGO)
        
TIM3->DIER         |= TIM_DIER_UDE;
        
TIM3->CR1         |= TIM_CR1_CEN;                //запуск счета


//********************DMA***************************
        
RCC->AHB1ENR    |= RCC_AHB1ENR_DMA2EN;
        
DMA2_Stream4->CR&=~ DMA_SxCR_CHSEL;            // 000: channel 0 selected
        
DMA2_Stream4->PAR= (uint32_t)&ADC1->DR;     //
        
DMA2_Stream4->M0AR=(uint32_t)&BUFF[0];        // Массив
        
DMA2_Stream4->NDTR=100;                        // Длина буфера
        
DMA2_Stream4->CR|= DMA_SxCR_MINC;            // Инкремент адреса
        
DMA2_Stream4->CR|= DMA_SxCR_MSIZE_0;        // 16 бит
        
DMA2_Stream4->CR|= DMA_SxCR_PSIZE_0;        // 16 бит
        
DMA2_Stream4->CR|= DMA_SxCR_CIRC;            // Непрерывный режим
        
DMA2_Stream4->CR&=~ DMA_SxCR_DIR;            // 01: peripheral-to-Memory
        
DMA2_Stream4->CR|= DMA_SxCR_PL;                // 11: Very high приоритет
        
DMA2_Stream4->CR|= DMA_SxCR_TCIE;            // Transfer complete interrupt enable
        
DMA2_Stream4->CR|= DMA_SxCR_EN;                 // Вкл. передачу
        
NVIC_EnableIRQ(DMA2_Stream4_IRQn);
        
NVIC_SetPriority(DMA2_Stream4_IRQn,5);

//********************ADC1**CH6 PA6***************
        
RCC->APB2ENR    |= RCC_APB2ENR_ADC1EN;
        
ADC1->CR1         |=ADC_CR1_SCAN;                // Scan mode
        
ADC1->CR2        |=(ADC_CR2_EXTSEL_3);        //tim 3 (TRGO)
        
ADC1->SQR3        =6;                            //выбор канала PA6
        
ADC1->CR2         |=ADC_CR2_DMA;                //разрешаем рабуту DMA
        
ADC1->CR2         |=ADC_CR2_DDS;                //DMA disable selection (for single ADC mode)
        
ADC1->CR2        &=~ADC_CR2_CONT;            //Continuous conversion
        
ADC1->CR2        |=ADC_CR2_EXTEN_0;            //01: Trigger detection on the rising edge
        
ADC1->CR2        |= ADC_CR2_EOCS;            //разрешаем прерывания
        
ADC1->CR2         |=ADC_CR2_ADON;                //Вкл. переобразования  

понедельник, 19 сентября 2016 г.

STM32F051 Continuous mode and Discontinuous mode explanation for the sequence conversion

The following illustrations present the differences among various configuration for continuous mode and discontinuous mode for 2 channels:

With both modes disabled: the conversion sequence start from the first channel until the last channel and then stop. Each time the channel conversion is done, the End of Conversion (EOC) interrupt flag will be triggered until the last channel, End of sequence (EOS) will be on.

 continuous mode disabled, and discontinuous mode disabled

With continuous mode enabled, and discontinuous mode disabled: similarly to single channel, the conversion process will be restarted automatically when the last channel is finished.

continuous mode enabled, and discontinuous mode disabled

With continuous mode disabled, and discontinuous mode enabled: Everytime the channel conversion is done, we need to trigger the start of ADC module again to move on to the next channel in the sequence.
continuous mode disabled, and discontinuous mode enabled


вторник, 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 в зависимости от того как построена система в каждом конкретном случае . 

вторник, 7 июня 2016 г.

FreeRTOS

void ATaskFunction( void *pvParameters );
void ATaskFunction( void *pvParameters )
{
   /* Переменные могут быть определены точно так же, как и в обычной функции. Каждый экземпляр созданной по этой функции задачи будет иметь собственную копию переменной iVariableExample. Это не верно, если переменная была продекларирована как статическая (static) – в этом случае будет сущесвовать только одна копия переменной, и она будет использоваться совместно всеми созданными экземплярами задачи. */


   int iVariableExample = 0;

  /* Задача должна быть нормально реализована как бесконечный цикл. */
  for( ;; )
  {
     /* Код, который реализует функционал задачи, должен быть помещен здесь. */
  }

   /* Код должен быть организован так, чтобы в случае выхода (break) из указанного 
выше бесконечного цикла задачи, задача должна быть удалена ПРЕЖДЕ чем управление достигнет конца этой функции. Параметр NULL, переданный vTaskDelete(), показывает, что должна быть удалена вызванная (эта, которая работает) задача. */
   vTaskDelete( NULL );
}


portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
                           const signed portCHAR * const pcName,
                           unsigned portSHORT usStackDepth,
                           void *pvParameters,
                           unsigned portBASE_TYPE uxPriority,
                           xTaskHandle *pxCreatedTask );




pvTaskCodeЗадачи - это простые C-функции, которые никогда не делают возврата из своего тела (постоянно выполняют свой бесконечный цикл). Параметр pvTaskCode - простой указатель на функцию (т. е. просто имя функции), которая реализует задачу.
 pcName
Описательное имя для задачи. Оно никак не используется внутри FreeRTOS, и нужно только для целей отладки. Идентификация задачи по легкочитаемому имени намного проще, чем по хендлу задачи (handle).
В приложении указана константа времени компиляции configMAX_TASK_NAME_LEN, которая задает максимальную длину для этого имени - включая нулевой байт окончания строки. Если в качестве pcName предоставлена более длинная строка, то она молча урезается до величины, заданной configMAX_TASK_NAME_LEN.
 usStackDepth
Каждая задача имеет собственное уникальное хранилище состояния, выделенное ядром при создании задачи. Значение параметра usStackDepth говорит ядру, какой величины стек необходимо создать.
Значение usStackDepth указывает количество слов, которое можно сохранить в стеке, а не количество байт. Например, если стек имеет ширину 32 бита, и переданное значение usStackDepth равно 100, то под стек будет выделено 400 байт (100 * 4 байт). Глубина стека, умноженная на его ширину, не должна превышать максимальное значение, которое может содержать переменная типа size_t.
Размер стека, используемого для задачи ожидания (idle task, об этой задаче подробнее говорится далее), задается константой configMINIMAL_STACK_SIZE. Значение, назначенное этой константе в демо-приложении FreeRTOS (для определенной архитектуры микроконтроллера) может быть использовано как минимально рекомендованное для любой задачи. Если Ваша программа использует пространство в стеке, то нужно указать для константы configMINIMAL_STACK_SIZE увеличенное значение.
Нет простого способа узнать, какого размера стек нужен для задачи. Этот размер можно вычислить, но в большинстве случаев можно просто назначить подходящее значение, подобранное опытным путем, либо взятое приблизительно. Подобрать правильный размер стека важно, чтобы обеспечить адекватное использование RAM без ненужных затрат. Часть 6 содержит информацию о том, как запросить размер стека, используемого задачей.
 pvParametersФункции задач принимают параметр, имеющий тип указателя на void (т. е. void*). Значение, указанное в pvParameters, будет передано в задачу. Несколько примеров в этом документе демонстрируют, как этот параметр может быть использован в реальных задачах.
 uxPriority
Задает приоритет, с которым будет выполняться задача. Приоритеты могут быть назначены в любое значение от 0 минимальный приоритет до (configMAX_PRIORITIES – 1) максимальный приоритет.
Константа configMAX_PRIORITIES определяется пользователем. Нет ограничения на верхний предел для количества приоритетов, которые можно задать (кроме ограничения на лимит используемого типа данных ограничения по количеству RAM, доступному в микроконтроллере), но желательно использовать как можно меньшее количество приоритетов, которое действительно необходимо - с целью уменьшения расхода RAM.
Передача в параметре значения uxPriority выше (configMAX_PRIORITIES – 1) приведет к молчаливому назначению приоритета задачи в максимально допустимое значение configMAX_PRIORITIES.
 pxCreatedTask
Параметр pxCreatedTask может использоваться для передачи наружу хендла созданной задачи. Этот хендл можно использовать как ссылку на задачу в вызовах API FreeRTOS, например для изменения приоритета задачи или для удаления задачи.
Если Ваше приложение не использует хендл задачи, то pxCreatedTask может быть установлен в NULL.
Возвращаемое значение
Имеется два возможных возвращаемых значения:
1. pdTRUE показывает, что задача успешно создана.
2. errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY показывает, что задача не создана, так как в куче (heap) недостаточно свободной памяти для FreeRTOS, чтобы она могла выделить место для структур данных задачи и стека. Часть 5 предоставляет больше информации по управлению памятью.


int main( void )
{
  /* Создание одной из двух задач. Имейте в виду, что реальное приложение должно
     проверить возвращаемое значение из вызова xTaskCreate(), чтобы удостовериться,
     что задача была успешно создана. */
  xTaskCreate( vTask1,  /* Указатель на функцию, которая реализует задачу. */
               "Task 1",/* Текстовое имя задачи. Этот параметр нужен только для
                           упрощения отладки. */
               1000,    /* Глубина стека - самые маленькие микроконтроллеры будут
                           использовать значение намного меньше, чем здесь
                           указано. */

               NULL,    /* Мы не используем параметр задачи. */
               1,       /* Задача будет запущена с приоритетом 1. */
               NULL );  /* Мы не будем использовать хендл задачи. */
  /* Создание другой задачи полностью совпадает с созданием первой, 
     приориет задачи тот же. */
  xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );

  /* Запуск шедулера, после чего задачи запустятся на выполнение. */
  vTaskStartScheduler();

  /* Если все хорошо, то управление в main() никогда не дойдет до этой точки,
     и теперь шедулер будет управлять задачами. Если main() довела 
управление
     до 
этого места, то это может означать, что не хватает памяти кучи
     
(heap) для создания специальной задачи ожидания (idle task, об этой задаче
     
далее). Часть 5 предоставляет больше информации по управлению памятью. */
  for( ;; );
}