舵机简介及其单片机控制方法

舵机简介及其单片机控制方法(转贴)

由于rocky 于Sun May 18, 2003 12:59 pm 向本人提出希望了解有关舵机的知识,现将本人在航空模型运动中和机器人制作中积累的一点点经验写出来,奉献给大家,希望本文能起到抛砖引玉的作用。但由于时间仓促,难免有不正确的地方,热情欢迎大家批评指教。

1、概述

舵机最早出现在航模运动中。在航空模型中,飞行机的飞行姿态是通过调节发动机和各个控制舵面来实现的。举个简单的四通飞机来说,飞机上有以下几个地方需要控制:

1. 发动机进气量,来控制发动机的拉力(或推力);

2. 副翼舵面(安装在飞机机翼后缘),用来控制飞机的横滚运动;

3. 水平尾舵面,用来控制飞机的俯仰角;

4. 垂直尾舵面,用来控制飞机的偏航角;

遥控器有四个通道,分别对应四个舵机,而舵机又通过连杆等传动元件带动舵面的转动,从而改变飞机的运动状态。舵机因此得名:控制舵面的伺服电机。

不仅在航模飞机中,在其他的模型运动中都可以看到它的应用:船模上用来控制尾舵,车模中用来转向等等。由此可见,凡是需要操作性动作时都可以用舵机来实现。

2、结构和控制

一般来讲,舵机主要由以下几个部分组成, 舵盘、减速齿轮组、位置反馈电位计5k 、直流电机、控制电路板等。

工作原理:控制电路板接受来自信号线的控制信号(具体信号待会再讲),控制电机转动,电机带动一系列齿轮组,减速后传动至输出舵盘。舵机的输出轴和位置反馈电位计是相连的,舵盘转动的同时,带动位置反馈电位计,电位计将输出一个电压信号到控制电路板,进行反馈,然后控制电路板根据所在位置决定电机的转动方向和速度,从而达到目标停止。

舵机的基本结构是这样,但实现起来有很多种。例如电机就有有刷和无刷之分,齿轮有塑料和金属之分,输出轴有滑动和滚动之分,壳体有塑料和铝合金之分,速度有快速和慢速之分,体积有大中小三种之分等等,组合不同,价格也千差万别。例如,其中小舵机一般称作微舵,同种材料的条件下是中型的一倍多,金属齿轮是塑料齿轮的一倍多。需要根据需要选用不同类型。

舵机的输入线共有三条,红色中间,是电源线,一边黑色的是地线,这辆根线给舵机提供最基本的能源保证,主要是电机的转动消耗。电源有两种规格,一是4.8V ,一是6.0V ,分别对应不同的转矩标准,即输出力矩不同,6.0V 对应的要大一些,具体看应用条件;另外一根线是控制信号线,Futaba 的一般为白色,JR 的一般为桔黄色。另外要注意一点,SANWA 的某些型号的舵机引线电源线在边上而不是中间,需要辨认。但记住红色为电源,黑色为地线,一般不会搞错。 舵机的控制信号为周期是20ms 的脉宽调制(PWM )信号,其中脉冲宽度从0.5ms-2.5ms ,相对应舵盘的位置为0-180度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。舵机内部有一个基准电路,产生周期20ms ,宽度1.5ms 的基准信号,有一个比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机

的转动信号。由此可见,舵机是一种位置伺服的驱动器,转动范围不能超过180度,适用于那些需要角度不断变化并可以保持的驱动当中。比方说机器人的关节、飞机的舵面等。

常见的舵机厂家有:日本的Futaba 、JR 、SANWA 等,国产的有北京的新幻想、吉林的振华等。现举Futaba S3003来介绍相关参数,以供大家设计时选用。之所以用3003是因为这个型号是市场上最常见的,也是价格相对较便宜的一种(以下数据摘自Futaba 产品手册)。

尺 寸(Dimensions): 40.4×19.8×36.0 mm

重 量(Weight): 37.2 g

工作速度(Operating speed):0.23 sec/60°(4.8V)

0.19 sec/60°(6.0V)

输出力矩(Output torque): 3.2 kg.cm (4.8V)

4.1 kg.cm (6.0V)

由此可见,舵机具有以下一些特点:

>体积紧凑,便于安装;

>输出力矩大,稳定性好;

>控制简单,便于和数字系统接口;

正是因为舵机有很多优点,所以,现在不仅仅应用在航模运动中,已经扩展到各种机电产品中来,在机器人控制中应用也越来越广泛。

3、用单片机来控制

正是舵机的控制信号是一个脉宽调制信号,所以很方便和数字系统进行接口。只要能产生标准的控制信号的数字设备都可以用来控制舵机,比方PLC 、单片机等。这里介绍利用51系列单片机产生舵机的控制信号来进行控制的方法,编程语言为C51。之所以介绍这种方法只是因为笔者用2051实现过,本着负责的态度,所以敢在这里写出来。程序用的是我的四足步行机器人,有删改。单片机并不是控制舵机的最好的方法,希望在此能起到抛砖引玉的作用。

2051有两个16位的内部计数器,我们就用它来产生周期20 ms 的脉冲信号,根据需要,改变输出脉宽。基本思路如下(请对照下面的程序):

我用的晶振频率为12M ,2051一个时钟周期为12个晶振周期,正好是1/1000 ms,计数器每隔1/1000 ms 计一次数。以计数器1为例,先设定脉宽的初始值,程序中初始为1.5ms ,在for 循环中可以随时通过改变a 值来改变,然后设定计数器计数初始值为a ,并置输出p12为高位。当计数结束时,触发计数器溢出中断函数,就是void timer0(void) interrupt 1 using1 ,在子函数中,改变输出p12为反相(此时跳为低位),在用20000(代表20ms 周期)减去高位用的时间a ,就是本周期中低位的时间,c=20000-a,并设定此时的计数器初值为c ,直到定时器再次产生溢出中断,重复上一过程。

# include

#define uchar unsigned char

#define uint unsigned int

uint a,b,c,d;

sbit p12=P1^2;

sbit p13=p1^3;

sbit p37=P3^7;

void timer0(void) interrupt 1 using 1

{ p12=!p12;

c=20000-c;

TH0=-(c/256); TL0=-(c%256);

if(c>=500&&c

else c=20000-a;

}

void timer1(void) interrupt 3 using 1

{p13=!p13;

d=20000-d;

TH1=-(d/256); TL1=-(d%256);

if(d>=500&&d

else d=20000-b;

}

void main(void)

{TMOD=0x11;

p12=1;

p13=1;

a=1500;

b=1500;

c=a;d=b;

TH0=-(a/256); TL0=-(a%256);

TH1=-(b/256); TL1=-(b%256);

EA=1;

ET0=1; TR0=1;EX0=1;EX1=1;

ET1=1; TR1=1;

PX0=0;PX1=0;PT1=1;PT0=1;

for(;;)

{

}

}

因为在脉冲信号的输出是靠定时器的溢出中断函数来处理,时间很短,因此在精度要求不高的场合可以忽略。因此如果忽略中断时间,从另一个角度来讲就是主程序和脉冲输出是并行的,因此,只需要在主程序中按你的要求改变a 值,例如让a 从500变化到2500,就可以让舵机从0度变化到180度。另外要记住一点,舵机的转动需要时间的,因此,程序中a 值的变化不能太快,不然舵机跟不上程序。根据需要,选择合适的延时,用一个a 递增循环,可以让舵机很流畅的转动,而不会产生像步进电机一样的脉动。这些还需要实践中具体体会。

舵机的速度决定于你给它的信号脉宽的变化速度。举个例子,t =0试,脉宽为0.5ms ,t =1s 时,脉宽为1.0ms ,那么,舵机就会从0.5ms 对应的位置转到1.0ms 对应的位置,那么转动速度如何呢?一般来讲,3003的最大转动速度在4.8V 时为0.23s/60度,也就是说,如果你要求的速度比这个快的话,舵机就反应不过来了;如果要求速度比这个慢,可以将脉宽变化值线性到你要求的时间内,做一个循环,一点一点的增加脉宽值,就可以控制舵机的速度了。当然,具体这一点一点到底是多少,就需要做试验了,不然的话,不合适的话,舵机就会向步进电机一样一跳一跳的转动了,尝试改变这“一点”,使你的舵机运动更平滑。还有一点很重要,就是舵机在每一次脉宽值改变的时候总会有一个转速由零增加再减速为零的过程,这就是舵机会产生像步进电机一样运动的原因。

请问一下,舵机转动速度是如何控制的?

这个比较简单吧,驱动普通舵机只要一个口线直接接舵机信号线就行了。软件上可以用“分时复用比较法(我自己想的名字)”来做。简单来说就是:设置一个定时器让它按舵机最小分辨率的周期来溢出,溢出后让某个寄存器从1开始到最大值不断重复,这个最大值不一定是0FFH ,可以根据自己的需要设。每次定时器溢出的时候进入中断,寄存器加1后和每个舵机的预设值进行比较,判断是否改变高电平的宽度。这个比较一般只能处理不多的几路(要保证在下个定时器中断前完成比较)。因为舵机信号的脉宽最大只有2.5MS ,在处理这几路舵机的时候把其它的舵机信号都拉低。当处理完这几路的时候,也就是定时器从1到最大值完成一次后,(这时候前面处理过的几路应该都是低电平了)把下次需要处理的几路都拉高。然后再比较这几路该什么时候拉低,依次循环,直到总时间达到20MS ,再回过头来处理刚开始处理的几路。

一、电路原理

电路如图1所示,由检测传感器、单片机电路和数码显示电路等组成。 检测传感器由永久磁铁和开关型霍尔集成电路UGN3020. 组成。UGN3020由霍尔元件、放大器、整形电路及集电极开路输出电路等组成,其功能是把磁信号转换成电信号,图2a 是其内部框图。霍尔元件H 为磁敏元件,当垂直于霍尔元件的磁场强度随之变化时,其两端的电压就会发生变化,经放大和整形后,即可在

③脚输出脉冲电信号。其工作特性如图2b 所示。由于有一定的磁滞效应,可保证开关无抖动。B 叩为工作点“开”的磁场强度,Brp 为释放点“关”的磁场强度。永久磁铁固定在车轮的辐条上,UGN3020固定在车轮的叉架上。检测传感器的工作原理如下:车轮每转一周,磁铁经过UGN3020一次,其③脚就输出一个脉冲信号。UGN3020输出的脉冲信号作为单片机AT89C2051的外中断信号,从P3.2口输人。单片机测量脉冲信号的个数和脉冲周期。根据脉冲信号的个数计算出里程,根据脉冲信号的周期计算出速度并送数码管显示。S1用来进行里程和速度显示的切换,在初始状态下显示的是速度。

数码管DS1--DS3,VT1-VT3.R4-R13等组成显示电路,使用共阳数码管。P3.3-P3.5为数码管的动态扫描位驱动。PLO-P1.6作数码段码输出。

二、程序设计

程序用C 语言编写,由主程序、外中断0服务程序,TO 中断服务程序、延时子程序等模块组成。主程序主要完成程序初始化和键盘处理,外部中断朋及务程序由测量、计算、读数等部分组成,TO 中断服务程序由计时、动态扫描显示、自行车停车判断等部分组成。

从P3.2口输人的脉冲信号作为外中断0的中断请求信号,采用沿触发方式。在测量速度时,由于车轮转动脉冲信号的频率很低,不适宜使用计数的方式进行测量,所以采用测脉冲周期的方法进行测量,用脉冲信号系统来控制计时信号,通过计时数计算出脉冲周期,用车轮的周长除以周期便可得到自行车的行驶速度。在测量里程时,用脉冲信号个数乘以车轮的周长便可获得行驶里程。需要说明的是:脉冲信号周期和个数是同时测量的,要做的只是用按钮开关S1切换显示。

本文的程序是针对车轮直径为26英寸的自行车编写的对于其他规格的自行车,只要改写程序spm=14904(常量1)In 和spm=207(常量2)xc 即可。为了避免使用浮点数,远算结果长度是以百米为单位的,数据读出时在第三位数加小数点就换算成千米了。为方便读者制作,现列出各种规格的轮径和轮周长、程序常量的对应值见附表,供参考。

定时器TO 的中断定时时间为5ms ,每中断一次计时变量n 加1,因此n 的单位为5ms 。例如:自行车车轮转一周对应的n 值为100,则对应的时间为0.5s ,由此可得自行车的速度为14.9km/li。如果n 的值达到1000,即5秒钟仍没有发生外部中断,即表示自行车没有前进,n 也被清零,速度显示为0。读数采用三位显示,TO 中断一次显示一位数,中断3次就可以刷新一次数据,即巧ms 刷新一次数据。

三、安装与调试

传感器的安装与调试是一个关键。将它安装在前轮的位置,把一块小永久磁铁固定在车轮的辐条上,UGN3020作防潮密封后固定在前叉上,使得车轮转动时磁铁从它的前面经过,并使两者相遇时间隔尽量小。安装时,要使磁铁的S 极面向UGN3020的正面。判定磁铁极性方法是:把磁铁的两个极分别靠近UGN3020的正面,当其③脚电平由高变低时即为正确的安装位置。传感器安装完成后,转动车轮,UGN3020的③脚应有脉冲信号输出,否则说明两者的间隔偏大,应缩小距离,直至转动时③脚有脉冲信号输出为止。一般间隔为5mm 左右,如果向隔小于5mm 仍无脉冲信号输出,说明磁铁的磁场强度偏小,应予以更换。

调试结束后,把里程速度表安装在车把手上,打开电源,骑动自行车,这时数码管显示的是速度,如果要显示里程,只要按一下S1,如果要回到显示速度,再按一下SI 即可。

江苏 吴汉清

基于单片机的小型自控飞艇舵控系统设计

2008/3/31/16:21 来源:电子技术应用 作者:第二炮兵工程学院 曹毅 王宏力 湖南航天局浮空器研发

以单片机为核心设计并实现了小型自控飞艇的舵机控制系统, 对系统的硬件设计进行了说明,对软件设计中的关键问题——串行通讯及帧识别、多单片机通

讯及PWM 波的软件产生方法进行了详细阐述。

平流层飞艇是一种利用轻于空气的气体(如氦气等) 产生浮力作为升力的飞行于平流层区域的飞行器。它依靠飞艇内部装载的轻于空气的气体产生的静升力,通过控制飞艇上的舵面和动力装置,以较小的能耗实现在平流层的飞行。配备集成化组合导航和自主飞行控制系统的飞艇,可以实现在平流层空间准静止和常驻空自主飞行。它具有高空定点工作时间长、对地观测范围广、维修使用方便以及成本低等特点,因此可以根据任务需要在飞艇上安装相应的载荷,构成对地、对空任务平台。小型自控飞艇是为了验证平流层飞艇飞行特性和控制性能的小型软式试验飞艇,对其控制系统的研究是平流层飞艇研制中一个重要的过渡阶段,

具有极其重要的意义。

1 小型自控飞艇舵控系统简介

舵机是小型自控飞艇执行机构中最主要的执行部件,能否快速、准确地完成对舵机的控制直接关系到飞艇的自主控制效果。因此,舵控系统成为小型飞艇自主飞行控制系统中最重要的组成部分之一,它的主要功能是接收艇载计算机发出的控制指令,实现对控制指令的采集、分析和处理,并根据控制指令向舵机

输出连续可调的舵控信号,操纵艇上各舵机完成预定动作。

2 舵控系统硬件设计

本飞艇舵控系统以多片P89C2051单片机为核心,配合电源模块、驱动芯片及多路转换开关等在一块印制电路板上实现预定功能。舵控系统设计总体框图如

图1所示。

舵控系统主控芯片(主控单片机1、2) 选择P89C51RA2xx 型单片机,它具有8KB 的并行可编程非易失性FLASH 程序存储器,并可对器件串行在系统编程(ISP)和在应用中编程(IAP)。该型微控制器是80C51微控制器的派生器件,是采用先进的CMOS 工艺制造的8位微控制器,指令系统与80C51完全相同。该器件有4组8位I/O口、3个16位定时计数器、多中断源-4中断优先级-嵌套中断结构、1个增强型UART 、片内振荡器及时序电路。舵控单片机采用Atmel 公司的89C2051

型单片机[2],其具体性能这里不再赘述。

电源模块采用美国国家半导体公司生产的LM2576系列产品,它是线性三端稳压器件(如78xx 系列端稳压集成电路)的替代品。相比而言,它的热损耗更低、工作效率更高、输出电流驱动能力更强,同时对于电源的高频干扰还有较强的抑制作用。利用该器件只需极少的外围器件便可构成高效稳压电路,为MCU

稳定可靠的工作提供强有力的保证。

此外,为增强信号的驱动能力,在输出之前采用74LS245作为信号驱动芯片;串口电平转换采用Max232芯片。

该系统硬件设计比较简单,值得一提的是其中的安全性设计部分,即当地面检测到艇上自动控制系统已经失效时,为确保飞艇安全返回,需要将控制方式转至遥控方式。如图1所示,当艇载计算机发生故障时,舵控系统通过无线射频接收机接收地面遥控信号,通过其输出的多通道PWM 波直接控制艇上舵机,控制飞艇安全返回。此处,控制方式的转换是通过多路转换开关实现的,开关的切换信号由艇载计算机看门狗电路在检测到艇载计算机已不能正常工作时给出。

3 舵控系统软件设计

3.1 软件总体结构

舵控系统各单片机程序均在KeilC51环境下采用C 语言编写。为了保证系统的实时性及快速性,软件编写采用了主程序+任务+中断的结构。

在三部分程序中,以主单片机1的外部中断最多,包括串口中断、与主单片机2的握手中断以及艇载计算机看门狗的外部中断,这几个中断的优先级排列顺序是:艇载计算机看门狗中断>串口中断>握手中断。主单片机1接收到艇载计算机通过RS232串口发来的信息帧后,首先进行帧识别,提取出前m 个字节的

数据,加上帧头帧尾后由P1口发送给主单片机2;并将第m+1个字节数据作为开关量通道控制信号由P2口输出,用作系统控制备用。

主单片机2程序的主要任务是通过其P1口接收上位机传来的数据,提取各控制信息,在相应控制指令的前面加上地址,依次由串口发送给下位舵控单片机。

舵控单片机的主要任务是识别控制指令和地址指令,并根据收到的控制指令(舵机占空比信号) 产生PWM 波控制艇上舵机。

该系统软件设计中的关键问题包括以下几个方面:(1)控制信号流程中数据帧的接收识别;(2)舵控系统中主从单片机之间的多机通信;(3)PWM波舵控信号

的软件产生方法。下面对这几个问题进行详细的阐述,并给出相应的解决方案。

3.2 软件设计中的关键问题

(1) 数据帧的串口接收及识别技术

在舵控系统中,数据以二进制信息帧的格式进行传递。每个信息帧从标题开始都有固定的帧头、帧尾,且长度固定,其基本数据格式如表1所示。

在该舵控系统的设计中,串行通讯占有很重要的地位,如艇载计算机与主单片机1之间的通讯过程。下面以主单片机1的串口接收程序为例,对串行通讯

的实现过程加以说明。

在串行通信中,接收程序的任务是数据接收、帧识别和信息提取。常规的设计方法是设置一个比较大的缓冲区。串行接收中断服务程序负责把接收到的数据压入缓冲区,当缓冲区的数据足够多时,再由主程序调用一个帧识别和解码子程序对缓冲区中的数据进行处理。这种方法的好处是中断服务程序比较短,不

足之处为从一帧数据接收完毕到解码时间较长,另外对缓冲区进行管理需要占用大量的的CPU 时间,因而实时性较差,此处不宜使用。

本文采用了中断服务程序就地帧识别技术,即省掉缓冲区,数据接收、帧识别均由中断服务程序完成,之后在主程序的循环中完成数据的提取和处理。就地帧识别技术的实现机理如下:把中断服务程序看作是一个处理机,串行数据逐字节到来,程序先从数据序列中等到第一个帧头,写入该帧的存储数组,同时置标志位flag1,接收状态推进一步;再判断下一次中断时,来到的数据是否符合第二个帧头的特征。如果符合则存入相应数组,并置相应的标志位flag2,接收状态继续推进;如果帧头两个字节均符合,则将后面来到的数据依次存入指定数组;根据已接收到的字节数判断,当符合该帧的数据部分接收完毕后,判断下一字节是否为帧尾的第一个字节,如果是则置标志位flag3;之后依据同样的方法判断帧尾第二个字节是否来到,如果已接收到,则置该帧数据已完整接收到标志flag4,同时接收状态归零,重新开始等待帧头字符。在帧头帧尾判断期间,一旦有一项不符合要求,则将接收状态归零,以重新开始等待帧头。主程

序每循环一次便对“帧完整接收到”标志进行一次判断,若为真则调用相应的数据提取子程序,并清flag4。

串行中断服务程序流程如图2所示。采用中断服务程序就地帧识别技术的优点在于数据接收后立即进行帧识别,省去了对缓冲区的管理工作,减少了存取

次数,因而节省了大量的时间,极大地提高了接收程序的实时性。同时错帧和断帧被自动丢弃,不再占用资源。

图2 中各标志位含义为:

flag1——接收到帧头Head1标志;

flag2——接收到完整帧头标志;

flag3——接收到帧尾End1标志;

flag4——接收到完整帧标志。

(2) 单片机多机通讯

在舵控系统设计中,各部分间的通讯是设计的重要内容,其中主要包括单片机与上位PC 机间的通讯和单片机与单片机之间的通讯。在舵控系统中,主单片

机1与上位PC 机通讯是通过单片机自带的一路异步串行通讯接口完成的;而主单片机1通过其P1口向主单片机2传输数据,这里不再赘述,重点介绍主单片

机2如何通过其一路串口分别向下位的多个舵控单片机传送指令。

此系统中,主单片机2作为主机,m 个舵控单片机作为从机,在主机与从机的通讯过程中,串口控制寄存器中SCON 中的SM2位发挥了重要作用。当其中一个舵控单片机(89C2051)的SM2位为1时,该单片机只接收地址帧,对数据帧不理睬;而当SM2位为0时,该单片机接收所有发来的消息。具体通信过程如下:

①首先将主、从单片机工作方式选为模式3,所有从机的SM2位开始置1,处于只接收地址帧状态。

②主机接收主单片机1发来的数据帧,从中提出数据部分(m个字节的指令对应m 个舵控单片机),根据序号在控制指令字节前加上一个字节的地址信息。

然后主机依次通过串口向下发送各舵控单片机的地址字节和数据字节。发送一帧地址信息,包含8位地址,第9位为1,表示发送的帧为地址帧。

③从机接收地址帧后,进入中断,将发来的地址与自身比较;地址一致的从机就是被寻址的从机,它清除SM2位,接收主机发来的所有后续帧信息(数据信息)。未寻址的所有其他从机仍维持SM2=1,对主机发来的数据帧不理睬,直到发来新地址帧;之后在下一次中断时被寻址的从机接收主机发来的数据信息

(第9位为0)。

需要注意的是,如果对已经寻址的从机再发送地址帧,则该从机SM2=1,恢复初始状态,和其他从机竞争。

(3)舵控信号PWM 波的产生

对飞艇舵机的控制最终是通过舵控单片机产生PWM 波来实现的。通常,产生PWM 波不外乎硬件和软件两种方法。考虑到舵控单片机计算任务不大,本系统

中采用软件产生PWM 波的方法。下面以定时器0产生PWM 波为例,说明通过软件产生PWM 波舵控信号的实现方法。

在程序中,由串口中断接收上位机发送的脉宽指令,继而通过改变入口参数a 来调整PWM 波的脉宽,并确保脉宽输出在正常范围之内。通过该方法产生PWM

波切实可行,简单有效,可以广泛应用于舵机控制信号的产生中。

4 实验结果

实验中以FUTABA3003舵机作为被控对象,由计算机模拟向舵控系统发送数据帧,通过示波器观察舵控信号的变化。实验结果表明,该舵控系统工作稳定,

输出PWM 波脉宽准确可靠,被控舵机转角线性度良好。

本文给出了小型自控飞艇舵控系统的主要设计方法,并详细阐述了在软件设计中几个关键问题的具体解决方案。实验结果证明,该系统能够很好地完成预

定功能,根据上位机发送的指令准确地对艇上舵机进行控制。

基于AT89C2051单片机的多路舵机控制器设计

最起码频率是什么范围要知道吧。

如果单单是频率不高的PWM 用死办法,延时程序嵌套都可以的啊

我曾经用延时嵌套做过LED 调光器,不过频率很低200HZ 左右

用8051的1个定时器就可以了,

假设你的pwm 的频率为 f,

T1的中断频率 至少为 100f(Tt1=1/(100f) ),这样可以做到1%可调, 如果可能的话更大就可调精度更高。

如果有变量 DutyN(DutyN :1-100),PWM 输出口为 PWM_Port:

在T1中断中:

设变量 n++, 当nn>DutyN 时PWM_Port=0;n=100时n 重新设为 0;并且PWM_Port=1,如此循环

这样你可以设定DutyN 的值来产生 1%-100% 占空,频率为f 的 PWM了,当然实际做时要注意 n在 0,DutyN ,100等值时的边界情况,也就是上面“阿土伯”提醒你的地方。

如果要做到频率可调的话用2个Timer2应该方便点。但是如果把上面 的100用变量来代替,比如:TimeN 的话,经过处理同样可以做到 MCS-51系列单片机无PWM输出功能,可以采用定时器配合软件的方法实现,对精度要求不高的场合是非常实用的。电路图见图1,采用高速光隔6N137输出,并将PWM的信号倒相。

这个是我当时学习单片机时写的一个用51产生PWM 的演示程序(现在都忘掉了,如有问题大家自己纠正一下吧),其中P1.3 P1.4是两个输出,这个程序比较匆忙,没有严格验证,可能有错,如有错误请指正。

/*****************************************************************************

* 程序名称:PWM 占空比调整演示程序 *

* 编写时间:2005.9.15 23:30分 *

* 程序版本:1.0 *

* 程序作者:ZHCE EMAIL:[email protected] QQ:187350548 *

* *

******************************************************************************

*程序思路说明: *

* *

*关于频率和占空比的确定,对于12M 晶振,假定PWM 输出频率为1KHZ, 这样定时中断次数 *

*设定为C=10,即0.01MS 中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms ,这样*

*可以设定占空比可从1-100变化。即0.01ms*100=1ms *

******************************************************************************/

#include

#define uchar unsigned char

/*****************************************************************************

* TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256; *

* TH0=(65536-C)/256,其中C 为所要计数的次数即多长时间产生一次中断;TMOD 是计数器*

* 工作模式选择,0X01表示选用模式1, 它有16位计数器,最大计数脉冲为65536, 最长时 *

* 间为1ms*65536=65.536ms *

******************************************************************************/

#define V_TH0 0XFF

#define V_TL0 0XF6

#define V_TMOD 0X01

void init_sys(void); /*系统初始化函数*/

void Delay5Ms(void);

unsigned char ZKB1,ZKB2;

void main (void)

{

init_sys();

ZKB1=40; /*占空比初始值设定*/

ZKB2=70; /*占空比初始值设定*/

while(1)

{

if (!P1_1) //如果按了+键,增加占空比

{

Delay5Ms();

if (!P1_1)

{

ZKB1++;

ZKB2=100-ZKB1;

}

}

if (!P1_2) //如果按了-键,减少占空比

{

Delay5Ms();

if (!P1_2)

{

ZKB1--;

ZKB2=100-ZKB1;

}

}

/*对占空比值限定范围*/

if (ZKB1>99) ZKB1=1;

if (ZKB1

}

}

/******************************************************

*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/

void init_sys(void) /*系统初始化函数*/

{

/*定时器初始化*/

TMOD="V"_TMOD;

TH0=V_TH0;

TL0=V_TL0;

TR0=1;

ET0=1;

EA="1";

}

//延时

void Delay5Ms(void)

{

unsigned int TempCyc = 1000;

while(TempCyc--);

}

/*中断函数*/

void timer0(void) interrupt 1 using 2

{

static uchar click="0"; /*中断次数计数器变量*/

TH0=V_TH0; /*恢复定时器初始值*/

TL0=V_TL0;

++click;

if (click>=100) click="0";

if (click

P1_3=0;

else

P1_3=1;

if (click

P1_4=0;

else

P1_4=1;

}

这是一个51产生PWM 的演示程序

以下为我修改的原代码,修正了错误。联系我:[email protected]

p3,p4为按键,对应+,-

p5 为pwm 输出1,

p6为pwm 输出2,输出占空比为100-p5

/*****************************************************************************

* 程序名称:PWM 占空比调整演示程序 *

* 编写时间:2005.9.15 23:30分 *

* 程序版本:1.0 *

* 程序修改 :sdyzxue *

* 修改时间:2008.12.1 *

* 在源代码的基础上,改正了错误,可以正常仿真。编译无错

误。 * *

******************************************************************************

*程序思路说明: *

* *

*关于频率和占空比的确定,对于12M 晶振,假定PWM 输出频率为1KHZ, 这样定时中断次数 *

*设定为C=10,即0.01MS 中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms ,这样*

*可以设定占空比可从1-100变化。即0.01ms*100=1ms *

******************************************************************************/

#include

#define uchar unsigned char

/*****************************************************************************

* TH0和TL0是计数器0的高8位和低8位计数器,计算办

法:TL0=(65536-C)%256; *

* TH0=(65536-C)/256,其中C 为所要计数的次数即多长时间产生一次中断;TMOD 是计数器*

* 工作模式选择,0X01表示选用模式1, 它有16位计数器,最大计数脉冲为65536, 最长时 * * 间为1ms*65536=65.536ms *

******************************************************************************/

#define V_TH0 0XFF

#define V_TL0 0XF6

#define V_TMOD 0X01

void init_sys(void); /*系统初始化函数*/

void Delay5Ms(void);

unsigned char ZKB1,ZKB2;

unsigned char click=0; /*中断次数计数器变量*/

void main (void)

{

init_sys();

ZKB1=50; /*占空比初始值设定*/

ZKB2=50; /*占空比初始值设定*/

while(1)

{

if (!P3_3) //如果按了+键,增加占空比

{

Delay5Ms();

if (!P3_3)

{

ZKB1=ZKB1+5;

ZKB2=100-ZKB1;

}

}

if (!P3_4) //如果按了-键,减少占空比

{

Delay5Ms();

if (!P3_4)

{

ZKB1=ZKB1-5;

ZKB2=100-ZKB1;

}

}

/*对占空比值限定范围*/

if (ZKB1>99) ZKB1=1;

if (ZKB1

}

}

/******************************************************

*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/

void init_sys(void) /*系统初始化函数*/

{

/*定时器初始化*/

TMOD=V_TMOD;

TH0=V_TH0;

TL0=V_TL0;

TR0=1;

ET0=1;

EA=1;

}

//延时

void Delay5Ms(void)

{

unsigned int TempCyc = 1000;

while(TempCyc--);

}

/*中断函数*/

void timer0(void) interrupt 1 using 2

{

TH0=V_TH0; /*恢复定时器初始值*/

TL0=V_TL0;

++click;

if (click>=100) click=0;

if (click

P3_5=0;

else

P3_5=1;

if (click

P3_6=0;

else

P3_6=1;

}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

0 推荐摘要:本文分析了单片机定时器溢出中断与CPU响应中断的时间误差,并给出了补偿误差的方法和实例。

关键词:单片机; 定时器; 中断; 误差

1 前言

单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU

正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。

2 误差原因、大小及特点

产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。

2.1. CPU正在执行某指令时的误差及大小

由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOV A, Rn,其最大误差为1个机器周期。而执行指令MOV Rn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法 或除法指令 时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc, CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc×Ci(us) 。例如fosc=12MHZ, CPU正在执行乘法指令(Ci=4),此时的最大时间误差为:

Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s) =4(μs)

2.2 CPU正在执行某中断服务的程序时的误差及大小

定时器溢出中断信号时,若CPU正在执行同级或高优先级中断服务程序,则它仍需继续执行这些程序,不能及时响应定时器的溢出中断请求,其延迟时间由中断转移指令周期T1、中断服务程序执行时间T2、中断返回指令的指令周期T3及中断返回原断点后执行下一条指令周期T4(如乘法指令)组成。中断转移指令和中断返回指令的指令周期都分别为2个机器周期。中断服务程序的执行时间为该程序所含指令的指令周期的总和。因此,最大时间误差Δtmax2为:

Δtmax2=(T1+T2+T3+T4)12/fosc=(2+T2+2+4)12/ fosc=12(T2+8)/ fosc

若设fosc=12MHZ,则最大时间误差为:

Δtmax2=12(T2+8)/ fosc =12(T2+8)/12×106=(T2+8)×10-6(s)=T2+8(μs)。

由于上式中T2一般大于8,因此,这种时间误差一般取决于正在执行的中断服务程序。当CPU正在执行中断返回指令RETI、或正在读写IE或IP指令时,这种误差在5个机器周期内。

2.3 误差非固定性特点

定时器溢出中断与CPU响应中断的时间误差具有非固定性特点。即这种误差因CPU正在执行指令的不同而有相当大的差异。如CPU正在执行某中断服务程序,这种误差将远远大于执行一条指令时的误差。后者误差可能是前者误差的几倍、几十倍、甚至更大。如同样只执行一条指令,这种误差也有较大的差别。如执行乘法指令MUL AB 比执行MOV A, Rn指令的时间误差增加了3个机器周期。这种误差的非固定不仅给误差分析带来不便,同时也给误差补偿带来困难。

3 误差补偿方法

由于定时器产生溢出中断与CPU响应中断请求的时间误差具有非固定性,因此,这种误差很难用常规方法补偿。为此,本文介绍一种新方法。

现介绍该方法的基本思路、定时器新初值及应用情况。

3.1 基本思路

为使定时器溢出中断与CPU响应中断实现同步,该方法针对中断响应与中断请求的时间误差,对定时器原有的计数初值进行修改,以延长定时器计数时间,从而补偿误差。在该方法中,当定时器溢出中断得到响应后,即停止定时器的计数,并读出计数值。该计数值是定时器溢出后,重新从OOH开始每个机器周期继续加1所计的值。然后,将这个值与定时器的停止计数时间求和。若在定时器原计数初值中减去这个和形成新计数初值,则定时器能在新计数初值下使溢出中断与CPU响应中断实现同步,从而达到误差的补偿要求。

3.2 定时器新计数初值

若定时器为计数方式,操作方式为1,则计数器初值X0=216-t0×fosc/12。式中fosc为振荡器的振荡频率。t0为需要定时的时间,也为中断的间隔时间。X0为定时器原计数初值。在对定时器溢出中断与CPU响应中断时间误差进行补偿时,定时器的新计数初值X1为:

X1=216-t3× fosc/12

t3=t0+t1+t2

式中t0为中断间隔时间。t1为定时器停止计数时间,该时间为定时器停止计数到重新启动计数之间所有程序指令周期数的总和。t2为定时器溢出中断后,重新从OOH开始直至计数器停止时计的值。在误差补偿中,若将定时器计数初值X1取代X0,则可使定时器下次的溢出中断与CPU响应中断实现同步。

3.3 实例

要求补偿定时器每1ms产生一次溢出中断时的中断响应延迟的误差。若振荡器振荡频率fosc=12MHZ,定时器工作在计数方式,工作模式为1,则补偿中断响应时间误差时的定时器新初值X1为:

X1=216-t3× fosc/12=216-(t0+ t1)- t2=216-(1000+ 13)- t2

误差补偿程序为:

……

0 CLR EA ;关CPU中断

1 CLR TRi ;停止定时器计数

2 MOV R0, #OOH ;R0清零

3 MOV R0, #LOW(216) ;定时器最大计数值的低8位送R0

4 MOV A, R0

5 SUBB A, #LOW(1000+13) ;216的低8位减去( t0+ t1)的低8位送累加器A

6 SUBB A, TLi ;216的低8位减去( t0+ t1+ t2)的低8位送TLi

7 MOV TLi, A

8 MOV R0, #OOH ;R0清零

9 MOV R0, #HIGH(216) ;216 的高8位送R0

10 MOV A, R0

11 SUBB A, #HIGH(1000+13) ;216的高8位减去( t0+ t1)的高8位送A

12 SUBB A, THi ;216的高8位减去( t0+ t1 +t2)的高8位送A

13 MOV THi, A

14 SETB TRi ;重新启动定时器

……

在上式和上段程序中,由于fosc=12MHZ,中断间隔时间为1ms,因此t0的机器周期数为1000。由于第1条指令到第14条指令的指令周期的机器周期数之和为13,因此,t1为13个机器周期。CPU虽在执行第一条指令CLR TRi 后停止定时器计数,但在TLi、THi中分别保存了t2的低位数据和高位数据。

4 结束语

由于本文介绍的误差补偿方法能对定时器溢出中断与CPU响应中断的非固定性时间误差进行有效补偿,因此,该方法对于提高高频控制系统实时控制精度和扩大单片机应用范围都有较高的实用价值。

舵机简介及其单片机控制方法(转贴)

由于rocky 于Sun May 18, 2003 12:59 pm 向本人提出希望了解有关舵机的知识,现将本人在航空模型运动中和机器人制作中积累的一点点经验写出来,奉献给大家,希望本文能起到抛砖引玉的作用。但由于时间仓促,难免有不正确的地方,热情欢迎大家批评指教。

1、概述

舵机最早出现在航模运动中。在航空模型中,飞行机的飞行姿态是通过调节发动机和各个控制舵面来实现的。举个简单的四通飞机来说,飞机上有以下几个地方需要控制:

1. 发动机进气量,来控制发动机的拉力(或推力);

2. 副翼舵面(安装在飞机机翼后缘),用来控制飞机的横滚运动;

3. 水平尾舵面,用来控制飞机的俯仰角;

4. 垂直尾舵面,用来控制飞机的偏航角;

遥控器有四个通道,分别对应四个舵机,而舵机又通过连杆等传动元件带动舵面的转动,从而改变飞机的运动状态。舵机因此得名:控制舵面的伺服电机。

不仅在航模飞机中,在其他的模型运动中都可以看到它的应用:船模上用来控制尾舵,车模中用来转向等等。由此可见,凡是需要操作性动作时都可以用舵机来实现。

2、结构和控制

一般来讲,舵机主要由以下几个部分组成, 舵盘、减速齿轮组、位置反馈电位计5k 、直流电机、控制电路板等。

工作原理:控制电路板接受来自信号线的控制信号(具体信号待会再讲),控制电机转动,电机带动一系列齿轮组,减速后传动至输出舵盘。舵机的输出轴和位置反馈电位计是相连的,舵盘转动的同时,带动位置反馈电位计,电位计将输出一个电压信号到控制电路板,进行反馈,然后控制电路板根据所在位置决定电机的转动方向和速度,从而达到目标停止。

舵机的基本结构是这样,但实现起来有很多种。例如电机就有有刷和无刷之分,齿轮有塑料和金属之分,输出轴有滑动和滚动之分,壳体有塑料和铝合金之分,速度有快速和慢速之分,体积有大中小三种之分等等,组合不同,价格也千差万别。例如,其中小舵机一般称作微舵,同种材料的条件下是中型的一倍多,金属齿轮是塑料齿轮的一倍多。需要根据需要选用不同类型。

舵机的输入线共有三条,红色中间,是电源线,一边黑色的是地线,这辆根线给舵机提供最基本的能源保证,主要是电机的转动消耗。电源有两种规格,一是4.8V ,一是6.0V ,分别对应不同的转矩标准,即输出力矩不同,6.0V 对应的要大一些,具体看应用条件;另外一根线是控制信号线,Futaba 的一般为白色,JR 的一般为桔黄色。另外要注意一点,SANWA 的某些型号的舵机引线电源线在边上而不是中间,需要辨认。但记住红色为电源,黑色为地线,一般不会搞错。 舵机的控制信号为周期是20ms 的脉宽调制(PWM )信号,其中脉冲宽度从0.5ms-2.5ms ,相对应舵盘的位置为0-180度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。舵机内部有一个基准电路,产生周期20ms ,宽度1.5ms 的基准信号,有一个比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机

的转动信号。由此可见,舵机是一种位置伺服的驱动器,转动范围不能超过180度,适用于那些需要角度不断变化并可以保持的驱动当中。比方说机器人的关节、飞机的舵面等。

常见的舵机厂家有:日本的Futaba 、JR 、SANWA 等,国产的有北京的新幻想、吉林的振华等。现举Futaba S3003来介绍相关参数,以供大家设计时选用。之所以用3003是因为这个型号是市场上最常见的,也是价格相对较便宜的一种(以下数据摘自Futaba 产品手册)。

尺 寸(Dimensions): 40.4×19.8×36.0 mm

重 量(Weight): 37.2 g

工作速度(Operating speed):0.23 sec/60°(4.8V)

0.19 sec/60°(6.0V)

输出力矩(Output torque): 3.2 kg.cm (4.8V)

4.1 kg.cm (6.0V)

由此可见,舵机具有以下一些特点:

>体积紧凑,便于安装;

>输出力矩大,稳定性好;

>控制简单,便于和数字系统接口;

正是因为舵机有很多优点,所以,现在不仅仅应用在航模运动中,已经扩展到各种机电产品中来,在机器人控制中应用也越来越广泛。

3、用单片机来控制

正是舵机的控制信号是一个脉宽调制信号,所以很方便和数字系统进行接口。只要能产生标准的控制信号的数字设备都可以用来控制舵机,比方PLC 、单片机等。这里介绍利用51系列单片机产生舵机的控制信号来进行控制的方法,编程语言为C51。之所以介绍这种方法只是因为笔者用2051实现过,本着负责的态度,所以敢在这里写出来。程序用的是我的四足步行机器人,有删改。单片机并不是控制舵机的最好的方法,希望在此能起到抛砖引玉的作用。

2051有两个16位的内部计数器,我们就用它来产生周期20 ms 的脉冲信号,根据需要,改变输出脉宽。基本思路如下(请对照下面的程序):

我用的晶振频率为12M ,2051一个时钟周期为12个晶振周期,正好是1/1000 ms,计数器每隔1/1000 ms 计一次数。以计数器1为例,先设定脉宽的初始值,程序中初始为1.5ms ,在for 循环中可以随时通过改变a 值来改变,然后设定计数器计数初始值为a ,并置输出p12为高位。当计数结束时,触发计数器溢出中断函数,就是void timer0(void) interrupt 1 using1 ,在子函数中,改变输出p12为反相(此时跳为低位),在用20000(代表20ms 周期)减去高位用的时间a ,就是本周期中低位的时间,c=20000-a,并设定此时的计数器初值为c ,直到定时器再次产生溢出中断,重复上一过程。

# include

#define uchar unsigned char

#define uint unsigned int

uint a,b,c,d;

sbit p12=P1^2;

sbit p13=p1^3;

sbit p37=P3^7;

void timer0(void) interrupt 1 using 1

{ p12=!p12;

c=20000-c;

TH0=-(c/256); TL0=-(c%256);

if(c>=500&&c

else c=20000-a;

}

void timer1(void) interrupt 3 using 1

{p13=!p13;

d=20000-d;

TH1=-(d/256); TL1=-(d%256);

if(d>=500&&d

else d=20000-b;

}

void main(void)

{TMOD=0x11;

p12=1;

p13=1;

a=1500;

b=1500;

c=a;d=b;

TH0=-(a/256); TL0=-(a%256);

TH1=-(b/256); TL1=-(b%256);

EA=1;

ET0=1; TR0=1;EX0=1;EX1=1;

ET1=1; TR1=1;

PX0=0;PX1=0;PT1=1;PT0=1;

for(;;)

{

}

}

因为在脉冲信号的输出是靠定时器的溢出中断函数来处理,时间很短,因此在精度要求不高的场合可以忽略。因此如果忽略中断时间,从另一个角度来讲就是主程序和脉冲输出是并行的,因此,只需要在主程序中按你的要求改变a 值,例如让a 从500变化到2500,就可以让舵机从0度变化到180度。另外要记住一点,舵机的转动需要时间的,因此,程序中a 值的变化不能太快,不然舵机跟不上程序。根据需要,选择合适的延时,用一个a 递增循环,可以让舵机很流畅的转动,而不会产生像步进电机一样的脉动。这些还需要实践中具体体会。

舵机的速度决定于你给它的信号脉宽的变化速度。举个例子,t =0试,脉宽为0.5ms ,t =1s 时,脉宽为1.0ms ,那么,舵机就会从0.5ms 对应的位置转到1.0ms 对应的位置,那么转动速度如何呢?一般来讲,3003的最大转动速度在4.8V 时为0.23s/60度,也就是说,如果你要求的速度比这个快的话,舵机就反应不过来了;如果要求速度比这个慢,可以将脉宽变化值线性到你要求的时间内,做一个循环,一点一点的增加脉宽值,就可以控制舵机的速度了。当然,具体这一点一点到底是多少,就需要做试验了,不然的话,不合适的话,舵机就会向步进电机一样一跳一跳的转动了,尝试改变这“一点”,使你的舵机运动更平滑。还有一点很重要,就是舵机在每一次脉宽值改变的时候总会有一个转速由零增加再减速为零的过程,这就是舵机会产生像步进电机一样运动的原因。

请问一下,舵机转动速度是如何控制的?

这个比较简单吧,驱动普通舵机只要一个口线直接接舵机信号线就行了。软件上可以用“分时复用比较法(我自己想的名字)”来做。简单来说就是:设置一个定时器让它按舵机最小分辨率的周期来溢出,溢出后让某个寄存器从1开始到最大值不断重复,这个最大值不一定是0FFH ,可以根据自己的需要设。每次定时器溢出的时候进入中断,寄存器加1后和每个舵机的预设值进行比较,判断是否改变高电平的宽度。这个比较一般只能处理不多的几路(要保证在下个定时器中断前完成比较)。因为舵机信号的脉宽最大只有2.5MS ,在处理这几路舵机的时候把其它的舵机信号都拉低。当处理完这几路的时候,也就是定时器从1到最大值完成一次后,(这时候前面处理过的几路应该都是低电平了)把下次需要处理的几路都拉高。然后再比较这几路该什么时候拉低,依次循环,直到总时间达到20MS ,再回过头来处理刚开始处理的几路。

一、电路原理

电路如图1所示,由检测传感器、单片机电路和数码显示电路等组成。 检测传感器由永久磁铁和开关型霍尔集成电路UGN3020. 组成。UGN3020由霍尔元件、放大器、整形电路及集电极开路输出电路等组成,其功能是把磁信号转换成电信号,图2a 是其内部框图。霍尔元件H 为磁敏元件,当垂直于霍尔元件的磁场强度随之变化时,其两端的电压就会发生变化,经放大和整形后,即可在

③脚输出脉冲电信号。其工作特性如图2b 所示。由于有一定的磁滞效应,可保证开关无抖动。B 叩为工作点“开”的磁场强度,Brp 为释放点“关”的磁场强度。永久磁铁固定在车轮的辐条上,UGN3020固定在车轮的叉架上。检测传感器的工作原理如下:车轮每转一周,磁铁经过UGN3020一次,其③脚就输出一个脉冲信号。UGN3020输出的脉冲信号作为单片机AT89C2051的外中断信号,从P3.2口输人。单片机测量脉冲信号的个数和脉冲周期。根据脉冲信号的个数计算出里程,根据脉冲信号的周期计算出速度并送数码管显示。S1用来进行里程和速度显示的切换,在初始状态下显示的是速度。

数码管DS1--DS3,VT1-VT3.R4-R13等组成显示电路,使用共阳数码管。P3.3-P3.5为数码管的动态扫描位驱动。PLO-P1.6作数码段码输出。

二、程序设计

程序用C 语言编写,由主程序、外中断0服务程序,TO 中断服务程序、延时子程序等模块组成。主程序主要完成程序初始化和键盘处理,外部中断朋及务程序由测量、计算、读数等部分组成,TO 中断服务程序由计时、动态扫描显示、自行车停车判断等部分组成。

从P3.2口输人的脉冲信号作为外中断0的中断请求信号,采用沿触发方式。在测量速度时,由于车轮转动脉冲信号的频率很低,不适宜使用计数的方式进行测量,所以采用测脉冲周期的方法进行测量,用脉冲信号系统来控制计时信号,通过计时数计算出脉冲周期,用车轮的周长除以周期便可得到自行车的行驶速度。在测量里程时,用脉冲信号个数乘以车轮的周长便可获得行驶里程。需要说明的是:脉冲信号周期和个数是同时测量的,要做的只是用按钮开关S1切换显示。

本文的程序是针对车轮直径为26英寸的自行车编写的对于其他规格的自行车,只要改写程序spm=14904(常量1)In 和spm=207(常量2)xc 即可。为了避免使用浮点数,远算结果长度是以百米为单位的,数据读出时在第三位数加小数点就换算成千米了。为方便读者制作,现列出各种规格的轮径和轮周长、程序常量的对应值见附表,供参考。

定时器TO 的中断定时时间为5ms ,每中断一次计时变量n 加1,因此n 的单位为5ms 。例如:自行车车轮转一周对应的n 值为100,则对应的时间为0.5s ,由此可得自行车的速度为14.9km/li。如果n 的值达到1000,即5秒钟仍没有发生外部中断,即表示自行车没有前进,n 也被清零,速度显示为0。读数采用三位显示,TO 中断一次显示一位数,中断3次就可以刷新一次数据,即巧ms 刷新一次数据。

三、安装与调试

传感器的安装与调试是一个关键。将它安装在前轮的位置,把一块小永久磁铁固定在车轮的辐条上,UGN3020作防潮密封后固定在前叉上,使得车轮转动时磁铁从它的前面经过,并使两者相遇时间隔尽量小。安装时,要使磁铁的S 极面向UGN3020的正面。判定磁铁极性方法是:把磁铁的两个极分别靠近UGN3020的正面,当其③脚电平由高变低时即为正确的安装位置。传感器安装完成后,转动车轮,UGN3020的③脚应有脉冲信号输出,否则说明两者的间隔偏大,应缩小距离,直至转动时③脚有脉冲信号输出为止。一般间隔为5mm 左右,如果向隔小于5mm 仍无脉冲信号输出,说明磁铁的磁场强度偏小,应予以更换。

调试结束后,把里程速度表安装在车把手上,打开电源,骑动自行车,这时数码管显示的是速度,如果要显示里程,只要按一下S1,如果要回到显示速度,再按一下SI 即可。

江苏 吴汉清

基于单片机的小型自控飞艇舵控系统设计

2008/3/31/16:21 来源:电子技术应用 作者:第二炮兵工程学院 曹毅 王宏力 湖南航天局浮空器研发

以单片机为核心设计并实现了小型自控飞艇的舵机控制系统, 对系统的硬件设计进行了说明,对软件设计中的关键问题——串行通讯及帧识别、多单片机通

讯及PWM 波的软件产生方法进行了详细阐述。

平流层飞艇是一种利用轻于空气的气体(如氦气等) 产生浮力作为升力的飞行于平流层区域的飞行器。它依靠飞艇内部装载的轻于空气的气体产生的静升力,通过控制飞艇上的舵面和动力装置,以较小的能耗实现在平流层的飞行。配备集成化组合导航和自主飞行控制系统的飞艇,可以实现在平流层空间准静止和常驻空自主飞行。它具有高空定点工作时间长、对地观测范围广、维修使用方便以及成本低等特点,因此可以根据任务需要在飞艇上安装相应的载荷,构成对地、对空任务平台。小型自控飞艇是为了验证平流层飞艇飞行特性和控制性能的小型软式试验飞艇,对其控制系统的研究是平流层飞艇研制中一个重要的过渡阶段,

具有极其重要的意义。

1 小型自控飞艇舵控系统简介

舵机是小型自控飞艇执行机构中最主要的执行部件,能否快速、准确地完成对舵机的控制直接关系到飞艇的自主控制效果。因此,舵控系统成为小型飞艇自主飞行控制系统中最重要的组成部分之一,它的主要功能是接收艇载计算机发出的控制指令,实现对控制指令的采集、分析和处理,并根据控制指令向舵机

输出连续可调的舵控信号,操纵艇上各舵机完成预定动作。

2 舵控系统硬件设计

本飞艇舵控系统以多片P89C2051单片机为核心,配合电源模块、驱动芯片及多路转换开关等在一块印制电路板上实现预定功能。舵控系统设计总体框图如

图1所示。

舵控系统主控芯片(主控单片机1、2) 选择P89C51RA2xx 型单片机,它具有8KB 的并行可编程非易失性FLASH 程序存储器,并可对器件串行在系统编程(ISP)和在应用中编程(IAP)。该型微控制器是80C51微控制器的派生器件,是采用先进的CMOS 工艺制造的8位微控制器,指令系统与80C51完全相同。该器件有4组8位I/O口、3个16位定时计数器、多中断源-4中断优先级-嵌套中断结构、1个增强型UART 、片内振荡器及时序电路。舵控单片机采用Atmel 公司的89C2051

型单片机[2],其具体性能这里不再赘述。

电源模块采用美国国家半导体公司生产的LM2576系列产品,它是线性三端稳压器件(如78xx 系列端稳压集成电路)的替代品。相比而言,它的热损耗更低、工作效率更高、输出电流驱动能力更强,同时对于电源的高频干扰还有较强的抑制作用。利用该器件只需极少的外围器件便可构成高效稳压电路,为MCU

稳定可靠的工作提供强有力的保证。

此外,为增强信号的驱动能力,在输出之前采用74LS245作为信号驱动芯片;串口电平转换采用Max232芯片。

该系统硬件设计比较简单,值得一提的是其中的安全性设计部分,即当地面检测到艇上自动控制系统已经失效时,为确保飞艇安全返回,需要将控制方式转至遥控方式。如图1所示,当艇载计算机发生故障时,舵控系统通过无线射频接收机接收地面遥控信号,通过其输出的多通道PWM 波直接控制艇上舵机,控制飞艇安全返回。此处,控制方式的转换是通过多路转换开关实现的,开关的切换信号由艇载计算机看门狗电路在检测到艇载计算机已不能正常工作时给出。

3 舵控系统软件设计

3.1 软件总体结构

舵控系统各单片机程序均在KeilC51环境下采用C 语言编写。为了保证系统的实时性及快速性,软件编写采用了主程序+任务+中断的结构。

在三部分程序中,以主单片机1的外部中断最多,包括串口中断、与主单片机2的握手中断以及艇载计算机看门狗的外部中断,这几个中断的优先级排列顺序是:艇载计算机看门狗中断>串口中断>握手中断。主单片机1接收到艇载计算机通过RS232串口发来的信息帧后,首先进行帧识别,提取出前m 个字节的

数据,加上帧头帧尾后由P1口发送给主单片机2;并将第m+1个字节数据作为开关量通道控制信号由P2口输出,用作系统控制备用。

主单片机2程序的主要任务是通过其P1口接收上位机传来的数据,提取各控制信息,在相应控制指令的前面加上地址,依次由串口发送给下位舵控单片机。

舵控单片机的主要任务是识别控制指令和地址指令,并根据收到的控制指令(舵机占空比信号) 产生PWM 波控制艇上舵机。

该系统软件设计中的关键问题包括以下几个方面:(1)控制信号流程中数据帧的接收识别;(2)舵控系统中主从单片机之间的多机通信;(3)PWM波舵控信号

的软件产生方法。下面对这几个问题进行详细的阐述,并给出相应的解决方案。

3.2 软件设计中的关键问题

(1) 数据帧的串口接收及识别技术

在舵控系统中,数据以二进制信息帧的格式进行传递。每个信息帧从标题开始都有固定的帧头、帧尾,且长度固定,其基本数据格式如表1所示。

在该舵控系统的设计中,串行通讯占有很重要的地位,如艇载计算机与主单片机1之间的通讯过程。下面以主单片机1的串口接收程序为例,对串行通讯

的实现过程加以说明。

在串行通信中,接收程序的任务是数据接收、帧识别和信息提取。常规的设计方法是设置一个比较大的缓冲区。串行接收中断服务程序负责把接收到的数据压入缓冲区,当缓冲区的数据足够多时,再由主程序调用一个帧识别和解码子程序对缓冲区中的数据进行处理。这种方法的好处是中断服务程序比较短,不

足之处为从一帧数据接收完毕到解码时间较长,另外对缓冲区进行管理需要占用大量的的CPU 时间,因而实时性较差,此处不宜使用。

本文采用了中断服务程序就地帧识别技术,即省掉缓冲区,数据接收、帧识别均由中断服务程序完成,之后在主程序的循环中完成数据的提取和处理。就地帧识别技术的实现机理如下:把中断服务程序看作是一个处理机,串行数据逐字节到来,程序先从数据序列中等到第一个帧头,写入该帧的存储数组,同时置标志位flag1,接收状态推进一步;再判断下一次中断时,来到的数据是否符合第二个帧头的特征。如果符合则存入相应数组,并置相应的标志位flag2,接收状态继续推进;如果帧头两个字节均符合,则将后面来到的数据依次存入指定数组;根据已接收到的字节数判断,当符合该帧的数据部分接收完毕后,判断下一字节是否为帧尾的第一个字节,如果是则置标志位flag3;之后依据同样的方法判断帧尾第二个字节是否来到,如果已接收到,则置该帧数据已完整接收到标志flag4,同时接收状态归零,重新开始等待帧头字符。在帧头帧尾判断期间,一旦有一项不符合要求,则将接收状态归零,以重新开始等待帧头。主程

序每循环一次便对“帧完整接收到”标志进行一次判断,若为真则调用相应的数据提取子程序,并清flag4。

串行中断服务程序流程如图2所示。采用中断服务程序就地帧识别技术的优点在于数据接收后立即进行帧识别,省去了对缓冲区的管理工作,减少了存取

次数,因而节省了大量的时间,极大地提高了接收程序的实时性。同时错帧和断帧被自动丢弃,不再占用资源。

图2 中各标志位含义为:

flag1——接收到帧头Head1标志;

flag2——接收到完整帧头标志;

flag3——接收到帧尾End1标志;

flag4——接收到完整帧标志。

(2) 单片机多机通讯

在舵控系统设计中,各部分间的通讯是设计的重要内容,其中主要包括单片机与上位PC 机间的通讯和单片机与单片机之间的通讯。在舵控系统中,主单片

机1与上位PC 机通讯是通过单片机自带的一路异步串行通讯接口完成的;而主单片机1通过其P1口向主单片机2传输数据,这里不再赘述,重点介绍主单片

机2如何通过其一路串口分别向下位的多个舵控单片机传送指令。

此系统中,主单片机2作为主机,m 个舵控单片机作为从机,在主机与从机的通讯过程中,串口控制寄存器中SCON 中的SM2位发挥了重要作用。当其中一个舵控单片机(89C2051)的SM2位为1时,该单片机只接收地址帧,对数据帧不理睬;而当SM2位为0时,该单片机接收所有发来的消息。具体通信过程如下:

①首先将主、从单片机工作方式选为模式3,所有从机的SM2位开始置1,处于只接收地址帧状态。

②主机接收主单片机1发来的数据帧,从中提出数据部分(m个字节的指令对应m 个舵控单片机),根据序号在控制指令字节前加上一个字节的地址信息。

然后主机依次通过串口向下发送各舵控单片机的地址字节和数据字节。发送一帧地址信息,包含8位地址,第9位为1,表示发送的帧为地址帧。

③从机接收地址帧后,进入中断,将发来的地址与自身比较;地址一致的从机就是被寻址的从机,它清除SM2位,接收主机发来的所有后续帧信息(数据信息)。未寻址的所有其他从机仍维持SM2=1,对主机发来的数据帧不理睬,直到发来新地址帧;之后在下一次中断时被寻址的从机接收主机发来的数据信息

(第9位为0)。

需要注意的是,如果对已经寻址的从机再发送地址帧,则该从机SM2=1,恢复初始状态,和其他从机竞争。

(3)舵控信号PWM 波的产生

对飞艇舵机的控制最终是通过舵控单片机产生PWM 波来实现的。通常,产生PWM 波不外乎硬件和软件两种方法。考虑到舵控单片机计算任务不大,本系统

中采用软件产生PWM 波的方法。下面以定时器0产生PWM 波为例,说明通过软件产生PWM 波舵控信号的实现方法。

在程序中,由串口中断接收上位机发送的脉宽指令,继而通过改变入口参数a 来调整PWM 波的脉宽,并确保脉宽输出在正常范围之内。通过该方法产生PWM

波切实可行,简单有效,可以广泛应用于舵机控制信号的产生中。

4 实验结果

实验中以FUTABA3003舵机作为被控对象,由计算机模拟向舵控系统发送数据帧,通过示波器观察舵控信号的变化。实验结果表明,该舵控系统工作稳定,

输出PWM 波脉宽准确可靠,被控舵机转角线性度良好。

本文给出了小型自控飞艇舵控系统的主要设计方法,并详细阐述了在软件设计中几个关键问题的具体解决方案。实验结果证明,该系统能够很好地完成预

定功能,根据上位机发送的指令准确地对艇上舵机进行控制。

基于AT89C2051单片机的多路舵机控制器设计

最起码频率是什么范围要知道吧。

如果单单是频率不高的PWM 用死办法,延时程序嵌套都可以的啊

我曾经用延时嵌套做过LED 调光器,不过频率很低200HZ 左右

用8051的1个定时器就可以了,

假设你的pwm 的频率为 f,

T1的中断频率 至少为 100f(Tt1=1/(100f) ),这样可以做到1%可调, 如果可能的话更大就可调精度更高。

如果有变量 DutyN(DutyN :1-100),PWM 输出口为 PWM_Port:

在T1中断中:

设变量 n++, 当nn>DutyN 时PWM_Port=0;n=100时n 重新设为 0;并且PWM_Port=1,如此循环

这样你可以设定DutyN 的值来产生 1%-100% 占空,频率为f 的 PWM了,当然实际做时要注意 n在 0,DutyN ,100等值时的边界情况,也就是上面“阿土伯”提醒你的地方。

如果要做到频率可调的话用2个Timer2应该方便点。但是如果把上面 的100用变量来代替,比如:TimeN 的话,经过处理同样可以做到 MCS-51系列单片机无PWM输出功能,可以采用定时器配合软件的方法实现,对精度要求不高的场合是非常实用的。电路图见图1,采用高速光隔6N137输出,并将PWM的信号倒相。

这个是我当时学习单片机时写的一个用51产生PWM 的演示程序(现在都忘掉了,如有问题大家自己纠正一下吧),其中P1.3 P1.4是两个输出,这个程序比较匆忙,没有严格验证,可能有错,如有错误请指正。

/*****************************************************************************

* 程序名称:PWM 占空比调整演示程序 *

* 编写时间:2005.9.15 23:30分 *

* 程序版本:1.0 *

* 程序作者:ZHCE EMAIL:[email protected] QQ:187350548 *

* *

******************************************************************************

*程序思路说明: *

* *

*关于频率和占空比的确定,对于12M 晶振,假定PWM 输出频率为1KHZ, 这样定时中断次数 *

*设定为C=10,即0.01MS 中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms ,这样*

*可以设定占空比可从1-100变化。即0.01ms*100=1ms *

******************************************************************************/

#include

#define uchar unsigned char

/*****************************************************************************

* TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256; *

* TH0=(65536-C)/256,其中C 为所要计数的次数即多长时间产生一次中断;TMOD 是计数器*

* 工作模式选择,0X01表示选用模式1, 它有16位计数器,最大计数脉冲为65536, 最长时 *

* 间为1ms*65536=65.536ms *

******************************************************************************/

#define V_TH0 0XFF

#define V_TL0 0XF6

#define V_TMOD 0X01

void init_sys(void); /*系统初始化函数*/

void Delay5Ms(void);

unsigned char ZKB1,ZKB2;

void main (void)

{

init_sys();

ZKB1=40; /*占空比初始值设定*/

ZKB2=70; /*占空比初始值设定*/

while(1)

{

if (!P1_1) //如果按了+键,增加占空比

{

Delay5Ms();

if (!P1_1)

{

ZKB1++;

ZKB2=100-ZKB1;

}

}

if (!P1_2) //如果按了-键,减少占空比

{

Delay5Ms();

if (!P1_2)

{

ZKB1--;

ZKB2=100-ZKB1;

}

}

/*对占空比值限定范围*/

if (ZKB1>99) ZKB1=1;

if (ZKB1

}

}

/******************************************************

*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/

void init_sys(void) /*系统初始化函数*/

{

/*定时器初始化*/

TMOD="V"_TMOD;

TH0=V_TH0;

TL0=V_TL0;

TR0=1;

ET0=1;

EA="1";

}

//延时

void Delay5Ms(void)

{

unsigned int TempCyc = 1000;

while(TempCyc--);

}

/*中断函数*/

void timer0(void) interrupt 1 using 2

{

static uchar click="0"; /*中断次数计数器变量*/

TH0=V_TH0; /*恢复定时器初始值*/

TL0=V_TL0;

++click;

if (click>=100) click="0";

if (click

P1_3=0;

else

P1_3=1;

if (click

P1_4=0;

else

P1_4=1;

}

这是一个51产生PWM 的演示程序

以下为我修改的原代码,修正了错误。联系我:[email protected]

p3,p4为按键,对应+,-

p5 为pwm 输出1,

p6为pwm 输出2,输出占空比为100-p5

/*****************************************************************************

* 程序名称:PWM 占空比调整演示程序 *

* 编写时间:2005.9.15 23:30分 *

* 程序版本:1.0 *

* 程序修改 :sdyzxue *

* 修改时间:2008.12.1 *

* 在源代码的基础上,改正了错误,可以正常仿真。编译无错

误。 * *

******************************************************************************

*程序思路说明: *

* *

*关于频率和占空比的确定,对于12M 晶振,假定PWM 输出频率为1KHZ, 这样定时中断次数 *

*设定为C=10,即0.01MS 中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms ,这样*

*可以设定占空比可从1-100变化。即0.01ms*100=1ms *

******************************************************************************/

#include

#define uchar unsigned char

/*****************************************************************************

* TH0和TL0是计数器0的高8位和低8位计数器,计算办

法:TL0=(65536-C)%256; *

* TH0=(65536-C)/256,其中C 为所要计数的次数即多长时间产生一次中断;TMOD 是计数器*

* 工作模式选择,0X01表示选用模式1, 它有16位计数器,最大计数脉冲为65536, 最长时 * * 间为1ms*65536=65.536ms *

******************************************************************************/

#define V_TH0 0XFF

#define V_TL0 0XF6

#define V_TMOD 0X01

void init_sys(void); /*系统初始化函数*/

void Delay5Ms(void);

unsigned char ZKB1,ZKB2;

unsigned char click=0; /*中断次数计数器变量*/

void main (void)

{

init_sys();

ZKB1=50; /*占空比初始值设定*/

ZKB2=50; /*占空比初始值设定*/

while(1)

{

if (!P3_3) //如果按了+键,增加占空比

{

Delay5Ms();

if (!P3_3)

{

ZKB1=ZKB1+5;

ZKB2=100-ZKB1;

}

}

if (!P3_4) //如果按了-键,减少占空比

{

Delay5Ms();

if (!P3_4)

{

ZKB1=ZKB1-5;

ZKB2=100-ZKB1;

}

}

/*对占空比值限定范围*/

if (ZKB1>99) ZKB1=1;

if (ZKB1

}

}

/******************************************************

*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/

void init_sys(void) /*系统初始化函数*/

{

/*定时器初始化*/

TMOD=V_TMOD;

TH0=V_TH0;

TL0=V_TL0;

TR0=1;

ET0=1;

EA=1;

}

//延时

void Delay5Ms(void)

{

unsigned int TempCyc = 1000;

while(TempCyc--);

}

/*中断函数*/

void timer0(void) interrupt 1 using 2

{

TH0=V_TH0; /*恢复定时器初始值*/

TL0=V_TL0;

++click;

if (click>=100) click=0;

if (click

P3_5=0;

else

P3_5=1;

if (click

P3_6=0;

else

P3_6=1;

}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

0 推荐摘要:本文分析了单片机定时器溢出中断与CPU响应中断的时间误差,并给出了补偿误差的方法和实例。

关键词:单片机; 定时器; 中断; 误差

1 前言

单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU

正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。

2 误差原因、大小及特点

产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。

2.1. CPU正在执行某指令时的误差及大小

由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOV A, Rn,其最大误差为1个机器周期。而执行指令MOV Rn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法 或除法指令 时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc, CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc×Ci(us) 。例如fosc=12MHZ, CPU正在执行乘法指令(Ci=4),此时的最大时间误差为:

Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s) =4(μs)

2.2 CPU正在执行某中断服务的程序时的误差及大小

定时器溢出中断信号时,若CPU正在执行同级或高优先级中断服务程序,则它仍需继续执行这些程序,不能及时响应定时器的溢出中断请求,其延迟时间由中断转移指令周期T1、中断服务程序执行时间T2、中断返回指令的指令周期T3及中断返回原断点后执行下一条指令周期T4(如乘法指令)组成。中断转移指令和中断返回指令的指令周期都分别为2个机器周期。中断服务程序的执行时间为该程序所含指令的指令周期的总和。因此,最大时间误差Δtmax2为:

Δtmax2=(T1+T2+T3+T4)12/fosc=(2+T2+2+4)12/ fosc=12(T2+8)/ fosc

若设fosc=12MHZ,则最大时间误差为:

Δtmax2=12(T2+8)/ fosc =12(T2+8)/12×106=(T2+8)×10-6(s)=T2+8(μs)。

由于上式中T2一般大于8,因此,这种时间误差一般取决于正在执行的中断服务程序。当CPU正在执行中断返回指令RETI、或正在读写IE或IP指令时,这种误差在5个机器周期内。

2.3 误差非固定性特点

定时器溢出中断与CPU响应中断的时间误差具有非固定性特点。即这种误差因CPU正在执行指令的不同而有相当大的差异。如CPU正在执行某中断服务程序,这种误差将远远大于执行一条指令时的误差。后者误差可能是前者误差的几倍、几十倍、甚至更大。如同样只执行一条指令,这种误差也有较大的差别。如执行乘法指令MUL AB 比执行MOV A, Rn指令的时间误差增加了3个机器周期。这种误差的非固定不仅给误差分析带来不便,同时也给误差补偿带来困难。

3 误差补偿方法

由于定时器产生溢出中断与CPU响应中断请求的时间误差具有非固定性,因此,这种误差很难用常规方法补偿。为此,本文介绍一种新方法。

现介绍该方法的基本思路、定时器新初值及应用情况。

3.1 基本思路

为使定时器溢出中断与CPU响应中断实现同步,该方法针对中断响应与中断请求的时间误差,对定时器原有的计数初值进行修改,以延长定时器计数时间,从而补偿误差。在该方法中,当定时器溢出中断得到响应后,即停止定时器的计数,并读出计数值。该计数值是定时器溢出后,重新从OOH开始每个机器周期继续加1所计的值。然后,将这个值与定时器的停止计数时间求和。若在定时器原计数初值中减去这个和形成新计数初值,则定时器能在新计数初值下使溢出中断与CPU响应中断实现同步,从而达到误差的补偿要求。

3.2 定时器新计数初值

若定时器为计数方式,操作方式为1,则计数器初值X0=216-t0×fosc/12。式中fosc为振荡器的振荡频率。t0为需要定时的时间,也为中断的间隔时间。X0为定时器原计数初值。在对定时器溢出中断与CPU响应中断时间误差进行补偿时,定时器的新计数初值X1为:

X1=216-t3× fosc/12

t3=t0+t1+t2

式中t0为中断间隔时间。t1为定时器停止计数时间,该时间为定时器停止计数到重新启动计数之间所有程序指令周期数的总和。t2为定时器溢出中断后,重新从OOH开始直至计数器停止时计的值。在误差补偿中,若将定时器计数初值X1取代X0,则可使定时器下次的溢出中断与CPU响应中断实现同步。

3.3 实例

要求补偿定时器每1ms产生一次溢出中断时的中断响应延迟的误差。若振荡器振荡频率fosc=12MHZ,定时器工作在计数方式,工作模式为1,则补偿中断响应时间误差时的定时器新初值X1为:

X1=216-t3× fosc/12=216-(t0+ t1)- t2=216-(1000+ 13)- t2

误差补偿程序为:

……

0 CLR EA ;关CPU中断

1 CLR TRi ;停止定时器计数

2 MOV R0, #OOH ;R0清零

3 MOV R0, #LOW(216) ;定时器最大计数值的低8位送R0

4 MOV A, R0

5 SUBB A, #LOW(1000+13) ;216的低8位减去( t0+ t1)的低8位送累加器A

6 SUBB A, TLi ;216的低8位减去( t0+ t1+ t2)的低8位送TLi

7 MOV TLi, A

8 MOV R0, #OOH ;R0清零

9 MOV R0, #HIGH(216) ;216 的高8位送R0

10 MOV A, R0

11 SUBB A, #HIGH(1000+13) ;216的高8位减去( t0+ t1)的高8位送A

12 SUBB A, THi ;216的高8位减去( t0+ t1 +t2)的高8位送A

13 MOV THi, A

14 SETB TRi ;重新启动定时器

……

在上式和上段程序中,由于fosc=12MHZ,中断间隔时间为1ms,因此t0的机器周期数为1000。由于第1条指令到第14条指令的指令周期的机器周期数之和为13,因此,t1为13个机器周期。CPU虽在执行第一条指令CLR TRi 后停止定时器计数,但在TLi、THi中分别保存了t2的低位数据和高位数据。

4 结束语

由于本文介绍的误差补偿方法能对定时器溢出中断与CPU响应中断的非固定性时间误差进行有效补偿,因此,该方法对于提高高频控制系统实时控制精度和扩大单片机应用范围都有较高的实用价值。


相关文章

  • 四足机器人的设计制作与实现
  • 文章编号:1008-0570(2011)09-0099-03 嵌入式与SOC 四足机器人的设计制作与实现 DesignAndImplementationofTheQuadrupedRobotics (上海理工大学) 宫赤坤张智斌谷根王慧 G ...查看


  • 舵机驱动原理
  • 舵机驱动原理 1.舵机简介 2.舵机的组成 3.舵机工作原理 4.舵机选购 5.舵机控制原理及编程方法 6.实验室用舵机Futaba S3003使用说明 7.程序举例 1 概述 舵机也叫伺服电机,最早用于船舶上实现其转向功能,由于可以通过程 ...查看


  • 机器人舵机说明
  • 机器人舵机说明 一.舵机简介 舵机,顾名思义,大海航行靠舵手,舵机早期是应用在航模中控制方向的,在航空模型中,飞行器的飞行姿态是通过调整发动机和各个控制多面来实现的,后来有人发现这种机器的体积小.重量轻.扭矩大.精度高,由于具备了这样的优点 ...查看


  • 国内无人直升机研究情况简介
  • 国内无人直升机研究情况简介 1."海鸥"无人驾驶直升机 1993年9月29日,中国第一架共轴式双旋翼无人驾驶直升机"海鸥"号首飞成功,标志着我国已经攻破了相应的一系列技术难关.据报道,"海鸥 ...查看


  • 仿生六足机器人中期报告
  • 编号: 哈尔滨工业大学 大一年度项目中期检查报告 项目名称: 仿生六足机器人 项目负责人: 学号 联系电话: 电子邮箱: 院系及专业: 机电工程学院 指导教师: 职称: 联系电话: 电子邮箱: 院系及专业: 机电工程学院 哈尔滨工业大学基础 ...查看


  • 机械臂的控制论文
  • 学校代码 学号 本科学年论文(设计) 学院.系 专业名称 年 级 学生姓名 指导教师 20 年9月日 目录 摘要 ............................................................... ...查看


  • 多路舵机控制器设计
  • 基于AT89C2051的多路舵机控制器设计 摘要 舵机是机器人.机电系统和航模的重要执行机构.舵机控制器为舵机提供必要的能源和控制信号.本文提出一种以外部中断计数为基础的PWM 波形实现方法.该方法具有简单方便,成本低,可实现多路独立PWM ...查看


  • 基于激光传感器的智能车循迹系统
  • 装 订 线 河北大学工商学院 本科生毕业论文(设计) 题目: 学 部 信息科学与工程学部 学科门类 工学 专 业 电气工程及自动化 学 号 姓 名 指导教师 2013年5月16日 基于激光传感器的智能车循迹系统 摘 要 智能汽车是未来汽车发 ...查看


  • 飞思卡尔-智能车入门
  • 从外观上看,智能车系统主要表现为由一系列的硬件组成,包括组成车体的底盘.轮胎.舵机装置.马达装置.道路检测装置.测速装置和控制电路板等.硬件是智能车系统的基础,没有一个好的硬件平台,智能车就无法运行.而软件部分则是整个智能车系统的灵魂,软件 ...查看


热门内容