我现在需要的功能是:在某一时间后,采样电压,然后超过目标值就驱动电机调压,到了目标值就停止,如果小于目标值就反向调压。
我用的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);}//反转
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
//头文件
#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);
}
}
代码在上面
@xyz549040622 帮看看这段程序,我没看出有明显问题
一周热门 更多>