你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

通过电压反馈AD输入从而调节PWM波的占空比

[复制链接]
701223poi 提问时间:2017-7-24 10:44 /
为恒流源提供PWM的输入,通过分压采进来一个2.5V左右的电压,根据与2.5V的差值经过简单的计算来调节一个50KHz的PWM波形的占空比,应该是个挺简单的程序,但是我出来的效果并不好
效果大致就是,出来一段PWM波,然后出现一段时间的持续高电平,然后继续输出PWM波,也不知道是什么原因导致的,是因为PWM和我的AD部分存在冲突么?

下面是程序:

#include <stdio.h>
#include "stm32f10x.h"

void Delay(void)
{
        int x,y;
        for(x=100;x>0;x--)
                for(y=1000;y>0;y--);

}

void Init_TIMER(void)
{
        TIM_TimeBaseInitTypeDef         TIM_BaseInitStructure;                       

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);          

        TIM_DeInit(TIM4);                                                     

        TIM_InternalClockConfig(TIM4);                                                        
          
        TIM_BaseInitStructure.TIM_Period = 1440-1;                                                                        
                                                                                                                       
                                                                                                                       
        TIM_BaseInitStructure.TIM_Prescaler = 0;                                 
                                                                                                                       
        TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;   
                                                                                                                       
        TIM_TimeBaseInit(TIM4, &TIM_BaseInitStructure);                

        TIM_ARRPreloadConfig(TIM4, ENABLE);                                               

        TIM_Cmd(TIM4, ENABLE);                         
}


void Init_PWM(uint16_t Dutyfactor)
{
          TIM_OCInitTypeDef  TIM_OCInitStructure;                                       
          TIM_OCStructInit(&TIM_OCInitStructure);                                       
          TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                  
          TIM_OCInitStructure.TIM_Pulse = Dutyfactor;                        
                                                                                       
          TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
                                                                                                                            
          TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;           
                                                                                                                                                                                    
    TIM_OC3Init(TIM4, &TIM_OCInitStructure);                                  
          TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);                  
    TIM_CtrlPWMOutputs(TIM4,ENABLE);                                                 
}

void PWM_GPIO_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                                       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);       
                                                                                                                       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                       
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
        GPIO_Init(GPIOB, &GPIO_InitStructure);                                          
}

void key_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                                       

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD ,ENABLE);       
                                                                                                                       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
        GPIO_Init(GPIOD, &GPIO_InitStructure);                                          
}



void ADC_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO | RCC_APB2Periph_ADC1,ENABLE);
                       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                         
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                      
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                            
        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_10, 1, ADC_SampleTime_55Cycles5);
       
        ADC_Cmd(ADC1, ENABLE);                            
          
        ADC_ResetCalibration(ADC1);                        

        while(ADC_GetResetCalibrationStatus(ADC1));         

        ADC_StartCalibration(ADC1);                                

        while(ADC_GetCalibrationStatus(ADC1));            
       
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                 
}


int main(void)
{
        u16 Temp_Value;
        u16        cha_0;
        u16 cha_1;
        uint16_t Pulse=749;                               
        PWM_GPIO_Init();                           
        key_Configuration();               
        ADC_Configuration();
        Init_TIMER();                                       
        Init_PWM(Pulse);                            
while(1)
{
        if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_11)==0)
        {
                        while(1)
                        {
                                Temp_Value = ADC_GetConversionValue(ADC1);
                               
                                if(Temp_Value>=3102)  
                                {
                                        cha_0=(int)((Temp_Value-3102)/74.5);
                                        Pulse=(int)(Pulse+(cha_0*14.4));                                                                       
                                        TIM_SetCompare3(TIM4,Pulse);                  
                                }
                               
                                if(Temp_Value<=3102)  
                                {
                                        cha_1=(int)((3102-Temp_Value)/74.5);
                                        Pulse=(int)(Pulse-(cha_1*14.4));                                                                          
                                        TIM_SetCompare3(TIM4,Pulse);                  
                                }
                        }
  }
}
}


int fputc(int ch, FILE *f)
{
  USART_SendData(USART1, (uint8_t) ch);                                        
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)         
  {}
  return ch;
}


收藏 评论8 发布时间:2017-7-24 10:44

举报

8个回答
dapan100 回答时间:2017-7-25 08:56:03
1.你的ADC时钟没分频,不知道有没有超出ADC最大频率
2.改写占空比太频繁了,定时器打开预加载。你都不等ADC转换完成一直在读有什么意义呢?
要我做会把AD采集和PWM输出同步起来,另外设个控制频率

评分

参与人数 2ST金币 +4 收起 理由
zero99 + 2
MrJiu + 2 很给力!

查看全部评分

LB_yjy 回答时间:2017-7-25 09:06:37
dapan100 发表于 2017-7-25 08:56
1.你的ADC时钟没分频,不知道有没有超出ADC最大频率
2.改写占空比太频繁了,定时器打开预加载。你都不等ADC ...

强!
701223poi 回答时间:2017-7-25 12:04:12
dapan100 发表于 2017-7-25 08:56
1.你的ADC时钟没分频,不知道有没有超出ADC最大频率
2.改写占空比太频繁了,定时器打开预加载。你都不等ADC ...

我用的是STM32F107它的AD部分时钟和103增强型相同,用的是默认时钟配置,默认应该是APB2是72Mhz,在ADC那里是2分频,我查的是给56Mhz时钟时速度最快,但是我不太清楚这个56M是怎么设置得到的,程序里用的采样时间是55.5cycles。
AD采集和PWM同步应该怎么做呢?是用DMA中断么?
控制频率应该怎么设置呢?
dapan100 回答时间:2017-7-25 13:33:44
701223poi 发表于 2017-7-25 12:04
我用的是STM32F107它的AD部分时钟和103增强型相同,用的是默认时钟配置,默认应该是APB2是72Mhz,在ADC那 ...

ADC最大时钟14M,分频系数分别为2468(复位值是二分频,也就是你AD超频了。转换值还准不准没试过)
应该调用一下RCC_ADCCLKConfig(RCC_PCLK2_Div6),给ADC的时钟变为12M。
同步就用定时器触发,控制频率也是用定时器实现
701223poi 回答时间:2017-7-25 14:17:44
dapan100 发表于 2017-7-25 13:33
ADC最大时钟14M,分频系数分别为2468(复位值是二分频,也就是你AD超频了。转换值还准不准没试过)
应该 ...

● ADC转换时间:
─  STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
─  STM32F101xx基本型产品:时钟为28MHz时为1μs(时钟为36MHz为1.55μs)
─  STM32F102xxUSB型产品:时钟为48MHz时为1.2μs
─  STM32F105xx和STM32F107xx产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)

这是在手册上看到的,这个应该是APB2给它的时钟,但是不太清楚56Mhz是怎么得到的,
dapan100 回答时间:2017-7-25 15:39:22
701223poi 发表于 2017-7-25 14:17
● ADC转换时间:
─  STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
─  STM32F10 ...

8M9倍频是72M,7倍频不就是56M了。。。ADC转换一次最少需要1.5+12.5个周期,最大时钟14M,所以是1uS。因为56M4分频刚好是14M,而72M要6分频是12M,所以56M时是1uS,72M反而是1.17uS了
701223poi 回答时间:2017-7-25 15:51:51
dapan100 发表于 2017-7-25 15:39
8M9倍频是72M,7倍频不就是56M了。。。ADC转换一次最少需要1.5+12.5个周期,最大时钟14M,所以是1uS。因 ...

大致明白了,我来试试,
谢谢啦
手动:滑稽
701223poi 回答时间:2017-7-27 17:48:01
dapan100 发表于 2017-7-25 15:39
8M9倍频是72M,7倍频不就是56M了。。。ADC转换一次最少需要1.5+12.5个周期,最大时钟14M,所以是1uS。因 ...

修改了之后似乎还是不行,,
依然是和以前差不多的,还是一小段PWM波然后接一长段的持续高电平输出

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版