OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5450|回复: 4

请教原子哥关于脉冲输出的问题

[复制链接]

4

主题

10

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2013-8-5
在线时间
0 小时
发表于 2014-3-10 21:39:13 | 显示全部楼层 |阅读模式

我想输出一个频率可变,占空比不变的脉冲。程序如下所示(只贴出有关定时器配置):

void Timer3_Configuration(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 TIM_OCInitTypeDef TIM_OCInitStructure; 
 
 TIM_DeInit(TIM3);
 TIM_TimeBaseStructure.TIM_Period=0;//cycle;
 TIM_TimeBaseStructure.TIM_Prescaler=0;
 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
 TIM_OCInitStructure.TIM_Pulse=0;
 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; 
 TIM_OC2Init(TIM3,&TIM_OCInitStructure); 
 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
 TIM_ARRPreloadConfig(TIM2, DISABLE);
    TIM_Cmd(TIM3,ENABLE);
 TIM_CtrlPWMOutputs(TIM3, ENABLE);
}


  
 cycle=(u16)((720*1000)/(200*44*speed/6000));
 TIM_SetAutoreload(TIM3, cycle); 
 TIM_SetCompare2(TIM3, cycle/2);

speed变化范围在1000-1900r/min  想要输出的脉冲信号的频率就是(200*44*speed/60)

问题就是输出的占空比频率误差太大了,如下图所示(1770r/min):


用示波器检测输出的脉冲信号发现频率差太多了,而且跳动特别大,如下图所示:



 



频率都是兆赫兹数量级,程序也不知道哪里有问题
我是小菜鸟,希望原子哥和各位高手给我说一下怎么去调整。
整个程序主要用了一个ADC,三个定时器(一个定时,一个输出脉冲,一个计数外部的脉冲数)



 


 




 

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2014-3-10 22:37:37 | 显示全部楼层
TIM_SetAutoreload(TIM3, cycle); 
 TIM_SetCompare2(TIM3, cycle/2); 
这里确实可以改变频率和占空比,你的输出误差很大,你看看cycle是不是你想要的结果呢?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

10

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2013-8-5
在线时间
0 小时
 楼主| 发表于 2014-3-11 11:15:02 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
测试在转速是1900r/min的时候还是准的,后面speed变小了就突然干扰很大,之后就不准了
#include "stm32f10x.h"




void GPIO_Configuration(void);
void RCC_Configuration(void);
void Timer_Configuration(void);
void Timer3_Configuration(void);
void Timer4_Configuration(void);
void NVIC_Configuration(void);
void ADC_RegularChannelConfiguration(void);
void USART_Configuration(void);
void USART_Send(u8);
void display(u16);
void  Delay(u8);
u16 speed=0,Max,Min,sum,angle=0; //,current=0
u16 advalue[7]={0,0,0,0,0,0,0};
u8  speed_h,speed_l,angle_h,angle_l,i,zero=0,cycle=0,round=0,wait;  //,current_h=0,current_l=0
u8  dis[8];
const char  shuzi[10]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
float current=0,adc_value=0;//resistor=0,voltage=0, ,speed_value=0 ,kw=0

#define SDATA_595_0  GPIO_ResetBits(GPIOE,GPIO_Pin_8)
#define SDATA_595_1  GPIO_SetBits(GPIOE,GPIO_Pin_8)
#define SCLK_595_0  GPIO_ResetBits(GPIOE,GPIO_Pin_9)
#define SCLK_595_1  GPIO_SetBits(GPIOE,GPIO_Pin_9)
#define RCK_595_0  GPIO_ResetBits(GPIOE,GPIO_Pin_10)
#define RCK_595_1  GPIO_SetBits(GPIOE,GPIO_Pin_10)
#define CS_LED8_0  GPIO_ResetBits(GPIOD,GPIO_Pin_6)
#define CS_LED8_1  GPIO_SetBits(GPIOD,GPIO_Pin_6)
#define CS_1302_0  GPIO_ResetBits(GPIOD,GPIO_Pin_7)
#define CS_1302_1  GPIO_SetBits(GPIOD,GPIO_Pin_7)


int main(void)
{
RCC_Configuration(); 
GPIO_Configuration(); 
Timer_Configuration();
Timer3_Configuration();
NVIC_Configuration();
ADC_RegularChannelConfiguration();
USART_Configuration();
CS_1302_0;
while(1)
{
 

}  
}

void TIM2_IRQHandler(void)
{
     wait++;
if(wait==2)   
{
 display(speed);
 wait=0;
 }
 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
 ADC_SoftwareStartConvCmd(ADC1,ENABLE);
 i++;
  while(!(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)));
  advalue=ADC_GetConversionValue(ADC1);
  ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
  ADC_SoftwareStartConvCmd(ADC1,DISABLE);
  if(i==7)
  {
  i=0;
  Max=advalue[0];
      Min=advalue[0];
      sum=advalue[0];
      for(i=1;i<7;i++) 
       {
         sum=sum+advalue;
         if(advalue>Max) Max=advalue;
         if(advalue<Min) Min=advalue;
       }
  adc_value=(sum-Max-Min)/5;

      current=0.06672*adc_value-140.5;
     speed=(u16)(60*(12-0.1*current)/(0.0842*3.14)-681);

    cycle=(u16)((720*1000)/(200*44*speed/6000));
      TIM_SetAutoreload(TIM3, cycle); 
      TIM_SetCompare2(TIM3, cycle/2); 

  angle = TIM_GetCounter(TIM4); 
  speed_h=(u8)((speed&0xff00)>>8);
      speed_l=(u8)(speed&0x00ff);


  }


 
}


void TIM4_IRQHandler(void)
{    
if (TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)    
   { 
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清TIM2标志位 
round=round+1;
    } 
   }

/*******************************************************************************
* Function Name: RCC_Configuration
* Description : Configures the different system clocks.
* Input       : None
* Output      : None
* Return      : None
*******************************************************************************/
void RCC_Configuration(void) 
{

    /* Enable refetch Buffer 设置预取缓冲器可以提高CPU的执行速度*/
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
 
    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    
    /* RCC system reset(for debug purpose) */
    RCC_DeInit();

    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
    //也可以用:while (!(RCC_WaitForHSEStartUp()== SUCCESS));

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
  
    /* CLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);  

    /* CLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2); 

    /* LLCLK = 8MHz * 9 = 72 MHz */                         
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable LL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till LL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    /* Select LL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till LL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08);     

    /* Enable GPIOB clocks */  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);// 使能APB2外设GPIOE时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);// 使能APB2外设GPIOE时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);// 使能APB2外设GPIOE时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOD , ENABLE);// 使能APB2外设GPIOE|D时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 

}

/*******************************************************************************
* Function Name: GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input       : None
* Output      : None
* Return      : None
*******************************************************************************/

void GPIO_Configuration(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
    
   /* Configure B.8 as output push-pull */

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选择PX.10/11        
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //模式为推挽输出 
   GPIO_Init(GPIOA, &GPIO_InitStructure);                  //初始化GPIOB寄存器

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //选择PX.10/11        
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //模式为推挽输出 
   GPIO_Init(GPIOA, &GPIO_InitStructure);  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;  //PWM输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选择PX.10/11        
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //模式为推挽输出 
   GPIO_Init(GPIOB, &GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOE, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);


//GPIO的配置设置,包括管脚、模式和频率

void Timer_Configuration(void)    

{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;



TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period=9;
TIM_TimeBaseStructure.TIM_Prescaler=35999;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); 
 
  TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); 
TIM_Cmd(TIM2,ENABLE);

}

void Timer3_Configuration(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period=0;//cycle;
TIM_TimeBaseStructure.TIM_Prescaler=0;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); 

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=0;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_ARRPreloadConfig(TIM2, DISABLE);
    TIM_Cmd(TIM3,ENABLE);
TIM_CtrlPWMOutputs(TIM3, ENABLE);
}



void Timer4_Configuration(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_DeInit(TIM4);
TIM_TimeBaseStructure.TIM_Period=999;//cycle;
TIM_TimeBaseStructure.TIM_Prescaler=0;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure); 

    TIM_ETRClockMode2Config(TIM4, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted , 0);
    TIM_SetCounter(TIM4, 0x0);
TIM_ClearFlag(TIM4,TIM_FLAG_Update);//清除溢出中断标志位  
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); //打开中断 溢出中断   
    TIM_Cmd(TIM4,ENABLE);
}


void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void ADC_RegularChannelConfiguration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel=1;
ADC_Init(ADC1,&ADC_InitStructure);

ADC_RegularChannelConfig(ADC1,ADC_Channel_2,1,ADC_SampleTime_55Cycles5);
ADC_Cmd(ADC1,ENABLE);

ADC_ResetCalibration(ADC1); 
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));  
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
ADC_SoftwareStartConvCmd(ADC1,DISABLE);

}

void USART_Configuration(void)
{

  USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);


 }
void USART_Send(u8 data)
{
while(!(USART_GetFlagStatus(USART1,USART_FLAG_TC)));
USART_SendData(USART1,data);
USART_ClearFlag(USART1,USART_FLAG_TC);
}

void  Delay(u8  dly)
{  u16  i;

   for(; dly>0; dly--)
      for(i=0; i<600; i++);
}

void display(u16 speed)
{
 u8 t,t1,t2,value,num;
 for(t=0;t<8;t++)
  {
   if (t==0)     value=speed%10;
   else if(t==1) value=(speed%100)/10;
   else if(t==2) value=(speed%1000)/100;
   else if(t==3) value=speed/1000;
   else value=0;
   dis[t]=shuzi[value];
  }
  t=0;
  for(t1=0;t1<8;t1++)
  {
   num=dis[t1];
CS_LED8_0;
for(t2=0;t2<8;t2++) //写入显示数据
{
SCLK_595_0;
if((num&(0x80))==0x80) SDATA_595_1;
else SDATA_595_0;
num=num<<1;
SCLK_595_1;
SCLK_595_0;
}
num=~(1<<t1);
for(t2=0;t2<8;t2++) //写入数码管序号
{
SCLK_595_0;
if((num&(0x80))==0x80) SDATA_595_1;
else SDATA_595_0;
num=num<<1;
SCLK_595_1;
SCLK_595_0;
}
RCK_595_0;
__nop(); //短延时
__nop();
RCK_595_1; 
__nop();
__nop();
RCK_595_0; //显示数据输出
Delay(20);
CS_LED8_1;
  }
}


源程序都在这里了,真的找不出原因啊。。>
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2014-3-11 23:42:17 | 显示全部楼层
回复【3楼】wukon:
---------------------------------
这一对代码,我看着也头大....
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

10

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2013-8-5
在线时间
0 小时
 楼主| 发表于 2014-3-18 22:30:36 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
谢谢原子哥,我再找找看!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-13 16:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表