adc采样控制pwm的问题

2019-07-24 17:29发布

我现在需要的功能是:在某一时间后,采样电压,然后超过目标值就驱动电机调压,到了目标值就停止,如果小于目标值就反向调压。
我用的TI的TIVA系列单片机,ADC采样和PWM输出我都可以实现,但是联动起来就有些问题。
TI的函数里都是unsigned int32 定义的变量,我用采样值减去目标值得到一个差值,利用差值的正负、大小,判断是否需要调压,因为有三相,所以for循环三次
遇到了几个问题
1.无法反转和停止,差值恒大于128,我想应该是无符号数不会小于0的错误,但是我如果count定义成有符号的,TI的函数里ADC0_Value是个无符号数,貌似没法相减得到有符号数。可以吗?
2.恒为高电平的PWM总是参杂着很短时间的低电平,我想是不是采样值在临界值左右时刻变化,导致的pwm时开时关。但是我调节电压,低电平一直存在。鉴于第一个问题,无法实现电压变化控制PWM的通断,低电平一直存在倒也不能说明什么。
3.不知道要实现这个功能,该用什么方式避免采样波动引起的边界问题?
for(a=0;a<3;a++)
        {
                count=ADC0_Value[a]-goal;
                PWM_CTRL(count,a);
        }//把三相电压ADC0、ADC1、ADC2和目标值的差值计算出来
        a=0;


void PWM_CTRL(uint32_t count,uint8_t a)//控制三相电机的启动、停止、正反转
{
        if(a==0)
        {
                if(count>=128)
                {S0=4800;S1=0; PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), false);}//不转
                else
                {S0=0;S1=4800; PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), true);}//反转
        }
        if(a==1)
        {
                if(count>=128)
                {S2=4800;S3=0; PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), false);}//不转
                else
                {S2=0;S3=4800; PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), true);}//反转
        }
        if(a==2)
        {
                if(count>=128)
                {S4=4800;S5=0; PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), false);}//不转
                else
                {S4=0;S5=4800; PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), true);}//反转
        }
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
djz1992
1楼-- · 2019-07-26 00:24
//模数转换器实验程序解析
//头文件
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "grlib/grlib.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/pwm.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/interrupt.h"

uint32_t S0=0,S1=0,S2=0,S3=0,S4=0,S5=0;
uint32_t ADC0_Value[6],Data[6]={0},goal[3];
uint32_t count;

void PWM_INIT(void)
{
        //使能M0PWM模块
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
        //使能M0PWM0和M0PWM1输出所在GPIOB和GPIOG
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
       
        //配置相应GPIO为PWM功能
        GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_4|GPIO_PIN_5);
        GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_5|GPIO_PIN_4);//不同:PG4、PG5
        // PWM时钟配置:不分频
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
        //配置M0PWM发生器:加减计数
        PWMGenConfigure(PWM0_BASE,PWM_GEN_0,PWM_GEN_MODE_UP_DOWN| PWM_GEN_MODE_NO_SYNC);
        //设置M0PWM发生器的周期,时钟频率/PWM分频数/n,周期=80M/1/6000=
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 6000);
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 6000);
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 6000);
        //设置M0PWM0/M0PWM1输出的脉冲宽度
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, S0);//此处S0+S1<=6000
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, S1);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, S2);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3, S3);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_5, S4);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, S5);
        //使能M0PWM0和M0PWM1的输出
        //PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), true);
        //PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), true);
        //PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), true);
        //使能M0PWM发生器生成模块0
        PWMGenEnable(PWM0_BASE, PWM_GEN_0);
        PWMGenEnable(PWM0_BASE, PWM_GEN_1);
        PWMGenEnable(PWM0_BASE, PWM_GEN_2);
}

void PWM_CTRL(uint32_t count,uint8_t a)//控制三相电机的启动、停止、正反转
{
        if(a==0)
        {
                if(count>=128)
                {S0=4800;S1=0;PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), false);}//不转
                else
                {S0=0;S1=4800;PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT), true);}//反转
        }
        if(a==1)
        {
                if(count>=128)
                {S2=4800;S3=0;PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), false);}//不转
                else
                {S2=0;S3=4800;PWMOutputState(PWM0_BASE, (PWM_OUT_2_BIT |PWM_OUT_3_BIT), true);}//反转
        }
        if(a==2)
        {
                if(count>=128)
                {S4=4800;S5=0;PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), true);}//正转
                else if(0<count<128)
                {PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), false);}//不转
                else
                {S4=0;S5=4800;PWMOutputState(PWM0_BASE, (PWM_OUT_4_BIT |PWM_OUT_5_BIT), true);}//反转
        }
}

void ADC_INIT(void)
{
        //初始化ADC0/PE3
        //SysCtlADCSpeedSet(SYSCTL_ADCSPEED_500KSPS);//设置采样速度,默认1MHZ
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

        //设置ADC参考电压为外部3V,TM4C123GH6PM只能使用内部参考电压,3.3V
        //ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);//若ADC_REF_INT,则指使用内部3V参考电压
        //配置ADC采集序列
        ADCSequenceConfigure(ADC0_BASE, 0,ADC_TRIGGER_PROCESSOR, 0);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 );//PE3
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1 );//PE2
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH2 );//PE1
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH3 );//PE0
        ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH4 );//PD3
        ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH5 );//PD2
        ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH6 | ADC_CTL_IE |ADC_CTL_END);//PD1
        //ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH7 | ADC_CTL_IE |ADC_CTL_END);//PD0未使用

        //使能ADC采集序列
        ADCSequenceEnable(ADC0_BASE, 0);
        //IntEnable(INT_ADC0SS0);
        IntMasterEnable();
        ADCIntEnable(ADC0_BASE, 0);
        //ADCIntEnableEx(ADC0_BASE,ADC_INT_DMA_SS0);//中断触发设置
        ADCIntClear(ADC0_BASE, 0);
}

int main(void)
{
        uint8_t a=0,b=0;
        //使能FPU
        FPUEnable();
        FPULazyStackingEnable();
        //设置系统时钟为50MHz (400/2/4=50)
        SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL |SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
        UATR_INIT();
        ADC_INIT();
        PWM_INIT();
while(1)
{
        //触发采集
        ADCProcessorTrigger(ADC0_BASE, 0);
        //等待采集结束
        while(!ADCIntStatus(ADC0_BASE, 0, false));
        //获取采集结果
        ADCSequenceDataGet(ADC0_BASE, 0, ADC0_Value);
                //延时
        //SysCtlDelay(SysCtlClockGet() / 12);
        PWM_CTRL(count,a);
}
}
djz1992
2楼-- · 2019-07-26 06:14
 精彩回答 2  元偷偷看……
djz1992
3楼-- · 2019-07-26 07:16
dirtwillfly 发表于 2015-12-29 13:00
有可能adc配置不有问题,方便的话建议把代码传上来

代码在上面
dirtwillfly
4楼-- · 2019-07-26 07:44
本帖最后由 dirtwillfly 于 2015-12-29 13:50 编辑

@xyz549040622 帮看看这段程序,我没看出有明显问题
xyz549040622
5楼-- · 2019-07-26 08:19
现在的问题是你前端采集到的电压就不准,所以后级出现问题就情有可原了。我晚上拿launchpad试试,AD误差真有这么大?我看看
pmp
6楼-- · 2019-07-26 09:02
怎么还有表情,是不是去掉

一周热门 更多>