19.08.2016, 21:34
|
|
Почётный гражданин KAZUS.RU
Регистрация: 05.07.2009
Адрес: Запорожье
Сообщений: 1,531
Сказал спасибо: 309
Сказали Спасибо 53 раз(а) в 48 сообщении(ях)
|
SOFTPWM stm32f030f4
Добрый день. Нужно сделать шим на всех ножках Мк(почти на всех). Это получилось. Но немогу понять почему я выше 4 кГц не могу его сделать. Чип работает на 8*13=52 МГц.
Вообщем ниже код.
PHP код:
|
#define PA3(a) GPIO_WriteBit(GPIOA, GPIO_Pin_3, (BitAction)a); #define PA2(a) GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)a); #define PA1(a) GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)a); #define PA0(a) GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)a);
uint8_t temp_bit=0,Time_1=0,LEDpins[5]; uint16_t timer_temp_1=0; RCC_ClocksTypeDef RCC_Clocks;
void SoftwPWM(void) { Time_1++;//это наш счетный регистр if (Time_1==100) //шим от 0 до 100, а не от 0 до 255 { Time_1 = 0; PA2(1); PA1(1); PA0(1); } else { if (LEDpins[0]==Time_1) { PA0(0); } // LEDpins - наш регистр сравнения для каждого канала if (LEDpins[1]==Time_1) { PA1(0); } // ?????????? 1-?? ??? ? 1 if (LEDpins[2]==Time_1) { PA2(0); } // ?????????? 2-?? ??? ? 1
} }
void TIM14_IRQHandler(void) { if (TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM14, TIM_IT_Update); // temp_bit^=1; // if (temp_bit) { // PA2(0); // } else { // PA2(1); // } timer_temp_1++; SoftwPWM(); } }
void Init_PORT(void) { GPIO_InitTypeDef Pin; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBP eriph_GPIOB|RCC_AHBPeriph_GPIOF,ENABLE); Pin.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_1;// OUT Pin.GPIO_Mode = GPIO_Mode_OUT; Pin.GPIO_Speed = GPIO_Speed_50MHz; Pin.GPIO_OType = GPIO_OType_PP; Pin.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOA, &Pin); GPIO_Init(GPIOB, &Pin); GPIO_Init(GPIOF, &Pin); }
void InitTimer14(void) { TIM_TimeBaseInitTypeDef TIM_Time_user; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); TIM_Time_user.TIM_Prescaler = 52 - 1; // kHz TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up; TIM_Time_user.TIM_Period = 4; //?? ????? ?????? ??????? ? ???????????? TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;//32 MHz TIM_TimeBaseInit(TIM14, &TIM_Time_user); NVIC_EnableIRQ(TIM14_IRQn); TIM_ITConfig(TIM14, TIM_IT_Update,ENABLE); TIM_Cmd(TIM14, ENABLE); }
int main(void) { RCC_DeInit(); PLL52(); RCC_AdjustHSICalibrationValue(19); Init_PORT(); InitTimer3(); InitTimer14(); LEDpins[0] = 30; LEDpins[1] = 100; LEDpins[2] = 10; while (1) { if (timer_temp_1 == 30000) {LEDpins[2]++;timer_temp_1 = 0;} //увеличиваем регистр сравнения if (LEDpins[2] › 100) LEDpins[2] = 0; } }
|
Этот код 2 кГц делает шим.
Если я вот тут TIM_Time_user.TIM_Prescaler = 52 - 1; изменю на 5, например, то должен шим стать 20 кГц по идее, но он становится 4.37 кГц и все. Подскажите в чем суть...?
Этот код делал большую частоту шима. Я понимаю что там расчеты выполняются, но неужели настолько они тяжелые?
PHP код:
|
temp_bit^=1; if (temp_bit) { PA2(0); } else { PA2(1); }
|
Аппаратный шим не устраивает. Мне нужен шим на конкретных ножках где то есть аппаратный шим то нет.
Последний раз редактировалось miwutka; 20.08.2016 в 11:05.
|
|
|
|
20.08.2016, 09:56
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,508
Сказал спасибо: 401
Сказали Спасибо 2,218 раз(а) в 1,316 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Сообщение от miwutka
|
Чип работает на 8*13=52 МГц.
|
Не-а, не работает он на такой частоте. 48 МГц максимум у него, выше никак не будет, это же 030-й, а не 103-й.
Стопудово, накосячил с установкой системных делителей, не те делители устанавливал, и вместо PLL поделил системную частоту или частоту периферийных шин, оттого частота таймера и просела.
Аппаратно шим делается на таймере (TIM16 например) вот так:
PHP код:
|
RCC-›APB2ENR |= RCC_APB2ENR_TIM16EN;
TIM16-›PSC = 4-1; //Значение предделителя частоты шины, от которой
// тактирован таймер (шина тоже может делить частоту)
TIM16-›ARR = 256-1; //Значение перезагрузки, определяет деление частоты
// и разрядность ШИМа
TIM16-›CCR1 = 30; //Значение скважности ШИМ
TIM16-›CCMR1 |= TIM_CCMR1_OC1M | TIM_CCMR1_OC1PE; //PWM mode1
TIM16-›CCER |= TIM_CCER_CC1E; //PWM out enable
TIM16-›BDTR |= TIM_BDTR_MOE; //Main enable PWM out
TIM16-›CR1 |= TIM_CR1_CEN; //таймер запущен
|
Например, для разрядности ШИМа 8 бит, максимально возможная частота ШИМа 187,5 кГц при 48 МГц. PSK = 0, ARR = 256-1, делители шины тактировния таймера 1:1.
Когда прескалер PSС таймера = 52-1, то частота счета вообще дичайше падает, в 52 раза. Но зато значение перезагрузки ARR = 4-1 просто не оставляет шансов получить более четырех значений скважности ШИМа - 0%, 33%, 66%, 100%, ведь скважность задается значением CCR, а оно должно быть в пределах от начала счета и до значения ARR. Если CCR › ARR, то таймер не досчитает до CCR и ШИМ будет 100%...
Программный ШИМ делается точно так же, но вместо аппаратного управления идет реакция на прерывания по событиям обновления таймера и сравнения таймера, вот так:
PHP код:
|
//в настройке таймера, вместо включения аппаратного выхода ШИМ вот это записать:
TIM16-›DIER |= TIM_DIER_UIE; //разрешено прерывание по UIE
TIM16-›DIER |= TIM_DIER_CC1IE; //разрешено прерывание по CCIE
NVIC_EnableIRQ(TIM16_IRQn); //разрешены прерывания от TIM16
//обработчик прерываний от таймера:
//по событию обновления таймера на выходе устанавл. лог.1,
//по событию сравнения таймера CCR канала на выходе сбрасывается лог.0
void TIM16_IRQHandler (void)
{
if ((TIM17-›SR & TIM_SR_UIF) != 0) //проверка флага события обновления
{
TIM17-›SR &= ~TIM_SR_UIF; //сброс флага прерывания
GPIOA-›BSRR = GPIO_Pin_1; // _/- на PA1 (лог.1)
// сюда можно добавить включение других выводов
}
if ((TIM17-›SR & TIM_SR_CC1IF) != 0) //проверка флага события сравнения
{
TIM17-›SR &= ~TIM_SR_CC1IF; //сброс флага прерывания
GPIOA-›BRR = GPIO_Pin_1; // -\_ на PA1 (лог.0)
}
//сюда можно дописать выключение других выводов по событиям сравнения в других каналах
}
|
и ФСЁ! Никаких простыней кода, которые написаны и в которых я не разобрался, че там написано.
Однако, макс.частота будет так же не выше указанной ранее.
Последний раз редактировалось NewWriter; 20.08.2016 в 10:47.
|
|
|
Сказали "Спасибо" NewWriter
|
|
|
20.08.2016, 10:44
|
|
Почётный гражданин KAZUS.RU
Регистрация: 05.07.2009
Адрес: Запорожье
Сообщений: 1,531
Сказал спасибо: 309
Сказали Спасибо 53 раз(а) в 48 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Сообщение от NewWriter
|
void TIM16_IRQHandler (void)
{
if ((TIM17-›SR & TIM_SR_UIF) != 0) //проверка флага события обновления
{
TIM17-›SR &= ~TIM_SR_UIF; //сброс флага прерывания
GPIOA-›BSRR = GPIO_Pin_1; // _/- на PA1 (лог.1)
// сюда можно добавить включение других выводов
}
if ((TIM17-›SR & TIM_SR_CC1IF) != 0) //проверка флага события сравнения
{
TIM17-›SR &= ~TIM_SR_CC1IF; //сброс флага прерывания
GPIOA-›BRR = GPIO_Pin_1; // -\_ на PA1 (лог.0)
}
//сюда можно дописать выключение других выводов по событиям сравнения в других каналах
}
|
в прерывании ТИМ16 мы проверяем флаги тим17? Или это ошибка?
|
|
|
|
20.08.2016, 10:50
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,508
Сказал спасибо: 401
Сказали Спасибо 2,218 раз(а) в 1,316 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Ааа, да, опечатка. Писал же в "блокноте", без проверки в отладчике то... Флаги TIM16 надо проверять конечно
|
|
|
|
20.08.2016, 10:54
|
|
Почётный гражданин KAZUS.RU
Регистрация: 05.07.2009
Адрес: Запорожье
Сообщений: 1,531
Сказал спасибо: 309
Сказали Спасибо 53 раз(а) в 48 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Сообщение от NewWriter
|
Чип работает на 8*13=52 МГц.
|
ошибся. Там 8/2 * 13=52. Я на осциллографе проверял. 103-тий на 128 максимум работает. Ну и мне надо чтобы каждый канал был независимым. А в вашем примере, как я понял, получается один регистр сравнения TIM_SR_CC1IF для всех каналов. То есть все каналы будут синхронными, правильно?
|
|
|
|
20.08.2016, 11:02
|
|
Почётный гражданин KAZUS.RU
Регистрация: 05.07.2009
Адрес: Запорожье
Сообщений: 1,531
Сказал спасибо: 309
Сказали Спасибо 53 раз(а) в 48 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Сообщение от NewWriter
|
максимально возможная частота ШИМа 187,5 кГц при 48 МГц.
|
аппаратный шим при TIM_Prescaler = 1 - 1; и TIM_Period = 350; 140 кГц. Если 350 уменьшаю до 300 то ножка остается в высоком уровне и всё. Наверно это аппаратный предел такой... Но мой программный наверно из-за вычислений ограничен.....
|
|
|
|
20.08.2016, 13:48
|
|
Гражданин KAZUS.RU
Регистрация: 16.02.2012
Сообщений: 441
Сказал спасибо: 89
Сказали Спасибо 735 раз(а) в 149 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
для начала не помешает заменить все эти индусо TIM_GetITStatus, TIM_ClearITPendingBit, GPIO_WriteBit прямым обращением к регистрам, SoftwPWM оформить как inline. И не забывать заглядывать в АСМ-листинг, что оно там нагенерировало.
Заработает без проблем на сотнях кГц
|
|
|
|
20.08.2016, 14:22
|
|
Гражданин KAZUS.RU
Регистрация: 16.02.2012
Сообщений: 441
Сказал спасибо: 89
Сказали Спасибо 735 раз(а) в 149 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Сообщение от NewWriter
|
TIM17-›SR &= ~TIM_SR_UIF
|
можно просто единицу писать, без &: TIM17-›SR = ~TIM_SR_UIF
один ldr лишний
|
|
|
|
20.08.2016, 15:56
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,508
Сказал спасибо: 401
Сказали Спасибо 2,218 раз(а) в 1,316 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Нууу 52 МГц - эт уже оверклогинг, там показатели не гарантированы... Хотя попробовал - ничо, тянет. Аппаратно 203 кГц 8-битного ШИМа выдает при 52 МГц.
Опробовал даже разгон до 64 МГц - тоже идет. ШИМ 8 бит, 250 кГц - полет нормальный.
133% разгона... Блин, а я и не пробовал раньше разгонять 030-й. Теперь буду знать. Хотя там наверно потребление запредельное выходит..
PS.. померил - не, всего на пару миллиампер увеличилось.
PHP код:
|
//+++++++++++++++++++++++++++++++++++++++++++++
// ++++++ Переключение на PLL от HSI, 64 МГц. +++++++
/* Enable Prefetch Buffer and set Flash Latency */
FLASH-›ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
/* PLL configuration = HSI/2 * 12 = 48 MHz */
//RCC-›CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC-›CFGR |= (uint32_t) RCC_CFGR_PLLMUL16;
/* Enable PLL */
RCC-›CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC-›CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC-›CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC-›CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC-›CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
//+++++++++++++++++++++++++++++++++++++++++++
/* тест.
* ШИМ 250 кГц при 64 МГц, 8 бит.
*
*/
void Initial_TIM16_PWM(void)
{
RCC-›APB2ENR |= RCC_APB2ENR_TIM16EN;
TIM16-›PSC = 0; //предделитель 1:1
TIM16-›ARR = 256-1; //разрядность ШИМ 8 бит (до 256)
TIM16-›CCR1 = 100; //значение скважности ШИМ
TIM16-›CCMR1 |= TIM_CCMR1_OC1M | TIM_CCMR1_OC1PE; //PWM mode2
TIM16-›CCER |= TIM_CCER_CC1E; //PWM out enable
TIM16-›BDTR |= TIM_BDTR_MOE; //Main enable PWM out
TIM16-›CR1 |= TIM_CR1_CEN; //таймер запущен
}
|
И если уж делать программный ШИМ, то всё равно через аппаратный таймер, программно отрабатывая лишь прерывания по обновлению и сравнению, дергая ноги. Иначе остальной код вообще ничего не сможет делать, считая циклы программно.
Но тут есть ограничения на минимальную и максимальную скважность - отработка прерывания занимает время.
Сообщение от miwutka
|
один регистр сравнения TIM_SR_CC1IF для всех каналов
|
Тогда выбрать таймер, у которого несколько таких регистров сравнения. Прерывание одно на всё, а флаги событий - разные. CC1IF, CC2IF, CC3IF, CC4IF..
Запускаем все таймеры (1, 3, 14, 16, 17 ), получаем 4+4+1+1+1=11 каналов.
Еще один вариант - один системный таймер SysTick. он будет считать тики и генерировать прерывание по обновлению таймера. Программно отрабатываем тики, используя их как счетчик времени.
Системный таймер относится к устройствам ядра Cortex и описан в мануале ядра. Настройка очень простая - вызов встроенной функции SysTick_Config(4800), параметр которой задает делитель таймера. Однако, лучше не увлекаться скоростями счета, не более нескольких килогерц ШИМа, иначе производительность МК катастрофически упадет.
Сообщение от zöner
|
один ldr лишний
|
Да лаааадна, на 52 МГц он захавает и не заметит лишнюю инстукцию.
И если уж придираться, тогда не "единицу", а "ноль", регистр то w0 принимает.
Последний раз редактировалось NewWriter; 20.08.2016 в 16:40.
|
|
|
|
20.08.2016, 16:33
|
|
Гражданин KAZUS.RU
Регистрация: 16.02.2012
Сообщений: 441
Сказал спасибо: 89
Сказали Спасибо 735 раз(а) в 149 сообщении(ях)
|
Re: SOFTPWM stm32f030f4
Цитата:
|
133% разгона... Блин, а я и не пробовал раньше разгонять 030-й.
|
а чего б ему не работать? Если не греть экстремально, в комнатных условиях работает без проблем...
при перегреве есть вероятность нарваться на сбои Flash или периферии...
Сообщение от NewWriter
|
на 52 МГц он захавает и не заметит лишнюю инстукцию
|
мелочь, а приятно...
а за простыни типа TIM_GetITStatus, TIM_ClearITPendingBit, GPIO_WriteBit в виде функций индусам нужно отрывать руки/ноги... Им наверно платят построчно, потому и раздувают такой говнокод...
Последний раз редактировалось zöner; 20.08.2016 в 16:36.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 12:18.
|
|