看到很多工控的朋友都在用STM32做发加减速固定脉冲pwm,看了很大网上的资料大多数都是用一个固定时间的定时器发一个波进入一次中断,在中断中计脉冲数,总感觉这样繁忙进中断欠妥。其实用STM32其强大的外设应该可以做出微占用,或不占用CPU的程序。以下是本人的思路:
使用两个定时器,一个定时器用于PWM输出,第二个定时器用于计数。先计算好加减速的数据共DMA用。第二个定时器计数完成触发DMA传送数据(同时送CR1启动两个定时器)我没有用DMA,以下是我的程序:
void PWM_Init(void)//这是TM3定时器PWM输出,TM4定时器用于计数的寄存器配置
{
RCC->APB1ENR|=1<<1;
RCC->APB1ENR|=1<<2;
GPIOB->CRL&=0XFFFFFFF0;
GPIOB->CRL|=0X0000000B;
GPIOB->ODR|=1<<0;
TIM3->PSC=71;
TIM3->CR2|=1<<5;
TIM4->SMCR|=1<<5; // Äú2¿′¥·¢2(ITR2)£¬TIM3
TIM4->SMCR|=7<<0; // ía2¿ê±ÖóÄ£ê½1 ¨C Ñ¡ÖDμÄ′¥·¢êäèë(TRGI)μÄéÏéyÑØÇy¶ˉ¼ÆêyÆ÷¡£
TIM4->DIER|=1<<6; //ÔêDíÖD¶Ï
TIM4->DIER|=1<<0; // ê1Äü
TIM4->CR1|=1<<2; //èç1ûê1Äüá˸üDÂÖD¶Ï£¬ÔòÖ»óD¼ÆêyÆ÷òç3ö2Å2úéú¸üDÂÖD¶ÏÇëÇ
TIM3->CCMR2|=7<<4; //CH2 PWM2Ä£ê½
TIM3->CCMR2|=1<<3; //CH2ԤװÔØê1Äü
TIM3->CCER|=1<<8; //OC2 êä3öê1Äü
TIM3->CR1=0x8000; //ARPEê1Äü
MY_NVIC_Init(1,3,TIM4_IRQn,2);
}
void PWM_out(u16 arr,u16 psc)//发出固定脉冲arr输出频率psc输出个数
{
TIM3->ARR=1000000/arr-1;//é趨¼ÆêyÆ÷×Ô¶ˉÖØ×°Öμ
TIM3->CCR3=(1000000/arr)/2; //Õ¼¿Õ±è50%
TIM4->ARR=psc-1;
TIM3->CR1|=0x01; //ê1Äü¶¨ê±Æ÷3
TIM4->CR1|=0X1; //ê1Äü¶¨ê±Æ÷
}
void jiajiansuPWM_out(u16 arr,u16 psc,u16 time)//c[]用于保存十段加速的频率d[]用于保存十段加减速的个数。arr输出频率,psc输出个数, time加减速时间ms
{
u8 i;
u16 j,k=0;
j=arr/10;//2½½øÂö3åêy£¬ÆμÂê
for(i=1;i<10;i++)
{
c=j*i;
d=c*time/(1000);
k=k+c*time/(1000);
}
c[10]=arr;
d[10]=psc-2*k;
for(i=1;i<10;i++)
{
c[20-i]=c;
d[20-i]=d;
}
b=19;
PWM_out(c,d);
}
void TIM4_IRQHandler(void)中断函数
{
if(TIM4->SR&0X0001)
{
TIM3->CR1&=0xfffe;
}
TIM4->SR&=~(1<<0);
b--;
if(b!=0) {PWM_out(c,d);}
}
int main(void)
{
Stm32_Clock_Init(9); //Ïμí3ê±ÖóéèÖÃ
delay_init(72); //Ñóê±3õê¼»ˉ
uart_init(72,9600); //′®¿ú3õê¼»ˉ
LED_Init(); //3õê¼»ˉóëLEDᬽóμÄó2¼t½ó¿ú
PWM_Init(); //2»·ÖÆμ¡£PWMÆμÂê=72000/900=8Khz
while(1)
{
jiajiansuPWM_out(2000,500,10);
while(1);
}
}
一周热门 更多>