黄文力++元晓
摘要:设计了一种DSP电机控制系统,开发了电机控制可视化界面。建立计算机(上位机)与DSP(下位机)之间的串口通信机制,既而完成对电机运行的复杂控制。着重分析DSP电机驱动程序的结构和相关代码,理清程序设计的思路,供相关研究人员借鉴。
关键词:DSP 直流电机 串口通信 程序设计
中图分类号:TP29 文献标识码:A 文章编号:1007-9416(2014)12-0147-03
Abstract:A kind of DSP motor control system was designed and one motor control visual interface was developed in the paper. The serial communication mechanism between PC of host and DSP of client is established to finish complicated controls of DC motor. Focus on the analysis of structures and related codes of DSP motor drive program is expected to clear program design ideas for relevant science researches.
Key Words:DSP; DC motor; serial communication; program design
目前,利用DSP实现对电动机运行的控制已经成为电机拖动领域流行且成熟的方案。通过DSP可以实施对多类型电机的多形式的运动控制,其中最突出的是对电机宽域且平滑的调速,依据电机与DSP类型的不同,具有诸多实用的方案[1,2]。关于直流电机的调速,理论上可以采取三种方式:改变电枢电压,改变电枢回路电阻,调节励磁磁通,但是由于其它两种方法缺陷明显,目前主要采用改变电枢电压的方法:通过调节DSP输出的PWM波形的占空比,调控输入到电机电枢绕组的电压有效值,既而实现电机速度在较宽的范围内平滑改变[3]。
本文介绍一种基于DSP TMS320F2812的电机控制系统。利用Visual Studio 2010(VS2010)开发电机控制界面,构建了计算机(上位机)与DSP(下位机)之间串口的通信机制,实现对电机运动的控制。着力讨论以DSP为信息交换枢纽的电机驱动程序的设计。
1 控制系统开发
首先,利用集成了.net Framework 4.0的Visual Studio 2010 Windows应用程序开发平台,采用C#语言开发出电机控制界面,用以实现如开停、增/减速、运行状态查询等可视化电机控制功能,如图1所示;其次,构建上位机与下位机之间的串口通信机制,由上位机PC把相应的控制命令传递给下位机DSP,执行电机控制的操作命令;最后,由DSP构成电机控制系统的信息交换枢纽,一方面传递上位机下达的控制命令给电动机,另一方面把电动机运行状态的相关信息反馈给上位机,实现对电机运行状态的实时监控。
该控制系统整体为主从式计算机结构如图2所示,其中PC为上位机,DSP为下位机,两者之间通过串口RS232C协议交换数据。硬件电路连接如图3所示,包括计算机、DSP开发板、仿真器、电机驱动电路板、直流电动机和一些电路连接线。
2 驱动程序设计
CCS3.3是一个集成版的DSP应用程序开发环境,基本涵盖了TI公司所有型号的DSP,与其它版本相比体积稍大,但是代码优化效率较高,调试方便,是目前用的最多的DSP程序开发平台。该电机控制系统利用C语言基于CCS3.3软件平台开发DSP的电机驱动程序,建立电机控制策略实施的纽带。
DSP的驱动程序主要包括:各个外设的初始化函数、主函数与输入中断函数。其中初始化函数完成相应外设的初始化定义,如系统、输入/输出引脚、串行通信接口、事件管理器等;主函数完成相关变量、宏及功能函数的定义,最后形成一个死循环,等待CPU对电机控制命令中断请求的响应,完成对电机运动的调节;中断函数为电机各种控制命令在DSP电机驱动程序中的入口,利用事件响应机制去完成对电机行为的控制。程序整体采用模块化结构,通过调用一个个功能子函数来实现对电机的不同控制,逻辑清晰,便于实现系统功能的扩展。
驱动程序的设计思路如图4所示,首先需要完成DSP及相应功能外设的初始化,即准备好去执行电机的控制命令,然后等待串口的电机控制命令的输入,即形成一个死循环。当串口有电机操作指令输入时,随即发生中断事件,调用中断函数,执行相应的电机操作指令,包括电机的起/停、正/反转、加/减速、状态查询等;在指令完成后,返回死循环进入待命状态,等待下一个电机操作指令,周而复始。
2.1 主函数
首先引用相关的头文件,定义相应的宏、变量与功能函数,然后在主函数中完成相关变量、函数及外设功能的初始化,最后形成一个死循环,等待串口输入对CPU的中断请求,既而完成电机行为的相关控制指令。以下程序代码的省略部分,均为DSP程序的一些固定的功能语句,如中断的使能、外设功能的设定等,为了节省篇幅,不再一一列出,可以参阅文献[4]。
//头文件,宏、变量、功能函数定义等
……;
void main(void)
{
InitSysCtrl(); //初始化系统函数
//CPU中断,PIE寄存器、外设初始化[4]
……;
InitGpio(); //初始化Gpio口
InitEv();endprint
for(i = 0; i < 4; i++) //初始化数组变量
{
Sci_VarRx[i] = 0;//存储电机控制指令
}
i = 0;//初始化
M1_Flag=0; M2_Flag=0;//电机起始为停止状态
//电机控制界面显示波特率初值
sendMsg(SciaRegs.SCIHBAUD);
sendMsg(SciaRegs.SCILBAUD);
//定时器T3和T1计数使能
EvbRegs.T3CON.bit.TENABLE=1;
EvaRegs.T1CON.bit.TENABLE=1;
/*使能SCI中断,开CPU中断,使能全局与实时中断[4]*/
……;
for(;;) { }
}
2.2 功能函数
该电机控制系统实现了控制2台(易于扩展到多台)直流电机的起/停、正/反转、加/减速、状态查询等行为,由于程序采用模块化结构,每一个控制功能都对应特定的功能函数,且每一个功能函数的结构类似,皆为先判断指令对象,然后再依据不同的指令代码执行对应的动作。因此在此仅列出加速功能函数的代码,其中省略部分为对两台以上电机的相同操作,不再重复。其它功能函数以此类推。
void M_Inc(unsigned int num) //加速函数
{
if((num==1)&(M1_Flag!=0)) //电机M1
{
//占空比增加2%
EvaRegs.CMPR1=EvaRegs.CMPR1+375;
if(EvaRegs.CMPR1>=0x41EB)
{
//最大占空比值为90%
EvaRegs.CMPR1=0x41EB;
}
}
else if((num==2)&(M2_Flag!=0)) //其它电机
{
……;//相同控制代码
}
}
2.3 系统初始化函数
在系统初始化函数中,主要完成关闭看门狗电路、初始化PLL锁相环模块、设定高/低速时钟预定标器频率等,也就是说确定系统输出PWM波的频率,相关内容可以参阅文献[4]。以下主要列出该工程中用到的外设的初始化设置代码:
void InitSysCtrl(void)
{
//关门狗电路、PLL模块、高低速时钟初始化[4]
……;
// EVA、EVB、SCIA模块时钟使能
SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;
SysCtrlRegs.PCLKCR.bit.EVBENCLK=1;
SysCtrlRegs.PCLKCR.bit.SCIENCLKA=1;
}
2.4 I/O口初始化函数
在输入输出引脚初始化函数中,主要完成工程用到引脚的功能与方向的设定,如引脚为功能引脚还是通用的输入输出引脚、是输入还是输出引脚等。其代码如下:
void InitGpio(void)
{
EALLOW;//使能寄存器访问
//设置串口的的发送和接收引脚为功能引脚 GpioMuxRegs.GPFMUX.bit.SCITXDA_GPIOF4=1;
GpioMuxRegs.GPFMUX.bit.SCIRXDA_GPIOF5=1;
//设置GPIOA0、A1等引脚为功能引脚
GpioMuxRegs.GPAMUX.bit.PWM1_GPIOA0=1;
GpioMuxRegs.GPAMUX.bit.PWM2_GPIOA1=1;
GpioMuxRegs.GPBMUX.bit.PWM7_GPIOB0=1;
GpioMuxRegs.GPBMUX.bit.PWM8_GPIOB1=1;
EDIS;//关闭寄存器访问
}
2.5 串口初始化函数
该工程利用串口的SCIA模块,其初始化包括设置1位停止位、8位数据位,禁止奇偶校验、禁止数据回送测试,使能串口的发送和接收数据功能,使能中断方式发送和接收数据,设置波特率等,最后重启SCI保存设置,完成初始化。主要代码如下所示:
void InitSci(void)
{
//停止位、数据位、极性校验等设置[4]
……;
SciaRegs.SCIHBAUD=0x00;
SciaRegs.SCILBAUD=0xE7;//波特率为9600
//发送和接收数据使能,中断使能。重启SCI[4]
……;
}
2.6 事件管理器初始化函数
在事件管理器初始化函数中,分别设定事件管理器EVA的定时器T1与EVB的定时器T3工作于连续增/减计数模式,定时器的时钟频率为37.5MHz,暂时禁止T1计数,使能T1内部时钟,设定T1的周期值为0x493E=18750(即相应的PWM波频率为1kHz),设定T1计数器初始值为0;使能比较单元的比较操作,全比较器输出,相应引脚PWM1~PWM6由比较逻辑驱动;立即重载寄存器保存设置;设定PWM1引脚为低电平有效,PWM2引脚为高电平有效,初始占空比值为0x1250(25%);设定死区定时器周期为10 s,定时器预定标因子为(37.5 MHz)/8≈4.69 MHz,相应的死区时间约为10/(4.69×106)≈2.13μs。对于EVB的操作完全类似,代码如下所示:endprint
void InitEv(void)
{
/*EVA模块。设定T1工作模式、时钟频率、周期值,T1计数器初值。比较单元1使能及相关引脚设定[4]。*/
……;
/*PWM1、PWM2引脚初始低电平,保证电机初始停止状态。*/
EvaRegs.ACTR.bit.CMP1ACT=0;
EvaRegs.ACTR.bit.CMP2ACT=0;
EvaRegs.CMPR1=0x1250;//占空比初始值25%
EvaRegs.DBTCONA.bit.DBT=10;//死区定时器周期
//死区定时器1使能
EvaRegs.DBTCONA.bit.EDBT1=1;
//死区定时器预定标因子
EvaRegs.DBTCONA.bit.EDBT1=3;
/*EVB模块。与EVA模块完全类似,只需把定时器T1换为T3,引脚PWM1与PWM2改为PWM7与PWM8,死区定时器控制寄存器DBTCONA改为DBTCONB即可。*/
……;
}
2.7 中断函数
DSP采用中断方式响应串口数据的读取,所有对电机的控制操作皆在中断函数里完成,不同的控制命令调用不同的功能子函数。相应程序的代码结构如下:
/*只要串口输入缓冲区有数据需要接收,CPU就//会执行此中断函数。*/
interrupt void SCIRXINTA_ISR(void)
{
//利用数组保存控制命令数据
Sci_VarRx[i] = SciaRegs.SCIRXBUF.all;
i++;//主函数中已定义
//根据命令代码格式,01为电机正反转识别代码
if(Sci_VarRx[0]==0x0001)
{
Rec_Manage(Sci_VarRx[0]);//电机正/反转
}
//02为电机停止识别代码
else if(Sci_VarRx[0]==0x0002)
{
……;//电机停止
}
/*03、04分别对应电机加/减速、占空比设定、运行状态查询等识别代码。*/
……;
if(i==4){ i=0; }
//使得同组其他中断能够得到响应
PieCtrl.PIEACK.bit.ACK9=1;
EINT; //开全局中断
}
3 结语
基于DSP所设计的电机运动控制器目前应用广泛,方案众多。本文介绍了一种可以实现对多台直流电机实施调节的DSP电机控制系统,利用VS2010开发了电机控制界面,并且建立了上、下位机之间的串口通信机制,成功实现了对多台(两台)电机运行的调制和状态的实时监控。另外,深入分析了基于C语言的DSP电机驱动程序的结构和有关代码,力争建立DSP相关电机驱动程序的模块化结构与模式化设计的思维。
参考文献
[1]任忠,王自强.基于DSP控制的无刷直流电机调速系统的设计[J].电力电子,2008,30(3):30-32.
[2]李宏,徐德民,焦振宏.基于DSP的大功率永磁直流电机调速系统设计[J].电力电子技术,2006,40(5):29-31.
[3]李方圆,李晓.基于dsp直流电机调速系统的设计[J].数字技术与应用,2012,(12):128-130.
[4]顾卫刚.手把手教你学DSP——基于TMS320X281x[M].北京:北京航空航天大学出版社,2011.endprint