51经验.docx
《51经验.docx》由会员分享,可在线阅读,更多相关《51经验.docx(14页珍藏版)》请在冰点文库上搜索。
51经验
Keilc51的MemoryModel说明[三种Model的选择对编译的影响]
MemoryModel:
用鼠标点击MemoryModel的下拉箭头,会有3个选项:
Small:
变量存储在内部ram里;
small模式下,再入函数的堆栈是设在idata中的
Compact:
变量存储在外部ram里,使用页8位间接寻址;
compact模式下,再入函数堆栈是设在pdata中的
Large:
变量存储在外部Ram里,使用16位间接寻址;
我们一般使用Small来存储变量,就是说单片机优先把变量存储在内部ram里,如果内部ram不够了,才会存到外部去。
Compact的方式要自己通过程序来指定页的高位地址,编程比较复杂,如果外部ram很少,只有256个字节,那么对该256个字节的读取就比较快,用MOVX@Ri,A或MOVXA,@Ri指令。
如果超过256字节,那么要不断地进行切换的话,就比较麻烦。
Compact模式适用于比较少的外部ram的情况。
Large模式,是指变量会优先分配到外部ram里,用MOVXA,@DPTR或MOVX@DPTR,A来读取。
要注意的是,3种存储方式都支持内部256字节和外部64k字节的ram。
区别是变量的优先(或默认)存储在哪里的区别。
除非你不想把变量存储在内部ram,才使用后面的Compact,Large模式。
因为变量存储在内部ram里,运算速度比存储在外部ram要快的多,大部分的应用都是选择Small的模式。
使用Small的模式:
也不是说变量就不可以存储在外部,一样可以存储在外部,只是你要指定,比如:
unsignedcharxdataa;那么变量a就存储在外部的ram。
unsignedchara;变量存储在内部ram。
使用Large的模式:
unsignedcharxdataa;那么变量a就存储在外部的ram。
unsignedchara;变量存储在外部ram。
这就是区别,就是说这几个选项只是影响没有特别指定变量的存储空间的时候,默认存储在哪里,比如上面的变量定义unsignedchara。
////////////////////////////////////////////////////////////////////////////////////////
如果在变量声明时未声明变量的存储器类型,则该变量的存储器类型,由程序的存储模式来决定。
小模式(smallmodel):
默认data区
紧凑模式(compactmodel):
默认pdata区
大模式(largemodel):
默认xdata区
C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问)
C51就是c语言for51单片机,这里边还是有很多不同的,在c语言里运算量相信都知道那叫一个简单,直接int,float就哦了C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问),当然这里也可以直接int,float,但是他们还是有不同的,这里就介绍一下运算量中的不同!
C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问),相同的我就直接跳过~(果断不说了,不同的对于以后c语言开发51单片机还是相当有用的,慢慢的就会体会到了~~~~~C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问),尤其是特殊功能寄存器变量、位变量、还有绝对地址的访问!
C51的运算量(只说重点~):
C51中的运算量主要是常量和变量。
1、常量
常量是指在程序执行过程中不能改变的量。
在C51中支持整型常量、浮点型常量、字符型常量和字符串型常量。
1)整型常量
2)浮点型常量
3)字符型常量
4)字符串型常量
2、变量
变量就是在程序运行过程中可以改变的量呗。
一个变量有两部分组成:
变量名和变量值。
每个变量都有一个变量名,在存储器中占用一定的存储单元,变量的数据类型不同,占用的存储单元数就不同。
在存储单元中存放的内容就是变量值。
1)数据类型说明符
在定义变量时必须通过数据类型说明符来指明变量的数据类型,指明变量在存储器中占用的字节数。
可以使基本数据类型说明符,也可以是组合数据类型说明符,还可以是typedef或者#define定义的类型别名(这里一定要注意typedef一般用来定义别名!
尽量不要用#define啊~~我就不解释了C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问),太专业了~~不过用宏定义就一定要用#define)
例如:
typedefunsignedcharuchar;//这个是有;的
typedefunsignedintuint;
或者:
#defineucharunsignedchar//这个就没有;而且它们两个定义相反
#defineuintunsignedint
2)变量名
变量名有两种:
普通变量和指针变量。
他们的区别是指针变量名前面带“*”号。
3)存储种类
存储种类是指变量在程序执行过程中的作用范围。
C51变量的存储种类有4种,分别是:
自动(auto)、外部(extern)、静态(static)和存储器(register)。
a、auto
当定义它的函数体或者复合语句执行时,C51才为该变量分配内存空间,结束时占用的内存空间释放。
自动变量一般分配在内存的堆栈空间中。
定义变量时,如果缺省存储种类,则默认为此。
b、extern
被定以后分配固定的内存空间,在程序整个执行时间内都有效,知道程序结束时才释放。
c、static
使用static定义的变量成为外部变量,可分为内部静态变量和外部静态变量。
在函数体内部定义的静态变量为内部静态变量,它在对应的函数体内有效,一直存在,但在函数体外不可见。
这样不仅使变量在定义它的函数体外可以被保护,还可以实现当离开函数体时值不被改变。
外部静态变量是在函数体外定义的静态变量,它在程序中一直存在,但在定义的范围之外是不可见的。
如在多文件或者多模块处理中(这点很重要,以后会用到很多,尤其是多模块,写大程序必须具备的),外部静态变量只在文件内部或者模块内部有效。
d、register
它定义的变量存放在CPU内部的寄存器中,处理速度快,但是数目有限。
4)存储器类型
存储器类型用来指明变量所处的单片机的存储区域情况。
类型如下:
data:
直接寻址的片内RAM低128B,访问速度快
bdata:
片内RAM的可位寻址区(20H~2FH),允许字节和位混合访问
idata:
间接寻址访问的片内RAM,允许访问全部片内RAM
pdata:
用Ri简洁访问的片外RAM低256B
xdata:
用DPTR间接访问的片外RAM,允许访问全部64KB片外RAM
code:
程序存储器ROM64KB
注意:
定义变量时可以省略“存储类型”,省略时C51编译器将按存储模式默认存储器类型。
具体的存储情况啊~~一会你就知道了,继续往下看~~哈C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问)
例如:
chardatavar1;//在片内RAM低128B定义用直接寻址方式访问的自足型变量var1
unsignedcharbdatavar2;//在片内RAM位寻址区(20H~2FH)单元定义可字节处理和位处理的无符号字符型变量var2
5)特殊功能寄存器变量
在51单片机中有很多特殊功能寄存器(不过这些有些东西还是不需要我们来关心的~~~因为在调用#include"reg52.h"的时候里面都给你整好了C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问)),通过这些特殊功能寄存器可以控制51单片机的定时器、计数器、串口、I/0及其他功能部件(这里很重要的~~~~~~),没一个特殊功能寄存器再片内RAM中都对应一个字节单元或者两个字节单元。
在C51中,允许用户对这些特殊功能寄存器进行访问,但是访问时需要通过sfr或者sfr16类型说明符进行定义,定义是需要指明他们所对应的片内RAM单元的地址。
(你过关不用担心,直接调用#include"reg52.h"就哦了~)
例如:
sfrPSW=0xd0;
sfrSCON=0x98;
sfr16DPTR=0x82;
6)位变量
在C51中,允许用户通过位类型符定义位变量。
位类型符有两个:
bit和sbit。
可以定义两种位变量。
a、bit型位变量
在格式中可以加上各种修饰,但是要注意存储器类型只能是bdata、data、idata,只能是片内RAM的可位寻址区,严格来说只能是bdata。
例如:
bitbdataa1;
b、sbit型位变量
sbit位类型符用于定义在可位寻址字节或者特殊功能寄存器中的位,定义时需要指明其位地址,可以使位直接地址,可以是可位寻址变量带位号,也可以是特殊功能寄存器名带位号。
例如(这些东西都在#include"reg52.h"中):
sbitOV=0xd2;
sbitCY=0xd7;
unsignedcharbdataflag;
sbitflag_0=flag^0;//字节地址与位号之间、特殊功能寄存器与位号之间一般用“^”作间隔
sfrP1=x090;
sbitP1_1=P1^1;
3、存储模式(个人感觉真的用不到这些东东了,因为你丫的要是嫌小可以换个大的,而且还相当的便宜~~~~C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问),我以前试过扩展一个RAM和ROM,擦C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问)不成啊~~)
C51编译器支持3种存储模式:
SMALL模式、COMPACT模式和LARGE模式。
不同的存储模式对变量默认的存储器类型不一样。
1)SMALL模式
SMALL模式成为小编译模式,在SMALL模式下,编译时函数参数以及变量被默认在片内RAM中,存储类型为data。
2)COMPACT模式
COMPACT模式称为紧凑编译模式,在COMPACT模式下,编译时函数参数和变量被默认在片外RAM的低256B空间,存储类型为pdata。
3)LARGE模式
LARGE模式称为大编译模式,在LARGE模式下,编译时函数参数和变量被默认在片外RAM的64KB空间了,存储器类型为xdata。
例如:
#pragmasmall//变量的存储模式为SMALL
chark1;//存储类型为data
intxdatam1;//存储类型xdata
#pragmacompact//变量的存储模式为COMPACT
chark2;
intxdatam2;
intfunc1(intx1,inty1)large//函数的存储模式为LARGE
{
return(x1+y1);
}
intfunc2(intx2,inty2)//编译的存储模式隐含为SMALL,没有指明模式,隐含SMALL
{
return(x2-y2);
}
4、绝对地址的访问(这里才是重点中的重点啊~~~)
在C51中,可以通过变量的形势访问51单片机的存储器,也可以通过绝对地址来访问存储器。
三种方法:
1)使用C51运行库中预定义宏(就是调用#include"absacc.h")
C51编译器提供了一组宏定义来对51单片机的code、data、pdata和xdata空间进行绝对寻址!
规定只能以无符号数方式访问,定义了8个宏定义,其函数原型如下:
#defineCBYTE((unsignedcharvolatile*)0x50000L)//CBYTE以字节形势对code区寻址
#defineDBYTE((unsignedcharvolatile*)0x40000L)//data区
#definePBYTE((unsignedcharvolatile*)0x30000L)//pdata区
#defineXBYTE((unsignedcharvolatile*)0x20000L)//xdata区
#defineCWORD(unsignedintvolatile*)0x50000L)//以字形式对code区寻址
#defineDWORD(unsignedintvolatile*)0x40000L)
#definePWORD(unsignedintvolatile*)0x30000L)
#defineXWORD(unsignedintvolstile*)0x20000L)
例如:
#include"absacc.h"
#include"reg52.h"
typedefunsignedcharuchar;
typedefunsignedintuint;
voidmain()
{
ucharvar1;
uintvar2;
var1=XBYTE[0x0005];//XBYTE[0x0005]访问片外RAM的0005字节单元
var2=XWORD[0x0002];//XWORD[0x0002]访问片外RAM的0002字单元
.
.
.
while
(1);
}
2)通过指针访问
采用指针的访问的方法,可以在C51程序中对任意指定的存储器单元进行访问。
typedefunsignedcharuchar;
typedefunsignedintuint;
voidfunc()
{
uchardatavar1;
ucharpdata*dp1;//定义一个指向pdata区的指针dp1
uintxdata*dp2;//定义一个指向xdata区的指针dp2,为uint型
uchardata*dp3;//定义一个指向data区的指针dp3,为char型
dp1=0x30;//dp1指针赋值,指向pdata区的30H单元
dp2=0x1000;//dp2指针赋值(uint型),指向xdata区的1000H单元
*dp1=0xff;//将数据0xff送到片外RAM30H单元
*dp2=0x1234;//将数据0x1234(由于是uint型,你懂得~~~),送到片外RAM1000H单元
dp3=&var1;//dp3指针指向data区的var1变量
*dp3=0x20;//给变量var1赋值0x20
}
3)使用C51扩展关键字_at_(这个用的最多了~~~C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问))
总算完了,我真的要累死了~~~~擦擦擦擦啊
一般格式:
[存储类型]数据类型说明变量名_at_地址常量;
其中,存储类型为data、bdata、idata、pdata、xdata等C51能识别的数据类型,如果省略,则会按照存储模式规定的默认存储类型确定变量的存储区域(C51—运算量(重点:
特殊功能寄存器变量、位变量、绝对地址的访问)这里又用到上边的了);数据类型为C51支持的数据类型;地址常数用于指定变量的绝对地址,必须位于有效的存储器空间之内;使用_at_定义的变量必须为全局变量。
例如:
typedefunsignedcharuchar;
typedefunsignedintuint;
dataucharx1_at_0x40;//在data区中定义字节变量x1,地址为0x40H,这里是uchar
xdatauintx2_at_0x2000;//在xdata区中定义字变量x2,它的地址为0x2000H,这里是uint
步进电机、步进电机驱动器常见问题解答
1.什么是步进电机,什么是步进电机驱动器?
步进电机是一种作为控制用的特种电机,它的旋转是以固定的角度(称为“步距角”)一步一步运行的,其特点是没有积累误差,所以广泛应用于各种开环控制。
步进电机的运行要有一电子装置进行驱动,这种装置就是步进电机驱动器,它是把控制系统发出的脉冲信号转化为步进电机的角位移,或者说:
控制系统每发一个脉冲信号,通过驱动器就使步进电机旋转一步距角。
所以步进电机的转速与脉冲信号的频率成正比。
所以,控制步进脉冲信号的频率,可以对电机精确调速;控制步进脉冲的个数,可以对电机精确定位目的。
2.什么是驱动器的细分?
什么是运行拍数?
步距角如何计算?
要了解“细分”,先要弄清“步距角”这个概念:
它表示控制系统每发一个步进脉冲信号,电机所转动的角度。
电机出厂时给出了一个步距角的值,如86BYG250A型电机给出的值为0.9°/1.8°(表示半步工作时为0.9°、整步工作时为1.8°),这个步距角可以称之为‘电机固有步距角’,它不一定是电机实际工作时的真正步距角,真正的步距角和驱动器有关,参见下表(以86BYG250A电机为例):
电机固有步距角 运行拍数 细分数 电机运行时的真正步距角
0.9°/1.8° 8 驱动器工作在2细分即半步状态 0.9°
0.9°/1.8° 20 细分驱动器工作在5细分状态 0.36°
0.9°/1.8° 40 细分驱动器工作在10细分状态 0.18°
0.9°/1.8° 80 细分驱动器工作在20细分状态 0.09°
0.9°/1.8° 160 细分驱动器工作在40细分状态 0.045°
简单地讲,细分数就是指电机运行时的真正步距角是固有步距角(整步)的几分指一。
从上表可以看出:
驱动器工作在10细分状态时,其步距角只为‘电机固有步距角’的十分之一,也就是说:
当驱动器工作在不细分的整步状态时,控制系统每发一个步进脉冲,电机转动1.8°;而用细分驱动器工作在10细分状态时,电机只转动了0.18°,这就是细分的基本概念。
更为准确地描述驱动器细分特性的是运行拍数,运行拍数指步进电机运行时每转一个齿距所需的脉冲数。
86BYG250A电机有50个齿,如果运行拍数设置为160,那么步进电机旋转一圈总共需要50×160=8000步;对应步距角为360°÷8000=0.045°。
请注意,如果运行拍数设为30,按上表对应关系细分数为7.5,不是一个整数。
细分功能完全是由驱动器靠精确控制电机的相电流所产生的,与电机无关。
3.驱动器细分有什么优点?
其一,完全消除了电机的低频振荡。
低频振荡是步进电机(尤其是反应式电机)的固有特性,而细分是消除它的唯一途径,如果您的步进电机有时要在共振区工作(如走圆弧),选择细分驱动器是唯一的选择。
其二,提高了电机的输出转矩。
细分比不细分,输出转矩对各种电机都有不同程度的提升。
其三,提高了电机的分辨率。
减小了步距角,提高了步距的均匀度。
4.反应式步进电机与混合式步进电机的区别?
首先,在结构和材料上不同,反应式电机不象混合式电机那样内部具有永久磁性材料,混合式电机具有一定的自锁转矩。
其次,在运行性能上有差别,混合式电机运行时相对较平稳,输出力矩相对较大,运行声音小。
再次,两种电机在价格上有差别,反应式电机比混合式电机相对便宜,但并不明显。
5.步进电机的运行方向和我要求的相反,怎样调整?
一种方法是改变控制系统的方向信号。
另一种方法是通过调整电机的接线来改变方向,具体如下表
电机接线方式原来接线序列 换向后接线序列
两相四线 A,A',B,B' A',A,B,B'或者A,A',B',B
三相三线 A,B,C B,A,C或者A,C,B
三相六线 A,A',B,B',C,C' B,B',A,A',C,C'或者A,A',C,C',B,B'
五相五线 A,B,C,D,E E,D,C,B,A
7.电机的噪音特别大;而且没有力,电机本身在振动?
如遇到这种情况时,是因为步进电机工作在振荡区,一般改变输入信号频率CP就可以解决此问题。
8.电机在低速运行时正常,当是频率略高一点就出现堵转现象?
遇到这种情况多是因为加在驱动器的电源电压不够高引起的;把输入电压加高一些,就可以解决此问题,注意不能高于驱动器电源端标注的最高电压;否则会引起驱动器烧毁.
9.驱动器通电以后,电机在抖动,不能运转?
遇到这种情况时,首先检查电机的绕组与驱动器连接有没有接错;如没有接错再检查输入频率CP是否太高;是否升降频设计不合理,参考升降频设计;以上原因都不是,可能是驱动器烧毁,请与我们联系。
10.升降速设计
步进电机速度控制是靠输入的脉冲信号的变化来改变的,从理论上说,只需给驱动器脉冲信号即可,每给驱动器一个脉冲(CP),步进电机就旋转一个步距角(细分时为一个细分步距角)但是实际上,如果脉冲CP信号变化太快,步进电机由于惯性将跟随不上电信号的变化,这时会产生堵转和丢步现象,所以步进电机在启动时,必须有升速过程,在停止时必须有降速过程。
一般来说升速和降速规律相同,以下为升速为例介绍:
升速过程由突跳频率加升速曲线组成(降速过程反之)。
突跳频率是指步进电机在静止状态时突然施加的脉冲启动频率,此频率不可太大,否则也会产生堵转和丢步。
升降速曲线一般为指数曲线或经过修调的指数曲线,当然也可采用直线或正弦曲线等。
用户需根据自己的负载选择合适的突跳频率和升降速曲线,找到一条理想的曲线并不容易,一般需要多次‘试机’才行。
指数曲线在实际软件编程中比较麻烦,一般事先算好时间常数存贮在计算机存贮器内,工作过程中直接选取。
延时方法
实现延时通常有两种方法:
一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。