Ярлыки

_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)

вторник, 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( ;; );
}



вторник, 12 апреля 2016 г.

STM32F4 & F0 CubeMX for Digital Potentiometers MCP453X/455X/463X/465X

MCP453X/455X/463X/465X

6.2.4 ADDRESSING
The address byte is the first byte received following the START condition from the master device. The address contains four (or more) fixed bits and (up to) three user defined hardware address bits (pins A2, A1, and A0). These 7-bits address the desired I2C device. The A7:A4 address bits are fixed to “0101” and the device appends the value of following three address pins (A2, A1, A0). Address pins that are not present on the device are pulled up (a bit value of ‘1’). Since there are up to three address bits controlled by hardware pins, there may be up to eight MCP4XXX devices on the same I2C bus. Figure 6-9 shows the slave address byte format, which contains the seven address bits. There is also a read/ write bit. Table 6-2 shows the fixed address for each device.

Байт адреса - первый байт посылаемый мастером после старта . Адрес содержит 4 (или больше) фиксированных бита и до 3-х битов, задаваемых пользователем с помощью соответствующих установок входов  A2, A1, A0  в зависимости от типа устройства. Если адресные пины в устройстве отсутствуют, то их значение принимаются равным "1".  Три адресных разряда позволяют увеличить количество учтройств, одновременно подключенных к шине. Рис 6-9 показыват назначение 7 бит адресного байта для вадомого (slave) устройства. После адресных битов идет бит чтения/записи (read/write).  В Табл. 6-2 приведены адреса для каждого типа устройств.
There are up to three hardware pins used to specify the device address. The number of address pins is determined by the part number. Address 0 is multiplexed with the High Voltage Command (HVC) function. So the state of A0 is latched on the MCP4XXX’s POR/BOR event.The HVC pin has an internal resistor connection to the MCP45XX/46XXs internal VDD signal. The state of the A2 and A1 pins should be static, that is they should be tied high or tied low. 

Вывод А0 используется для High-Voltge комманд. Для  MCP45XX/46XXs устройств он подтянут к "1". 
При обращении к ведомому устройству типа  MCP45X1 его адрес 0x2F или 0x2E.









Пример передачи команды от master к slave для MCP4551 form Arduino for I2C Digital Potentiometer

  Wire.beginTransmission(0x2F);  // transmit to device address 0x2F is specified in datasheet
  Wire.write(0x00);                        // sends instruction byte - Write data
  Wire.write(0x55);                        // sends potentiometer value byte
  Wire.endTransmission();             // stop transmitting

Transmitt with Arduino board (byte 0x00, 0x55)



I2C signal from STM32F042 with Saleae Logic (transmitted byte - 0x16, 0x00). Address byte 0x5E.



понедельник, 11 апреля 2016 г.

STM32F0 (STM32F042) BOOT problem (User Option bit - nBoot0 )

Start STM32 ST-LINK Target -> Connect



With STM32 ST-LINK after Taregt -> Option bytes


nBoot0_SW_Cfg -
Cheked: The BOOT0 is bonded to GPIO pin (PB8 for small packages,  PF11 for big packages)
Uncheked: Its allows user to disable BOOT0 pin completely and use User Option bit ( nBoot0 ).

If nBOOT0 is cheked (=1) Main Flash memory is selected as boot area.

Table from reference manual

суббота, 9 апреля 2016 г.

bxCAN STM32F042 transmit and receive.

Transmitter

#include "stm32f0xx_hal.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;

I2C_HandleTypeDef hi2c1;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

unsigned int val_Tx = 0, val_Rx = 0;              /* Globals used for display */
volatile uint32_t msTicks;                        /* counts 1ms timeTicks     */

четверг, 7 апреля 2016 г.

CAN bus

STMicroelectronics CAN Controller for Cortex-M3 Processors.

Shown is a block diagram of the CAN controller. Here are the main points of all CAN controllers:
1. I/O Pins: These connect to the CAN transceiver chip pins R and D as already described.
2. Parallel-Serial Converters: CAN is a serial bus while the processor is parallel. Conversion happens here.
3. Tx mailbox: The messages to be transmitted are written here. ID, data (if any) and the DLC go here.
4. Acceptance Filter: This passes only specified messages to the processor via the FIFOs. By default at RESET, these filters pass all messages to the FIFOs. Your software must configure them to filter messages.
5. FIFO 0 & 1: Each Receive FIFO can hold 3 CAN messages. They provide a buffering system to the processor.
6. Control, Status, Configuration registers: Your software must configure these registers, usually at initialization. Various flags and switches are found here. Examples are set CAN speed, request transmission, manage receive messages, enable interrupts and obtain diagnostic information. Keil provides examples on how to set and use these registers. All CAN controllers have the same basic architecture. Different controllers will have differences in the number of receive FIFO buffers, transmit buffers, size of acceptance filters and the bit mapping, addresses and definitions of the various configuration registers. All CAN controllers are licensed by Robert Bosch GmbH in Germany and therefore they are able to exert considerable control over basic CAN attributes to make them consistent with various manufacturers. This means that all CAN controllers can communicate with other brands in a reliable and predictable manner.


The CAN frame has many fields but we can simplify this to a Programming Model as shown. These fields are accessed by your software through the CAN controller registers.

IDE: Identifier Extension: 1 bit - specifies if the ID field to be transmitted is 11 or 29 bits:
If IDE = 0, then the ID is 11 bits. If IDE = 1, then the ID is 29 bits.
ID: Identifier: 11 or 29 bits as set by the IDE field. This part of the CAN frame sets the priority.
DLC: Data Length Code: 4 bits - specifies number of data bytes in the frame from 0 through 8.
Data Bytes: 0 through 8 bytes.





пятница, 25 марта 2016 г.

I2C HAL

 ==============================================================================
                        ##### How to use this driver #####
  ==============================================================================
  [..]
    The I2C HAL driver can be used as follows:

    (#) Declare a I2C_HandleTypeDef handle structure, for example:
        I2C_HandleTypeDef  hi2c;

    (#)Initialize the I2C low level resources by implement the HAL_I2C_MspInit() API:
        (##) Enable the I2Cx interface clock
        (##) I2C pins configuration
            (+++) Enable the clock for the I2C GPIOs
            (+++) Configure I2C pins as alternate function open-drain
        (##) NVIC configuration if you need to use interrupt process
            (+++) Configure the I2Cx interrupt priority
            (+++) Enable the NVIC I2C IRQ Channel
        (##) DMA Configuration if you need to use DMA process
            (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream
            (+++) Enable the DMAx interface clock using
            (+++) Configure the DMA handle parameters
            (+++) Configure the DMA Tx or Rx Stream
            (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle
            (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
                  the DMA Tx or Rx Stream

вторник, 2 февраля 2016 г.

C# Serial Port Reading with delegate (чтение Сом порта с использованием делегатов)

Almost all the functionality in the app is a one liner and completely self explanatory because .NET is such a well written high level language. The only tricky part of this app is that the serial port receives data on a separate thread. You cannot access visual controls from a separate thread, so you must invoke a delegate that will set the text and send a copy of the memory with (new object[] { text }).
It is important to notice that InvokeRequired will let you know if the thread ID is different.
What will happen when we receive data is, serialPort1_DataReceived handler will be fired when serial data is received and it will call SetText which is just a little wrapper that will in turn invoke the SetTextCallbackdelegate. The delegate is set to call SetText so SetText will be invoked again, but now it is on the UI thread. At this point, this.txtData.InvokeRequired will be false and we can set the text like we normally would.


// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.

delegate void SetTextCallback(string text);
private void serialPort1_DataReceived
    (object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    SetText(this.serialPort1.ReadExisting());
}

private void SetText(string text)
{
    // InvokeRequired required compares the thread ID of the
    // calling thread to the thread ID of the creating thread.
    // If these threads are different, it returns true.

    if (this.txtData.InvokeRequired)
    {
        SetTextCallback d = new SetTextCallback(SetText);     
        this.Invoke(d, new object[] { text });
    }
    else
    {
        this.txtData.Text = text;
        serialPort1.DiscardInBuffer();   // <<<!!!!!
    }
}

пятница, 1 января 2016 г.

STM32F Timer diagramm & registers









ARM Cortex Debug Port Access Port DP AP JTAG-DP SW-DP SWJ-DP JTAG-AP MEM-AP





MDK5 & STM32Cube

\RTE\Device\STM32F407IGHx\MX_Device.h


/******************************************************************************
 * File Name   : MX_Device.h
 * Date        : 07/08/2015 18:06:21
 * Description : STM32Cube MX parameter definitions
 * Note        : This file is generated by STM32CubeMX (DO NOT EDIT!)
 ******************************************************************************/

#ifndef __MX_DEVICE_H
#define __MX_DEVICE_H

/*---------------------------- Clock Configuration ---------------------------*/

#define MX_LSI_VALUE                            32000
#define MX_LSE_VALUE                            32768
#define MX_HSI_VALUE                            16000000
#define MX_HSE_VALUE                            25000000
#define MX_EXTERNAL_CLOCK_VALUE                 12288000
#define MX_SYSCLKFreq_VALUE                     16000000
#define MX_HCLKFreq_Value                       16000000
#define MX_FCLKCortexFreq_Value                 16000000
#define MX_CortexFreq_Value                     16000000
#define MX_AHBFreq_Value                        16000000
#define MX_APB1Freq_Value                       16000000
#define MX_APB2Freq_Value                       16000000
#define MX_APB1TimFreq_Value                    16000000
#define MX_APB2TimFreq_Value                    16000000
#define MX_48MHZClocksFreq_Value                48000000
#define MX_EthernetFreq_Value                   16000000
#define MX_I2SClocksFreq_Value                  96000000
#define MX_WatchDogFreq_Value                   32000
#define MX_RTCFreq_Value                        32000
#define MX_MCO1PinFreq_Value                    16000000
#define MX_MCO2PinFreq_Value                    16000000

/*-------------------------------- NVIC       --------------------------------*/

#define MX_NVIC                                 1

/*-------------------------------- USART1     --------------------------------*/

#define MX_USART1                               1

#define MX_USART1_VM                            VM_ASYNC

/* GPIO Configuration */

/* Pin PB7 */
#define MX_USART1_RX_Pin                        PB7
#define MX_USART1_RX_GPIO_AF                    GPIO_AF7_USART1
#define MX_USART1_RX_GPIO_Speed                 GPIO_SPEED_HIGH
#define MX_USART1_RX_GPIO_PuPd                  GPIO_PULLUP
#define MX_USART1_RX_GPIOx                      GPIOB
#define MX_USART1_RX_GPIO_Mode                  GPIO_MODE_AF_PP
#define MX_USART1_RX_GPIO_Pin                   GPIO_PIN_7

/* Pin PB6 */
#define MX_USART1_TX_Pin                        PB6
#define MX_USART1_TX_GPIO_AF                    GPIO_AF7_USART1
#define MX_USART1_TX_GPIO_Speed                 GPIO_SPEED_HIGH
#define MX_USART1_TX_GPIO_PuPd                  GPIO_PULLUP
#define MX_USART1_TX_GPIOx                      GPIOB
#define MX_USART1_TX_GPIO_Mode                  GPIO_MODE_AF_PP
#define MX_USART1_TX_GPIO_Pin                   GPIO_PIN_6

/*-------------------------------- USART2     --------------------------------*/

#define MX_USART2                               1

#define MX_USART2_VM                            VM_ASYNC

/* GPIO Configuration */

/* Pin PD5 */
#define MX_USART2_TX_Pin                        PD5
#define MX_USART2_TX_GPIO_AF                    GPIO_AF7_USART2
#define MX_USART2_TX_GPIO_Speed                 GPIO_SPEED_HIGH
#define MX_USART2_TX_GPIO_PuPd                  GPIO_PULLUP
#define MX_USART2_TX_GPIOx                      GPIOD
#define MX_USART2_TX_GPIO_Mode                  GPIO_MODE_AF_PP
#define MX_USART2_TX_GPIO_Pin                   GPIO_PIN_5

/* Pin PD6 */
#define MX_USART2_RX_Pin                        PD6
#define MX_USART2_RX_GPIO_AF                    GPIO_AF7_USART2
#define MX_USART2_RX_GPIO_Speed                 GPIO_SPEED_HIGH
#define MX_USART2_RX_GPIO_PuPd                  GPIO_PULLUP
#define MX_USART2_RX_GPIOx                      GPIOD
#define MX_USART2_RX_GPIO_Mode                  GPIO_MODE_AF_PP
#define MX_USART2_RX_GPIO_Pin                   GPIO_PIN_6

/*-------------------------------- GPIO       --------------------------------*/

#define MX_GPIO                                 1

/* GPIO Configuration */

#endif  /* __MX_DEVICE_H */

RCR repetition counter register

Счётчик повторений

Этот счётчик выполняет оочень простую функцию: генерировать событие (прерывание или запрос DMA) update не на каждое переполнение счётчика, а на каждые N переполнений. То есть, вы задаёте счётчик повторений, таймер его копирует в скрытый регистр и при каждом переполнении уменьшает значение копии на 1. Когда значение достигает нуля, генерируется событие update, таймер снова копирует счётчик повторений и т.д. На самом деле, перечисленные таймеры и так задействуют этот счётчик, просто по умолчанию его значение равно нулю, и событие генерируется на каждое переполнение.

Счётчик может принимать значения от 0 до 255 (0xFF). Инициализация

base_timer.TIM_RepetitionCounter = 7;

 В этом случае событие update будет генерироваться каждые 8 переполнений (7 повторений).

вторник, 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
  }
}



понедельник, 28 декабря 2015 г.

STM32F 3 phase digital signals

snippet from timer.c:
----------------------------------------------------------------------------------------------
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
__IO uint16_t CCR1_Val = 65534;
__IO uint16_t CCR2_Val = 43689;
__IO uint16_t CCR3_Val = 21844;
uint16_t PrescalerValue = 0;

/* Private function prototypes -----------------------------------------------*/
void Setup3PhaseTimer(void);
void NVICConfig(void);
/* Private functions ---------------------------------------------------------*/


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

STM32 CubeMX Timer One Pulse Mode










  MX_TIM3_Init();

  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
  while (1)
  {
   HAL_Delay(1000);
   __HAL_TIM_ENABLE(&htim3);
  }

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



STM32 Timer One Pulse Mode












суббота, 26 декабря 2015 г.

CMSIS Initialisation

GPIO

STM32F4 HAL Timer& Interrupt Init

/* TIM5 init function */
void MX_TIM5_Init(void)
{
  htim5.Instance = TIM3; 
  htim5.Init.Prescaler = 16800-1; // делим 168 МГц на 16800 получаем 10000 Гц или 10 мс
  htim5.Init.CounterMode = TIM_COUNTERMODE_UP; // таймер считает вверх
  htim5.Init.Period = 5000-1; // считать будет до 5000, т.е. через 500 мс произойдет прерывание
  htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // частоту входную не делим - нам хватает
  HAL_TIM_Base_Init(&htim5);
  /* Start the TIM Base generation in interrupt mode */
  /* Start Channel1 */
  HAL_TIM_Base_Start_IT(&htim5); // включаем прерывание таймера 5
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
}