主题中讨论的其他部件:MSP-EXP430G2
工具/软件:Code Composer Studio
我正在经历一个有趣的挑战。 我的代码在EXP430G2仿真器上的工作方式与我想要的完全相同,但在将其移动到部件时,其行为会有所不同。
电路概述:
我在两个定时器上分别控制两个电机。 我感应到一个零交叉点,然后在三端双向可控硅开关元件的闸门上用200US脉冲进行相位控制。 我具有相位控制和光隔离零交叉检测。 一次一个,它们工作正常,但当我打开第二个电机时,另一个计时器中断似乎受到影响。 例如,一旦电机完全加速,我就会禁用计时器中断,而只是将输出引脚设置为高电平,这样当我打开另一个电机时,它就不会执行任何操作,但当我打开第二个电机时,它似乎会重新启用中断并开始脉冲 再次导致电机速度波动。 同样,在仿真器上也可以正常工作。
我正在调查电路,以确保滤波和噪音不是问题,因为这是我的头先到的地方,但当用跳线将仿真器板连接到我的电机控制板时,它工作正常。
所以我想看看有没有人对此有什么想法。 也许我的ISR中有太多代码,所以有人想将大部分代码移到主循环,因为我在中断中执行大部分操作。
下面是我的代码:
#include <MSP4S.h>/**
* main.c
*/
volatile int Phase标志= 0x00; //相移标志位0 =低,等待触发光标1/*
*位0:准备触发电机1上的相位控制
*位1:电机1上的脉冲超时
*位2: 准备触发电机2的相位控制
*位3:电机2的脉冲超时
*/
volatile unsigned int RamK_1= 0x00; //Ramp 1计数器
volatile unsigned int RamP_2 = 0x00; //渐变2计数
器#define Max_count 7000 每个计数是//2我们???? 最小马达输出
#define half_power 3500
#define ramper_rate 10
#define pulse_width 200 //将门触发器的脉冲宽度设置为200 us
#define off_detect 1万 //设置应长于零交叉期的计数器。
int main (void){
/***定义***/
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
DCOCTL = 0; //选择最低DCOx和MODx
BCSCTL1 = CALC1_8MHZ; //设置范围
DCOCTL = CALDCO_8MHZ; //设置DCO步进+调制
TA0CTL = tassel_2 + MC_1 + ID_3;/* tassel_2:使用SMCLK MC_1:upcount ID_3:除以8*/
TA1CTL = tassel_2 + MC_1 + ID_3;/* tassel_2:使用SMCLK MC_1:upcount ID_3:除以8*/
/*** GPIO设置***//*
WFP 1.1 (输入):电机2零交叉检测
* WFP 1.3 (输出):电机2相控制
* WFP 1.4 (输出):LED输出
* WFP 1.5 (输入):选择器开关输入
* WFP 1.6 (输出):电机1相控制
* WFP 1.7 (输入):电机1零交叉检测
* _________________________
P1OUT &= 0x00; //关闭所有设备
P1DIR &= 0x00;
P2OUT &= 0x00; //关闭所有设备
P2DIR &= 0x00;
P3OUT &= 0x00; //关闭所有设备
P3DIR &= 0x00;
P1DIR || BIT3 + BIT4 + BIT6;// WFP 1.3 ,WFP 1.4 ,WFP 1.6 引脚输出其余为输入
//零交叉中断设置
P1IE || BIT1 + BIT7 +BIT5; //已启用WFP 1.1 和WFP 1.7 中断
P1IES |= BIT1; // WFP 1.1 高/低EDGE |_
P1IES |= BIT7; // WFP 1.1 Hi-Lo edge |_
P1IFG &=~BIT1; //已清除WFP 1.1 IFG
P1IFG &=~BIT7; //已清除WFP 1.7 IFG
/*
需要确定选择器开关的初始状态,因为我们将切换中断的边缘选择
*假定高功率为高功率,低功率
为低功率*/
IF ((P1IN和BIT5)) //检查选择器上的开关是否处于高位
{
P1IES |= BIT5; //WFP 1.5 高/低EDGE
}
否则
{
P1IES &=~BIT5; //WFP 1.5 LO/Hi EDGE
}
P1IFG &=~BIT5; // WFP 1.5 IFG已清除
_BIS_SR(GIE); //启用中断
// Ramp/1 =0; //
将RamP_1设置为零,同时(1) //永远循环,我们用中断完成所有工作!
{}//
电机1的计时器A1中断服务例程
#pragma vector=Timer1_A0_vector
__interrupt void Timer1_A0 (void){
IF((Phase_flags & BIT1)!=0) //如果我们到达这里,则开关已关闭,并且没有收到零交叉来重置计时器
{
phone_flags &=~BIT1; //清除BIT3相位标记以指定为斜坡准备就绪
RamK_1 = 0x00;
TA1R = 0x00;
TA1CCR0 =最大计数;
phone_flags &=~BIT0; //确保触发器标志已重置
P1OUT &=~BIT6; //确保WFP 1.6 为低
TA1CCTL0 &=~CCIE; //禁用Timer_A1中断
}
否则
{
IF (Ramp/1 < Max_count)
{
IF((Phase_flags & BIT0)!=0) //测试标记位2是否为高,以查看我们是否设置为触发相位脉冲
{
P1OUT || BIT6; //将WFP 1.6 设置为高
TA1R = 0;
TA1CCR0 =脉冲宽度; //负载脉冲宽度计数器
phone_flags &=~BIT0; //清除相位标记零设置为延迟
TA1CCTL0 = CCIE; //启用计时器A1中断-我们是否需要此功能?
}
否则 //已完成相位脉冲,现在只需清除输出等
{
P1OUT &=~BIT6; //清除WFP 1.6
phue_flags |= BIT1; //将相位标记设置为高,以检查是否没有零交叉
TA1R = 0;
TA1CCR0 = OFF_DETECT; //负载关闭检测值
TA1CCTL0 = CCIE; //启用计时器A1中断
// TA0CCTL0 &=~CCIE; //禁用Timer_A中断
}
}
否则
{
P1OUT || BIT6; //将WFP 1.3 HIGH MOTORI 1设置为FULL ON
phue_flags |= BIT1; //将相位标记设置为高斜率完成//将相位标记设置为高,以检查是否没有零交叉
TA1CCR0 = OFF_DETECT; //负载脉冲宽度计数器
TA1CCTL0 = CCIE; //启用计时器A1中断
// P1IE &=~BIT1; //禁用电机2零交叉中断,因为我们已经完成了ramp....no,了解如何重新启用它...等待不要禁用
}
}
TA1CCTL0 &=~CCIFG; //清除中断标志-应该自动清除,但可能需要?
}
//电机2的计时器A0中断服务例程
#pragma vector=TIMER0_A0_vector
__interrupt void Timer0_A0 (void)
{
IF((Phase_flags & BIT3)!=0) //如果我们到达这里,则开关已关闭,并且没有收到零交叉来重置计时器
{
phone_flags &=~BIT3; //清除BIT3相位标记以指定为斜坡准备就绪
RamK_2 = 0x00;
TA0R = 0x00;
TA0CCR0 =最大计数;
phone_flags &=~BIT2; //确保触发器标志已重置
P1OUT &=~BIT3; //确保WFP 1.6 为低
TA0CCTL0 &=~CCIE; //禁用Timer_A中断
}
其它
{
IF (RamP_2 < Max_count)
{
IF((Phase_flags & BIT2)!=0) //测试标记位2是否为高,以查看我们是否设置为触发相位脉冲
{
P1OUT || BIT3; //将WFP 1.3 设置为高
TA0R = 0;
TA0CCR0 =脉冲宽度; //负载脉冲宽度计数器
phone_flags &=~BIT2; //清除相位标记零设置为延迟
TA0CCTL0 = CCIE; //启用计时器A0中断-我们是否需要此功能?
}
否则 //已完成相位脉冲,现在只需清除输出等
{
P1OUT &=~BIT3; //清除WFP 1.3
phue_flags |= BIT3; //将相位标记设置为高,以检查是否没有零交叉
TA0R = 0;
TA0CCR0 = OFF_DETECT; //负载关闭检测值
TA0CCTL0 = CCIE; //启用计时器A0中断
// TA0CCTL0 &=~CCIE; //禁用Timer_A中断
}
}
否则
{
P1OUT || BIT3; //设置为WFP 1.3 HIGH MOTOR2 FULL ON
phue_flags |= BIT3; //将相位标记设置为高斜率完成//将相位标记设置为高,以检查是否没有零交叉
TA0CCR0 = OFF_DETECT; //负载脉冲宽度计数器
TA0CCTL0 = CCIE; //启用计时器A0中断
// P1IE &=~BIT1; //禁用电机2零交叉中断,因为我们已经完成了ramp....no,了解如何重新启用它...等待不要禁用
}
}
TA0CCTL0 &=~CCIFG; //清除中断标志-应该自动清除,但可能需要?
}
//端口1中断服务例程****将只测试零交叉#pragma
vector=Port1_vector
__interrupt void Port_1 (void)
{/*
if((P1IFG & BIT3)!=0) //检查开关复位
{
RamK_1 = 0x00;
TA0R = 0x00;
TA0CCR0 =最大计数;
P1IFG &=~BIT3; //已清除WFP 1.3 IFG
TA0CCTL0 = CCIE;// TA0CCTL0寄存器:如果您计划使用计时器,则需要设置的第一个寄存器是CCTL0。 它是一个16位寄存器,此寄存器的设置影响我们使用寄存器的方式。 出于我们的目的,我们只告诉它使用启用中断
phue_flags = 0x00; //重置相位标志
P1OUT &=~BIT0; //确保WFP 1.0 输出为低
}
// P1OUT |= BIT6; //切换WFP 1.6 高*/
如果(P1IFG和BIT5)!= 0) //电源开关选择器中断
{
如果(P1IN和BIT5)!= 0) //检查选择器上的开关"高",这样做只是为了确保我们每次都将中断边缘设置为正确的方式
{
P1IES |= BIT5; //WFP 1.5 高/低边缘
//设置为Max_count
}
否则
{
P1IES &=~BIT5; //WFP 1.5 LO/Hi EDGE
//设置为half_power ....只需检查开关状态并停止半路上升
//需要处理马达已满功率的情况。 我们可以重置所有的定时器和斜坡寄存器.....
//如果在打开此开关后立即从高功率切换到低功率,该怎么办??? 我认为它会立即达到一半的功率
如果((Phase_flags & BIT1)!=0) //检查我们是否完成了斜坡。
{
RAK_1 =半功率; //将斜坡1重置为半功率
}
IF((Phase_flags & BIT3)!=0) //检查我们是否完成了斜坡。
{
RAK_2 =半功率; //将斜坡2重置为半功率
}
//我们是否需要更改阶段标志?
//
}
P1IFG &=~BIT5; //已清除WFP 1.5 IFG
}
如果(P1IFG和BIT7)!= 0) //检查电机1上的零交叉
{
IF (Ramp/1 < Max_count) //初始零交叉触发最大计数- RAM_RATE,但我们是否在乎? 可能想要设置最小值或其他内容
{
IF ((P1IN和BIT5)) //不确定这是否是正确的语法检查我们是否处于完全的状态
{
RAK_1+= RAK_RATE;
}
否则,如果(Ramp/1 < Half_power)
{
RAK_1 += RAM_RATE; //设置向右移动相位移的速度
}
P1OUT &=~BIT6; //确保WFP 1.6 低,这可能是多余的
// P1OUT |= BIT0; //将WFP 1.0 设置为高
phue_flags |= BIT0; //将相位标记设为高,我们正在等待触发电机2脉冲
TA1R = 0; //重置计数器A1
TA1CCR0 = Max_count - RamP_1; //计数到新的最大计数
TA1CCTL0 = CCIE; //启用计时器A1中断将需要查看这是否是对两个计时器执行此操作的正确方式。
phone_flags &=~BIT1; //清除斜坡超时标志
}
Else if ((Phase_flags & BIT1)!= 0)
{
TA1R = 0x00; //当我们完全处于斜坡状态并正在等待检测到关闭时,重置计时器
}
P1IFG &=~BIT7; //WFP 1.7 IFG已清除
}
如果(P1IFG和BIT1)!= 0) //检查电机2上的零交叉
{
IF (RamP_2 < Max_count) //初始零交叉触发最大计数- RAM_RATE,但我们是否在乎? 可能想要设置最小值或其他内容
{
IF ((P1IN和BIT5)) //不确定这是否是正确的语法检查我们是否处于完全的状态
{
RAK_2+= RAK_RATE;
}
否则,如果(RamP_2 < Half_POWER)
{
RAK_2 += RAK_RATE; //设置向右移动相位移的速度
}
P1OUT &=~BIT3; //确保WFP 1.3 低,这可能是多余的
// P1OUT |= BIT0; //将WFP 1.0 设置为高
phue_flags |= BIT2; //将相位标记设为高,我们正在等待触发电机2脉冲
TA0R = 0; //重置计数器A0
TA0CCR0 =最大计数- RamP_2; //计数到新的最大计数
TA0CCTL0 = CCIE; //启用计时器A0中断将需要查看这是否是对两个计时器执行此操作的正确方式。
phone_flags &=~BIT3; //清除斜坡超时标志
}
Else if ((Phase_flags & BIT3)!= 0)
{
TA0R = 0x00; //当我们完全处于斜坡状态并正在等待检测到关闭时,重置计时器
}
P1IFG &=~BIT1; //WFP 1.1 IFG已清除
}
}
提前感谢,我会一直插上电源,但任何帮助都值得赞赏!