Всем привет!
Пытаюсь выжать аппаратно ШИМ сигнал из STM32F100C8T6, частота 4800Гц, фишка в том что скважность меняется каждый такт, импульсы повторяются в таком порядке: 30%, 70%, 95%, 95%, 70%, 30%, это значения скважности в %.
Использую TIM1 и каналы 2й и 4й, это ноги РА9 и РА11.
Скважность меняю в прерывании по сравнению, регистр таймера и регистр сравнения буферизованы, то есть их значения меняются после Update Event, который происходит после переполнения таймера.
На частоте 400Гц или чуть больше всё получается, но при увеличении частоты что-то ломается и пара импульсов идет не с той скважностью, причём у каждого канала это своя пара, но порядок чёткий и не меняется например при увеличении частоты на порядок.
Добавлено after 2 minutes 23 seconds:Мне кажется проблема в аппаратных возможностях F100, поправьте если ошибаюсь
Код инициализации и обработчика прерывания:
Спойлер
Код:
void GPIO_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef temp_GPIO_Init;
//PWM
temp_GPIO_Init.GPIO_Pin = PH1sig|PH2sig;
temp_GPIO_Init.GPIO_Speed = GPIO_Speed_10MHz;
temp_GPIO_Init.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &temp_GPIO_Init);
}
void PWM_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM1->CCMR1 = 0x0000;
TIM1->CR1 = 0x0000;
TIM1->CCER = 0x0000;
TIM1->DIER = 0x0000;
TIM1->BDTR = 0x0000;
TIM1->CCMR1 |= 0x6000; //PWM1 mode CH2
TIM1->CCMR2 |= 0x6000; //PWM1 mode CH4
TIM1->ARR = 20000;
TIM1->CCR2 = 1000;
TIM1->CCR4 = 1000;
//TIM1->PSC = 0x0009;
TIM1->CCMR1 |= 0x0800; //OC2 preload enable
TIM1->CCMR2 |= 0x0800; //OC4 preload enable
TIM1->CR1 |= 0x0080; //ARR preload enable
TIM1->CCER |= 0x0010; //CC2E = 1
TIM1->CCER |= 0x1000; //CC4E = 1
TIM1->BDTR |= 0x8000; //MOE = 1
TIM1->EGR |= 0x0001; //generate update event
TIM1->CR1 |= 0x0001; //counter enable
TIM1->DIER |= 0x0004; //compare CH2 interrupt enable
NVIC_EnableIRQ(TIM1_CC_IRQn);
__enable_irq(); //вроде не нужно, на всякий случай
}
#define PULSE_A 30
#define PULSE_B 70
#define PULSE_C 95
void TIM1_CC_IRQHandler(void)
{
TIM1->SR &= 0xFFE0; //5 flags reset
period = (float)TIM1->ARR;
switch(pulse)
{
case 1:
TIM1->CCR2 = (period/100)*PULSE_A;
TIM1->CCR4 = (period/100)*PULSE_C;
pulse += 1;
break;
case 2:
TIM1->CCR2 = (period/100)*PULSE_B;
TIM1->CCR4 = (period/100)*PULSE_B;
pulse += 1;
break;
case 3:
TIM1->CCR2 = (period/100)*PULSE_C;
TIM1->CCR4 = (period/100)*PULSE_A;
pulse += 1;
break;
case 4:
TIM1->CCR2 = (period/100)*PULSE_C;
pulse += 1;
break;
case 5:
TIM1->CCR2 = (period/100)*PULSE_B;
TIM1->CCR4 = (period/100)*PULSE_B;
pulse += 1;
break;
case 6:
TIM1->CCR2 = (period/100)*PULSE_A;
TIM1->CCR4 = (period/100)*PULSE_C;
pulse += 1;
break;
case 7:
TIM1->CCR2 = (period/100)*PULSE_A;
pulse += 1;
break;
case 8:
TIM1->CCR2 = (period/100)*PULSE_B;
TIM1->CCR4 = (period/100)*PULSE_B;
pulse += 1;
break;
case 9:
TIM1->CCR2 = (period/100)*PULSE_C;
TIM1->CCR4 = (period/100)*PULSE_A;
pulse += 1;
break;
case 10:
TIM1->CCR2 = (period/100)*PULSE_C;
pulse += 1;
break;
case 11:
TIM1->CCR2 = (period/100)*PULSE_B;
TIM1->CCR4 = (period/100)*PULSE_B;
pulse += 1;
break;
case 12:
TIM1->CCR2 = (period/100)*PULSE_A;
TIM1->CCR4 = (period/100)*PULSE_C;
pulse = 1;
break;
default:
break;
}
}
Добавлено after 4 hours 51 minute 7 seconds:В общем проблема была из-за использования float в прерывании.