Ярлыки
_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)
воскресенье, 19 июля 2015 г.
среда, 27 мая 2015 г.
2-x фазный ШИМ (PWM) генератор на STM32F030F4
Для питания ряда устройств (например электродвигателей переменного тока) иногда необходимо наличие сдвинутых по фазе питающих напряжений. Для питания 2-х фазных синхронных индукционных двигателей необходимо наличие двух фаз синусоидального напряжения с частотой 400 Герц и сдвинутых по фазе на 90 градусов. Один из примеров таких двигателей являются двигатели серии ДИД. Они интересны тем, что их частота вращения может составлять от 16000 до 18000 об/мин. Для питания таких двигателей и было сделано данное устройство, которое представляет собой задающий генератор 2-х фазного 400 Гц напряжений сдвинутых по фазе на 90 градусов относительно друг друга.
В качестве микроконтроллера использован STM32F030F4. Его выбор обусловлен его "минимализмом" - наименьший из корпусов в серии STM32F0 и естественно с минимальной стоимостью. Схема подключения изображена ниже. Микроконтроллер работает на частоте 48 МГц. В качестве задающего генератора использован TIM3, так как в данном контроллере только этот таймер можно конфигурировать так, чтобы использовать выходы трех каналов. Третий канал можно в случае необходимости использовать для генерации 3-фазного напряжения. Таймер работает в режиме генерации ШИМ (PWM). Для получения синусоидального напряжения 400 Гц в канале используется высокочастотное изменение коэффициента ШИМ с частотой 40 кГц, на которую настроен системный таймер SysTick. Синусоида формируется с помощью таблицы значений синуса с шагом 360/100 градусов.
Ниже показаны выходные осциллограммы генератора
воскресенье, 24 мая 2015 г.
суббота, 23 мая 2015 г.
2-х фазный ШИМ генератор 400 Герц на STM32F103
2-х фазный ШИМ генератор 400 Герц на STM32F103 с фазами, сдвинутыми на 90 градусов. Частота ШИМ генерации 40 кГц. Для генерации используется TIM4.
четверг, 5 марта 2015 г.
Cortex STM32 memory (& bitband)
Код - эта область адресов используется для доступа к памяти, хранящей исполняемые коды.
Внутреннее ОЗУ - по этим адресам доступна внутренняя оперативная память.
Внутренняя периферия - по этим адресам доступны регистры управления внутренней периферией контроллера.
Внешнее ОЗУ - эта область адресов используется для доступа к внешней оперативной памяти.
Внешняя периферия - эта область адресов используется для доступа к внешней периферии.
Системная область - по этим адресам доступно управление самим ядром.
среда, 18 февраля 2015 г.
понедельник, 16 февраля 2015 г.
RCC STM32F1
Контроллеры STM32 обладают достаточно развитой системой тактирования, включающей кучу различных делителей, умножителей и селекторов, которые позволяют "разогнать" до 72 МГц частоту ядра и системной шины, а также организовать тактирование на различных частотах всех входящих в состав контроллера модулей (USB, I/O, I2C, SPI...).
При этом стартует контроллер всегда от внутреннего генератора на 8 МГц, а дальнейший "разгон" и настройка тактирования различных модулей выполняется программно.
Все регистры, отвечающие за настройку системы тактирования сгруппированы в так называемый блок RCC (reset and clock control). Это десять 32-х битных регистров, доступных в памяти начиная с адреса 0x40021000, названия которых начинаются с "RCC_".
Настройку системы тактирования можно разделить на два этапа. На первом этапе настраивается системная тактовая частота. На втором этапе - частота системной шины AHB и подключенные к шине AHB модули. Отдельно от этих двух этапов можно настроить низкоскоростные генераторы для часов реального времени и независимого "собачьего таймера".
При этом стартует контроллер всегда от внутреннего генератора на 8 МГц, а дальнейший "разгон" и настройка тактирования различных модулей выполняется программно.
Все регистры, отвечающие за настройку системы тактирования сгруппированы в так называемый блок RCC (reset and clock control). Это десять 32-х битных регистров, доступных в памяти начиная с адреса 0x40021000, названия которых начинаются с "RCC_".
Настройку системы тактирования можно разделить на два этапа. На первом этапе настраивается системная тактовая частота. На втором этапе - частота системной шины AHB и подключенные к шине AHB модули. Отдельно от этих двух этапов можно настроить низкоскоростные генераторы для часов реального времени и независимого "собачьего таймера".
суббота, 14 февраля 2015 г.
STM32 Assembler routine sqrt modul
Функция подсчета модуля вектора (квадрат модуля не должен превышать 32 бита)
AREA |.text|, CODE, READONLY
sqrt_32 PROC
EXPORT sqrt_32 [WEAK]
MUL R0,R0,R0
MUL R1,R1,R1
ADD R0,R0,R1
; Optimised 32-bit integer sqrt
; INPUT
; Calculates square root of R0
; OUTPUT
; Result returned in R0
AREA |.text|, CODE, READONLY
sqrt_32 PROC
EXPORT sqrt_32 [WEAK]
MUL R0,R0,R0
MUL R1,R1,R1
ADD R0,R0,R1
; Optimised 32-bit integer sqrt
; INPUT
; Calculates square root of R0
; OUTPUT
; Result returned in R0
воскресенье, 8 февраля 2015 г.
среда, 4 февраля 2015 г.
CMSIS DSP Library: arm_sqrt_q15
Определение функции:
arm_status arm_sqrt_q15(q15_t in, q15_t * pOut)
q15 - формат с фиксированной точкой 1.15 в котором 0 представлен как 0х0000, а 1 представлена как 0х7FFF. Это значит, что например 1/2 будет представлена в формате 0х4000, а 1/4 как 0х2000. Функция возвращает статус ARM_MATH_SUCCESS или ARM_MATH_ARGUMENT_ERROR. Результат функция возвращает по ссылке pOut. Результат представлен также в формате q15. Например
arm_sqrt_q15(0x1000,&out);
0х1000 является представлением в формате q15 числа 1/8 или 0.125. Корень квадратный sqrt(0.125)=0.3536. Функция дает результат 0х2D42 = 11586/2^15 = 0,3536. Время выполнения функции для 32F103 @72MHz - 244 такта (3,39 mks).
Аналогичным образом используется и более точная функция:
arm_sqrt_q31(q31_t in, q31_t * pOut);
Ее время выполнения функции для 32F103 @72MHz - 286 тактов (3,97 mks).
Для плавающей точки:
arm_sqrt_f32(float32_t in, float32_t * pOut);
Время выполнения функции для 32F103 @72MHz - 544 такта (7,56 mks).
Указанное время выполнения функций были определены для версии V1.4.4 библиотеки CMSIS DSP (Date: 12. March 2014), которая идентична предыдущим версиям V1.4.3, V1.4.2, и V1.4.1.
Для справки: при использовании стандартной библиотеки Си math.h для различных типов переменных получим примерно такие (в зависимости от аргумента) времена выполнения функций в тактах
float sqrtf(float) ~ 575
double sqrt(double) ~ 2640
arm_status arm_sqrt_q15(q15_t in, q15_t * pOut)
q15 - формат с фиксированной точкой 1.15 в котором 0 представлен как 0х0000, а 1 представлена как 0х7FFF. Это значит, что например 1/2 будет представлена в формате 0х4000, а 1/4 как 0х2000. Функция возвращает статус ARM_MATH_SUCCESS или ARM_MATH_ARGUMENT_ERROR. Результат функция возвращает по ссылке pOut. Результат представлен также в формате q15. Например
arm_sqrt_q15(0x1000,&out);
0х1000 является представлением в формате q15 числа 1/8 или 0.125. Корень квадратный sqrt(0.125)=0.3536. Функция дает результат 0х2D42 = 11586/2^15 = 0,3536. Время выполнения функции для 32F103 @72MHz - 244 такта (3,39 mks).
Аналогичным образом используется и более точная функция:
arm_sqrt_q31(q31_t in, q31_t * pOut);
Ее время выполнения функции для 32F103 @72MHz - 286 тактов (3,97 mks).
Для плавающей точки:
arm_sqrt_f32(float32_t in, float32_t * pOut);
Время выполнения функции для 32F103 @72MHz - 544 такта (7,56 mks).
Указанное время выполнения функций были определены для версии V1.4.4 библиотеки CMSIS DSP (Date: 12. March 2014), которая идентична предыдущим версиям V1.4.3, V1.4.2, и V1.4.1.
Для справки: при использовании стандартной библиотеки Си math.h для различных типов переменных получим примерно такие (в зависимости от аргумента) времена выполнения функций в тактах
float sqrtf(float) ~ 575
double sqrt(double) ~ 2640
среда, 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
}
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 и в коде добавить функцию:
Этот макрос выполняет проверку выражения с участием проверяемого аргумента функции на равенство нулю. Если значение выражения равно нулю, то вызывается функция-обработчик ошибки аргумента 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);
}
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
Подписаться на:
Сообщения (Atom)













