2-х фазный ШИМ генератор 400 Герц на STM32F103 с фазами, сдвинутыми на 90 градусов. Частота ШИМ генерации 40 кГц. Для генерации используется TIM4.
Ярлыки
_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)
Показаны сообщения с ярлыком STM32F1. Показать все сообщения
Показаны сообщения с ярлыком STM32F1. Показать все сообщения
суббота, 23 мая 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 модули. Отдельно от этих двух этапов можно настроить низкоскоростные генераторы для часов реального времени и независимого "собачьего таймера".
воскресенье, 8 февраля 2015 г.
среда, 17 декабря 2014 г.
STM32F103 PWM init TIM1
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // Enable GPIOB clocking RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Enable GPIOA clocking RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // Enable TIM1 clocking RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Enable AFIO clocking //////////////////////////////////////////////////////////////////////////////// GPIO GPIOB->CRL = (GPIO_CRL_MODE0 |
GPIO_CRL_CNF0_1); // PB0 - Output mode 50 MHz GPIOB->CRL &= (~GPIO_CRL_CNF0_0); // and alternate push-pull //---------------------------------------- GPIOA->CRL |= (GPIO_CRL_MODE7 | GPIO_CRL_CNF7_1); // PA7 - Output mode 50 MHz GPIOA->CRL &= (~GPIO_CRL_CNF7_0); // and alternate push-pull //---------------------------------------- GPIOA->CRH |= (GPIO_CRH_MODE8 |
GPIO_CRH_MODE9 |
GPIO_CRH_CNF8_1 |
GPIO_CRH_CNF9_1); // PA8, PA9 - Output mode 50 MHz GPIOA->CRH &= (~(GPIO_CRH_CNF8_0 |
GPIO_CRH_CNF9_0)); // and alternate push-pull GPIOA->ODR = 0x0000;//---------------------------------------
AFIO->MAPR |= AFIO_MAPR_TIM1_REMAP_0;
AFIO->MAPR &= (~AFIO_MAPR_TIM1_REMAP_1); //////////////////////////////////////////////////////////////////////////////// PWM Timer 1 TIM1->CR1 = TIM_CR1_ARPE; TIM1->PSC = 8; TIM1->ARR = 0x00FF;
TIM1->CCR1 = 100; TIM1->CCR2 = 0xFF; TIM1->CCR3 = 0x00; TIM1->CCR4 = 0x00;
TIM1->CCMR1 = (TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2M);
TIM1->CCER = (TIM_CCER_CC1E | /*TIM_CCER_CC1P |*/ TIM_CCER_CC1NE | /*TIM_CCER_CC1NP |*/ TIM_CCER_CC2E | /*TIM_CCER_CC2P |*/ TIM_CCER_CC2NE /*| TIM_CCER_CC2NP*/);
TIM1->BDTR = (TIM_BDTR_MOE | ((4<<5) | 10));
TIM1->CR1 |= TIM_CR1_CEN;
#include "stm32f10x_lib.h"
#include "pwm.h"
TIM1_TimeBaseInitTypeDef TIM1_TimeBaseStructure;
TIM1_OCInitTypeDef TIM1_OCInitStructure;
TIM1_BDTRInitTypeDef TIM1_BDTRInitStructure;
extern GPIO_InitTypeDef GPIO_InitStructure;
void InitPWM(void) {
// Enable GPIOA and GPIOB clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// GPIOA Configuration: Channel 1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Enable TIM1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// TIM1 Peripheral Configuration
TIM1_DeInit();
// Time Base configuration
TIM1_TimeBaseStructure.TIM1_Prescaler = 0x0;
TIM1_TimeBaseStructure.TIM1_CounterMode = TIM1_CounterMode_Up;
// TIM1_TimeBaseStructure.TIM1_Period = 0xFFF; // 12 bit
TIM1_TimeBaseStructure.TIM1_Period = 0x3FF; // 10 bit
TIM1_TimeBaseStructure.TIM1_ClockDivision = 0x0;
TIM1_TimeBaseStructure.TIM1_RepetitionCounter = 0x0;
TIM1_TimeBaseInit(&TIM1_TimeBaseStructure);
// Channel 1 Configuration in PWM mode
TIM1_OCInitStructure.TIM1_OCMode = TIM1_OCMode_PWM2;
TIM1_OCInitStructure.TIM1_OutputState = TIM1_OutputState_Enable;
TIM1_OCInitStructure.TIM1_OutputNState = TIM1_OutputNState_Enable;
TIM1_OCInitStructure.TIM1_Pulse = 0x3FF;
TIM1_OCInitStructure.TIM1_OCPolarity = TIM1_OCPolarity_Low;
TIM1_OCInitStructure.TIM1_OCNPolarity = TIM1_OCNPolarity_Low;
TIM1_OCInitStructure.TIM1_OCIdleState = TIM1_OCIdleState_Set;
TIM1_OCInitStructure.TIM1_OCNIdleState = TIM1_OCIdleState_Reset;
TIM1_OC1Init(&TIM1_OCInitStructure);
// Automatic Output enable, Break, dead time and lock configuration
TIM1_BDTRInitStructure.TIM1_OSSRState = TIM1_OSSRState_Enable;
TIM1_BDTRInitStructure.TIM1_OSSIState = TIM1_OSSIState_Enable;
TIM1_BDTRInitStructure.TIM1_LOCKLevel = TIM1_LOCKLevel_1;
TIM1_BDTRInitStructure.TIM1_DeadTime = 0x05;
TIM1_BDTRInitStructure.TIM1_Break = TIM1_Break_Disable;
TIM1_BDTRInitStructure.TIM1_BreakPolarity = TIM1_BreakPolarity_High;
TIM1_BDTRInitStructure.TIM1_AutomaticOutput = TIM1_AutomaticOutput_Enable;
TIM1_BDTRConfig(&TIM1_BDTRInitStructure);
// TIM1 counter enable
TIM1_Cmd(ENABLE);
// Main Output Enable
TIM1_CtrlPWMOutputs(ENABLE);
}
void SetDutyPeriod(Int16U period) {
TIM1_OCInitStructure.TIM1_Pulse = period;
TIM1_OC1Init(&TIM1_OCInitStructure);
}
воскресенье, 14 декабря 2014 г.
General-purpose timers (TIM2 to TIM5) RM0008
Все блоки таймеров выполнены на основе 16-битного перезагружаемого счетчика, который синхронизируется с выхода 16-битного предделителя. Перезагружаемое значение хранится в отдельном регистре. Счет может быть прямой, обратный или двунаправленный (сначала прямой до определенного значения, а затем обратный). Вход синхронизации счетчика можно связать с одним из восьми различных источников. В их число входят: специальный сигнал синхронизации, производный от сигнала главной системной синхронизации; выходной сигнал синхронизации одного из других таймеров или внешний сигнал синхронизации, связанный с выводами захвата/сравнения.
Каждый из четырех таймеров МК STM32 содержит 16-битный счетчик, 16-битный предделитель частоты и 4-канальный блок захвата/сравнения. Их можно синхронизировать системной синхронизацией, внешними сигналами или другими таймерами.
Помимо составляющего основу таймера счетчика, в каждый блок таймера также входит четырехканальный блок захвата/сравнения. Данный блок выполняет, как стандартные функции захвата и сравнения, так и ряд специальных функций. Каждый из таймеров может генерировать прерывания и поддерживает ПДП. Каждый канал захвата/сравнения управляется через один регистр. Данный регистр имеет несколько функций, которые зависят от установок бит выбора. В режиме захвата, данный блок выполняет фильтрацию на входах, поддерживает специальный режим измерения внешнего ШИМ-сигнала, а также имеет входы для подключения внешнего энкодера. В режиме сравнения, блок выполняет стандартные функции сравнения, генерации ШИМ-сигналов, а также поддерживает опциональную функцию одновибратора.
Basic таймеры тактируются от шины APB1. Если ничего не менять в настройках тактирования и оставить их по умолчанию, то частота APB1 составляет 72МГц при условии что подключен внешний кварц на частоту 8 МГц.
TIMx_CNT-счётный 16-ти битный регистр, занимающийся непосредственно счётом времени. Каждый раз когда с шины APB1 приходит тактовый импульс, содержимое этого регистра увеличивается на едницу. Когда регистр переполняется, все начинается с нуля. При дефолтной частоте шины APB1, таймер за одну секунду тикнет 72 млн раз! Это очень дофига, и поэтому у таймера есть предделитель, управлять которым мы можем при помощи регистра TIMx_PSC. Записав в него значение 72000-1 мы заставим счётный регистр TIMx_CNT увеличивать свое значение каждую милисекунду (Частоту APB1 делим на число в регистре предделителе и получаем сколько раз в секунду увеличивается счётчик). Единицу нужно вычесть потому, что если в регистре ноль то это означает, что включен делитель на единицу. Теперь, когда счётный регистр дотикает до 1000 мы можем точно заявить, что прошла ровно одна секунда! И че теперь опрашивать счётный регистр и ждать пока там появится 1000? Это не наш метод, ведь мы можем заюзать прерывания! Но вот беда, прерывание у нас всего одно, и возникает оно когда счётчик обнулится. Для того чтоб счётчик обнулялся досрочно, а не когда дотикает до 0xFFFF, служит регистр TIMx_ARR. Записываем в него то число до которого должен досчитывать регистр TIMx_CNT перед тем как обнулиться. Если мы хотим чтоб прерывание возникало раз в секунду, то нам нужно записать туда 1000. По части непосредственно отсчёта времени это все, но таймер сам по себе тикать не начнет. Его нужно включить установив бит CEN в регистре TIMx_CR1. Этот бит разрешает начать отсчёт, соответственно если его сбросить то отсчет остановится (ваш К.О.). В регистре есть и другие биты но они нам не особо интересны. Зато интересен нам еще один бит, но уже в регистре TIMx_DIER. Называется он UIE, установив его мы разрешаем таймеру генерить прерывания при сбросе счётного регистра. Итак небольше резюме: Чтоб заюзать basic таймер нужно:
-Установить предделитель чтоб таймер не тикал быстро (TIMx_PSC)
-Задать предел до которого таймер должен дотикать перед своим сбросом (TIMx_ARR)
-Включить отсчет битом CEN в регистре TIMx_CR1
-Включить прерывание по переполнению битом UIE в регистре TIMx_DIER
суббота, 29 ноября 2014 г.
SPI2 в режиме мастера для работы с DMA
void SPI_init(void)
{
// SPI2 init
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // такты на SPI2
GPIOB->CRH &= (~(GPIO_CRH_CNF13_0 | GPIO_CRH_CNF15_0)); //настройка выводов для SPI
GPIOB->CRH |= (GPIO_CRH_MODE13 | GPIO_CRH_MODE15
| GPIO_CRH_CNF13_1 | GPIO_CRH_CNF15_1); // AF Push-Pull out
SPI2->CR1 |= SPI_CR1_BR_1 //настройка делителя
// | SPI_CR1_BR_0 //комментируя или раскомментируя эти строки можно изменять значение делителя
// | SPI_CR1_BR_2
| SPI_CR1_SSM // программное управление слэйвом
| SPI_CR1_SSI // при программном управлении слэйвом данный бит должен быть 1
| SPI_CR1_MSTR // Режим мастера
| SPI_CR1_SPE; // разрешить SPI2
SPI2->CR2 |= SPI_CR2_RXDMAEN // разрешить передачу принятых данных через DMA
| SPI_CR2_TXDMAEN; // Разрешить принимать данные для передачи через DMA
return;
}
DMA для работы с SPI2 на прием и передачу
RCC->AHBENR |= RCC_AHBENR_DMA1EN; //такты
// 4 канал DMA1 RX SPI2 -> память
DMA1_Channel4->CPAR = SPI2_BASE+0x0C; // адрес DR
DMA1_Channel4->CMAR = pSPI2_readbuf_addr->Buf_Addr; //адрес буфера приема
DMA1_Channel4->CNDTR = 12; // размер транзакции
DMA1_Channel4->CCR |= DMA_CCR4_MINC //инкремент адреса буфера
| DMA_CCR4_PSIZE_0; //размерность данных SPI 16 бит (происходит автоматическое преобразование 16->8 бит)
// 5 канал DMA1 память -> TX SPI2
DMA1_Channel5->CPAR = SPI2_BASE+0x0C; //адрес DR
DMA1_Channel5->CMAR = pSPI2_writebuf_addr->Buf_Addr; //адрес буфера передачи
DMA1_Channel5->CNDTR = 12; // размер транзакции
DMA1_Channel5->CCR |= DMA_CCR5_MINC //инкремент адреса буфера
| DMA_CCR5_DIR; // направление передачи из памяти в периферию
Транзакция запускается следующим куском кода:
void SPI2_start (void) // По сути это переинициализация каналов DMA
{
DMA1_Channel4->CPAR = SPI2_BASE+0x0C; //DR Base
DMA1_Channel4->CMAR = pSPI2_readbuf_addr->Buf_Addr;
DMA1_Channel4->CNDTR = 12;
DMA1_Channel5->CPAR = SPI2_BASE+0x0C; //DR Base
DMA1_Channel5->CMAR = pSPI2_writebuf_addr->Buf_Addr;
DMA1_Channel5->CNDTR = 12;
DMA1_Channel4->CCR |= DMA_CCR4_TCIE | DMA_CCR4_EN;
DMA1_Channel5->CCR |= DMA_CCR5_EN;
return;
}
Результаты обрабатываются по прерыванию завершения работы канала DMA работающего на прием данных от SPI:
void DMAChannel4_IRQHandler (void)
{
DMA1_Channel4->CCR &= (~(DMA_CCR4_TCIE | DMA_CCR4_EN)); // выключаем канал приемника и его прерывание
DMA1->IFCR |= DMA_IFCR_CTCIF4 | DMA_IFCR_CGIF4; //очищаем флаги
DMA1_Channel5->CCR &= (~(DMA_CCR5_EN)); // выключаем канал передатчика
pCurrent_mode->stat.led_data_send = 0; // выставляем нужные флаги для дальнейшей работы с данными
HC595_OUT;
pCurrent_mode->stat.read_key_data_ready=1;
return;
}
Подписаться на:
Сообщения (Atom)
