OpenEdv-开源电子网

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

ADC采集,PWM输出的问题

[复制链接]

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
发表于 2017-10-29 15:35:07 | 显示全部楼层 |阅读模式
1金钱
我用的是原子哥的pwm和adc的历程,,通过采集ADC的电压值,,来控制LED的亮度的功能,,但是程序单独测试是没有问题的,,组合起来,,pwm不工作,adc的工作是正常的
[mw_shl_code=applescript,true]#include "pwm.h"

          
int main(void)
{
        u8 se=1;
        u16 adc;
        u16 adcx;
        float temp;
        delay_init();                     //延时函数初始化          
        uart_init(9600);                 //串口初始化为9600
        //LED_Init();                                  //初始化与LED连接的硬件接口
        LCD_Init();
        Adc_Init();                                  //ADC初始化       
        TIM1_PWM_Init(899,0);
//        POINT_COLOR=RED;//设置字体为红色
//        LCD_ShowString(60,50,200,16,16,"Mini STM32");       
//        LCD_ShowString(60,70,200,16,16,"ADC TEST");       
//        LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
//        LCD_ShowString(60,110,200,16,16,"2014/3/9");       
//        //显示提示信息
//        POINT_COLOR=BLUE;//设置字体为蓝色
//        LCD_ShowString(60,130,200,16,16,"ADC_CH1_VAL:");             
//        LCD_ShowString(60,150,200,16,16,"ADC_CH1_VOL:0.000V");            
        while(1)
        {
            adcx=Get_Adc_Average(ADC_Channel_1,10);
        //        LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
                temp=(float)adcx*(3.3/4096);
                adcx=temp;
        //        LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
                temp-=adcx;
                temp*=1000;
        //        LCD_ShowxNum(172,150,temp,3,16,0X80);
                //LED0=!LED0;
                //delay_ms(250);
                adc=(float)adcx*242*(3.3/4096);//乘以242电压值装换为798代替PWM中的800的临界值
        //        if(se)adc++;
        //        else adc--;
        //        if(adc>800)se=0;
        //        if(adc==0)se=1;
                TIM_SetCompare1(TIM1,adc);
               
        }                                                                                            
}       
[/mw_shl_code]

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

使用道具 举报

57

主题

121

帖子

0

精华

高级会员

Rank: 4

积分
643
金钱
643
注册时间
2016-10-5
在线时间
50 小时
发表于 2017-10-29 21:32:16 | 显示全部楼层
回复

使用道具 举报

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
 楼主| 发表于 2017-10-29 21:35:06 | 显示全部楼层
能指点一下吗,,,,谢谢
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2017-10-29 22:02:31 | 显示全部楼层
好像是个库的bug,群里很多人问也很多人回复了,好像两个方案能解决

方案1:串口放到pwm(定时器其他功能也是)之后初始化
方案2:定时器函数初始化的时候最前面加上这两句
TIM_OCStructInit(&TIM_OCInitStructure);//设置缺省值,这一步最好加上
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//设置缺省值,这一步最好加上,
防止初始化过程中有的成员并没有赋值出现奇怪错误(用到定时器的其他结构体也类似设置缺省值)
回复

使用道具 举报

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
 楼主| 发表于 2017-10-29 23:31:30 | 显示全部楼层
275891381 发表于 2017-10-29 22:02
好像是个库的bug,群里很多人问也很多人回复了,好像两个方案能解决

方案1:串口放到pwm(定时器其他功 ...

还是不对的,,但是我把串口初始化屏蔽之后led一直是亮的,,,调整了定时器的初始化的位置,,,也试过了,那两句话也加上试了,,,没有变化,,,还是不行[mw_shl_code=applescript,true]#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "pwm.h"

          
int main(void)
{
        u8 se=1;
        u16 adc=0;
        u16 adcx;
        float temp;
        TIM1_PWM_Init(899,0);
        delay_init();                             //延时函数初始化          
//        uart_init(9600);                         //串口初始化为9600
        LED_Init();                                          //初始化与LED连接的硬件接口
        LCD_Init();
        Adc_Init();                                          //ADC初始化       

        POINT_COLOR=RED;                        //设置字体为红色
        POINT_COLOR=BLUE;                        //设置字体为蓝色
        LCD_ShowString(60,130,200,16,16,"ADC_CH1_VAL:");             
        LCD_ShowString(60,150,200,16,16,"ADC_CH1_VOL:0.000V");       
        printf("初始化正常");
        while(1)
        {
    adcx=Get_Adc_Average(ADC_Channel_1,10);
                LCD_ShowxNum(156,130,adcx,4,16,0);//显示ADC的值
                temp=(float)adcx*(3.3/4096);
                adcx=temp;
                LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
                temp-=adcx;
                temp*=1000;
                LCD_ShowxNum(172,150,temp,3,16,0X80);
////                LED0=!LED0;
                adc=adcx*242*(3.3/4096);//乘以242电压值装换为798代替PWM中的800的临界值
//                if(se)adc++;
//                else adc--;
//                if(adc>800)se=0;
//                if(adc==0)se=1;
                TIM_SetCompare1(TIM1,adc);
                printf("主循环正常");
        }                                                                                            
}        [/mw_shl_code]


adc一直工作正常的
        #include "adc.h"
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK miniSTM32开发板
//ADC 代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/7
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////
          
                  
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3                                                                                                                                          
void  Adc_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟


        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA1 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_Init(GPIOA, &GPIO_InitStructure);       

        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
       
        ADC_ResetCalibration(ADC1);        //使能复位校准  
         
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
       
        ADC_StartCalibration(ADC1);         //开启AD校准

        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束

//        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能

}                                  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
          //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      
  
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能       
         
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);
                delay_ms(5);
        }
        return temp_val/times;
}        

PWM函数
#include "pwm.h"
#include "led.h"



//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
         GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
                                                                                    
//        TIM_OCStructInit(&TIM_OCInitStructure);//设置缺省值,这一步最好加上
//        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//设置缺省值,这一步最好加上,
       
       
   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

       
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         80K
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位


        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

  TIM_CtrlPWMOutputs(TIM1,ENABLE);        //MOE 主输出使能       

        TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1预装载使能         
       
        TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
       
        TIM_Cmd(TIM1, ENABLE);  //使能TIM1

   
}

回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2017-10-30 00:15:57 | 显示全部楼层
本帖最后由 275891381 于 2017-10-30 00:20 编辑
usb123 发表于 2017-10-29 23:31
还是不对的,,但是我把串口初始化屏蔽之后led一直是亮的,,,调整了定时器的初始化的位置,,,也试过 ...

pwm看了下没问题,你说adc也没问题,就串口看看TIM_SetCompare1(TIM1,adc);里面的adc变没变吧,一点点的看
建议 float adc    4096.0 试试   adc=adcx*242*(3.3/4096.0);//乘以242电压值装换为798代替PWM中的800的临界值

回复

使用道具 举报

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
 楼主| 发表于 2017-10-30 13:35:51 | 显示全部楼层
275891381 发表于 2017-10-30 00:15
pwm看了下没问题,你说adc也没问题,就串口看看TIM_SetCompare1(TIM1,adc);里面的adc变没变吧,一点点的 ...

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "pwm.h"

          
int main(void)
{
        u8 se=1;
        float adc;
        u16 adcx;
        float temp;
        TIM1_PWM_Init(899,0);
        delay_init();                             //延时函数初始化          
//        uart_init(9600);                         //串口初始化为9600
        LED_Init();                                          //初始化与LED连接的硬件接口
        LCD_Init();
        Adc_Init();                                          //ADC初始化       
        POINT_COLOR=RED;                        //设置字体为红色
        POINT_COLOR=BLUE;                        //设置字体为蓝色
        LCD_ShowString(60,130,200,16,16,   "TIM1_VAL:");             
        LCD_ShowString(60,150,200,16,16,"ADC_CH1_VOL:0.000V");       
        while(1)
        {
    adcx=Get_Adc_Average(ADC_Channel_1,10);
                LCD_ShowxNum(156,130,adc,4,16,0);        //显示定时器的值
                temp=(float)adcx*(3.3/4096);
                adc=temp*242;                                                                                        //赋值给定时器模拟一个临界值800
                adcx=temp;                                                                                                //赋值给显示电压
                LCD_ShowxNum(156,150,adcx,1,16,0);//显示电压值
                temp-=adcx;
                temp*=1000;
                LCD_ShowxNum(172,150,temp,3,16,0X80);
////                LED0=!LED0;
//                adc=(float)adcx*242*(3.3/4096);//乘以242电压值装换为798代替PWM中的800的临界值
//                if(se)adc++;
//                else adc--;
//                if(adc>800)se=0;
//                if(adc==0)se=1;
                TIM_SetCompare1(TIM1,adc);
                delay_ms(50);                                                                                            
}       
        }
回复

使用道具 举报

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
 楼主| 发表于 2017-10-30 13:41:44 | 显示全部楼层
adc还是正常工作的,同时液晶显示屏上的电压值都是对的,,但是定时器中的adc显示在液晶上也是变化的,,,但是led就是没有变化,,,pwm中的硬件都是没有问题的,,led一直处于长灭的状态,有人说pwm要加延时,,但是我加了延时LED也还没有反应,,,,示波器看不到变化的
回复

使用道具 举报

15

主题

78

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
409
金钱
409
注册时间
2017-2-21
在线时间
159 小时
 楼主| 发表于 2017-10-30 23:07:47 | 显示全部楼层
自己顶一下
回复

使用道具 举报

5

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2017-11-9
在线时间
9 小时
发表于 2018-1-5 17:22:23 | 显示全部楼层
usb123 发表于 2017-10-30 13:41
adc还是正常工作的,同时液晶显示屏上的电压值都是对的,,但是定时器中的adc显示在液晶上也是变化的,,, ...

楼主我也遇见了同样的问题 想问一下你解决这个问题了吗?
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-22 19:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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