51单片机控制的步进电机C语言程序

合集下载

单片机控制步进电机程序设计

单片机控制步进电机程序设计

单片机控制步进电机程序设计1.引言步进电机是一种常用的电机类型,其特点是精度高、稳定性好、速度可调。

在很多自动控制系统中,步进电机被广泛应用于位置控制、定位、打印机等领域。

本文将介绍如何使用单片机来控制步进电机,并给出一个简单的步进电机程序设计示例。

2.步进电机简介步进电机是一种将电脉冲信号转换为角位移或线位移的电机。

其优点包括:-分辨率高:每个步进电机的旋转角度可以非常小,可实现较高的位置精度。

-可控制性强:通过控制电压脉冲的频率和顺序,可以精确控制步进电机的转动方向和步数。

-响应快速:步进电机的响应速度较快,可达数千转每分钟。

3.单片机选型与连接在实现步进电机的控制过程中,我们选择了一款适用于步进电机控制的单片机。

这款单片机具有以下特点:-高效的运算能力和大容量存储空间,适用于复杂的控制算法。

-可编程性强,支持多种开发环境,开发过程相对简便。

-丰富的外设接口,方便与步进电机的连接和控制。

连接单片机与步进电机的基本电路如下所示:步进电机驱动引脚1--单片机引脚A步进电机驱动引脚2--单片机引脚B步进电机驱动引脚3--单片机引脚C步进电机驱动引脚4--单片机引脚D4.步进电机控制原理步进电机控制原理基于对步进电机驱动引脚输入电压脉冲信号的控制。

针对不同的步进电机类型,控制方式可以有所不同,常见的控制方式包括全步进控制和半步进控制。

4.1全步进控制全步进控制方式是将电流依次施加到步进电机的每个驱动相,使其按照一定顺序正转或反转。

控制步骤如下:1.给引脚A和引脚B施加电压,使电机顺时针转动一个步距。

2.给引脚B和引脚C施加电压,使电机顺时针转动一个步距。

3.给引脚C和引脚D施加电压,使电机顺时针转动一个步距。

4.给引脚D和引脚A施加电压,使电机顺时针转动一个步距。

4.2半步进控制半步进控制方式是在全步进控制的基础上,通过控制相邻两个相的电流互补关系,实现更细微的步距调整。

控制步骤如下:1.给引脚A施加电压,使电机顺时针转动半个步距。

单片机控制步进电机系统(C语言源代码)

单片机控制步进电机系统(C语言源代码)

题目:单片机控制步进电机系统摘要很多工业控制设备对位移和角度的控制精度要求较高, 一般电机很难实现, 而步进电机可精确实现所设定的角度和转数。

本设计主要是运用51 单片机控制六线4相步进电机系统, 由单片机产生驱动脉冲信号, 控制步进电机以一定的转速向某一方向产生一定的转动角度。

同时能够利用单片机实现电机的正、反转及速度控制,并能在数码管上显示出相应的速度。

本文中给出了该系统设计的硬件电路,软件设计,人机交互等。

并对各个功能模块进行了详细的说明。

主要内容包括以下几个方面:单片机控制步进电机的一般原理。

电机驱动及控制的实现。

控制系统整体设计以及模块划分说明。

原理图。

代码。

关键词:单片机;步进电机;系统;驱动AbstractMany Industrial control equipment have a highly requirement in displacement and angle with control accuracy, the most motor can't carry out .but the step motor can carry out the displacement and angle that you enactmented in accuracy. This design mainly used SCM to control step motor system.The step motor is formed six lines and four phasic.Through SCM generate the drive pulse signal.Control stepper motor through a certain speed in a direction to get a certain degree of rotation angle.At the same time, It can use SCM to realization of the motor is , reverse and speed control. and showed the speed in the digital tube.In this paper, given the design of the system hardware circuit,software design, human-computer interaction and so on.and it given the details description of each functional module.the main contents include the following:(1) The general principles of signal_chip controlling step motor.(2) The realization of motor driving and controlling(3) Control system overall design and description module division(4) Schematic Diagram(5) CodeKey Words:SCM; stepper motor; system; drive目录引言41 单片机控制步进电机的一般原理41.1 步进电机41.1.1 步进电机介绍41.1.2 步进电机分类51.1.3 技术指标51.1.4 步进电机工作原理51.2 单片机72 步进电机驱动实现82.1简介82.2驱动选择83 系统硬件设计93. 1 单片机控制电机93.2 键盘93.3 显示部分10程序流程图11总结12致谢13参考文献13附录13C代码13引言目前,在工业控制生产以及仪器上应用十分广泛。

c语言实现单片机控制步进电机加减速源程序

c语言实现单片机控制步进电机加减速源程序

C 语言实现单片机控制步进电机加减速源程序1. 引言在现代工业控制系统中,步进电机作为一种常见的执行元件,广泛应用于各种自动化设备中。

而作为一种常见的嵌入式软件开发语言,C 语言在单片机控制步进电机的加减速过程中具有重要的作用。

本文将从单片机控制步进电机的加减速原理入手,结合 C 语言的编程技巧,介绍如何实现单片机控制步进电机的加减速源程序。

2. 单片机控制步进电机的加减速原理步进电机是一种能够精确控制角度的电机,它通过控制每个步骤的脉冲数来实现旋转。

在单片机控制步进电机的加减速过程中,需要考虑步进电机的加速阶段、匀速阶段和减速阶段。

在加速阶段,需要逐渐增加脉冲的频率,使步进电机的转速逐渐增加;在匀速阶段,需要保持恒定的脉冲频率,使步进电机以匀速旋转;在减速阶段,需要逐渐减小脉冲的频率,使步进电机的转速逐渐减小。

这一过程需要通过单片机的定时器和输出控制来实现。

3. C 语言实现步进电机加减速的源程序在 C 语言中,可以通过操作单片机的 GPIO 来控制步进电机的旋转。

在编写源程序时,需要使用单片机的定时器模块来生成脉冲信号,以控制步进电机的旋转角度和速度。

以下是一个简单的 C 语言源程序,用于实现步进电机的加减速控制:```c#include <reg52.h>void main() {// 初始化定时器// 设置脉冲频率,控制步进电机的加减速过程// 控制步进电机的方向// 控制步进电机的启停}```4. 总结与回顾通过本文的介绍,我们了解了单片机控制步进电机的加减速原理和 C 语言实现步进电机加减速源程序的基本思路。

掌握这些知识之后,我们可以更灵活地应用在实际的嵌入式系统开发中。

在实际项目中,我们还可以根据具体的步进电机型号和控制要求,进一步优化 C 语言源程序,实现更加精准和稳定的步进电机控制。

希望本文能为读者在单片机控制步进电机方面的学习和应用提供一定的帮助。

5. 个人观点与理解在我看来,掌握 C 语言实现单片机控制步进电机加减速源程序的技术是非常重要的。

[整理]51单片机驱动步进电机电路及程序(1)

[整理]51单片机驱动步进电机电路及程序(1)

在这里介绍一下用51单片机驱动步进电机的方法。

这款步进电机的驱动电压12V,步进角为 7.5度 . 一圈 360 度 , 需要 48 个脉冲完成!!!该步进电机有6根引线,排列次序如下:1:红色、2:红色、3:橙色、4:棕色、 5:黄色、6:黑色。

采用51驱动ULN2003的方法进行驱动。

ULN2003的驱动直接用单片机系统的5V电压,可能力矩不是很大,大家可自行加大驱动电压到12V。

;******************************************************************** *************;**************************** 步进电机的驱动***************************************; DESIGN BY BENLADN911 FOSC = 12MHz 2005.05.19;---------------------------------------------------------------------------------; 步进电机的驱动信号必须为脉冲信号!!! 转动的速度和脉冲的频率成正比!!! ; 本步进电机步进角为 7.5度 . 一圈 360 度 , 需要 48 个脉冲完成!!!;---------------------------------------------------------------------------------; A组线圈对应 P2.4; B组线圈对应 P2.5; C组线圈对应 P2.6; D组线圈对应 P2.7; 正转次序: AB组--BC组--CD组--DA组 (即一个脉冲,正转 7.5 度);----------------------------------------------------------------------------------;---------------------------- 正转--------------------------ORG 0000HLJMP MAINORG 0100HMAIN:MOV R3,#144 正转 3 圈共 144 脉冲START:MOV R0,#00HSTART1:MOV P2,#00HMOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START 对 A 的判断,当 A = 0 时则转到 STARTMOV P2,ALCALL DELAYINC R0DJNZ R3,START1MOV P2,#00HLCALL DELAY1;-----------------------------反转------------------------ MOV R3,#144 反转一圈共 144 个脉冲START2:MOV P2,#00HMOV R0,#05START3:MOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START2MOV P2,ACALL DELAYINC R0DJNZ R3,START3MOV P2,#00HLCALL DELAY1LJMP MAINDELAY: MOV R7,#40 步进电机的转速M3: MOV R6,#248DJNZ R6,$DJNZ R7,M3RETDELAY1: MOV R4,#20 2S 延时子程序DEL2: MOV R3,#200DEL3: MOV R2,#250DJNZ R2,$DJNZ R3,DEL3DJNZ R4,DEL2RETTABLE:DB 30H,60H,0C0H,90H 正转表DB 00 正转结束DB 30H,90H,0C0H,60H 反转表DB 00 反转结束END。

51单片机驱动步进电机的方法(详解)

51单片机驱动步进电机的方法(详解)
系统电源:
1
CHD
v?c
31门
33
37
30
35
34
33
32
1
2
3
4
5

ICJ
ATfiSCSl
RST
PSEN
XI
XZ
EA
ALE
CADI) PdO
(AS)P20
(ADI,)PD 1
CA9)P2 1
CAD2)PD.a
CA10)P22
(AD3)PD.3
(AU)P2 3
(AI>4)PO 4
CA1Z)P3 4
CAD5)P0.5
51单片机驱动步进电机的方法
2019.02
这款步进电机的驱动电压12V,步进角为7.5度.一圈360度,需要48个脉冲完成!!!
I^H
该步进电机有
6根引线,排列次序如下:
1:红色、2:红色、
3:橙色、4:棕色、5:黄色、
6:黑色。
米用51驱动
ULN2003的方法进行驱动。
I
R1
I OK
C3 lOuF
P37而
9
X2
12M
X2
^_JOp_J 30p
GND
IC2

3
37
3
2E
4
1D
11
30近
22
23
25
_5_6Zj
3

LB
IC
2B
2C
3B
3C
斗B
AC
5B
5C
6B
6C
7B
7C
GND
VCC
1
16
<

基于51单片机的步进电机调速系统(含完整代码)

基于51单片机的步进电机调速系统(含完整代码)

课程设计报告设计题目:遥控小车——基于51单片机的步进电机调速系统学院:专业:班级:学号:姓名:电子邮件:时间:成绩:指导教师:华南农业大学理学院应用物理系课程设计(报告)任务书学生姓名指导教师职称学生学号专业电子信息科学与技术题目基于51单片机的步进电机调速系统(遥控小车)任务与要求1. 设计并制作电路,利用单片计控制步进电机运转。

2. 通过键盘可以不间断地设定改变电机的转速、转向。

3. 利用显示器实时显示转速等参数。

4. 扩展功能:可设定转动步数。

开始日期2014 年3 月完成日期2014 年3 月1引言步进电机是一种将电脉冲转化为角位移的执行机构。

目前,步进机已经广泛应用于领域,例如工业生产中的机械臂的控制,照明装置和监控摄像机转动等。

步进机在装置转动、精确位移方面有很重大的作用。

本系统是基于STC89C51 单片机的遥控小车。

采用STC89C51单片机作为控制核心,通过ULN2003A驱动步进机(28BYJ-48)转动,由按键和显示屏1602组成人机交互模块,同时通过315M无线发射和接收模块向单片机输入控制信号,将整个系统固定于简易小车上,最终实现小车测试和远程遥控功能。

基本达到预定的设计要求以及功能的扩展。

2系统的设计与理论分析2.1系统总体设计2.2理论分析本设计分为两种工作模式:测试模式、遥控模式。

在电路板上有一个带锁的开关进行设置。

测试模式工作时,通过控制小车上的按键进行加速、减速、反转、设置、步数增、步数减等按键,单片机扫描按键,通过软件控制液晶模块显示对应的转速、设置的速度和步数,同时控制步进机模块进行相应的转动。

步进机的是由ULN2003A达林顿管驱动,由单片机控制输入脉冲的频率来控制步进机的转速,单片机是通过程序查表对4个I/O口输出脉冲,本次设计采用的是两相四线减速步进机,步进角为5.625°,减速比为64:1,程序采用的是8拍查表,具有较好的扭矩。

遥控模式工作时,遥控部分五个按键分别输入前、后、左、右、暂停,单片机扫描按键,通过无线发射模块发射串行编码,小车的无线接收模块接收对应的编码,送至单片机进行解码,从而控制液晶模块的显示和步进机模块的工作,进而完成功能。

完整的单片机控制步进电机程序

完整的单片机控制步进电机程序

#include "reg52.h"#include "INTRINS.H"#include <absacc.h>#include <math.h>#define uint unsigned int#define uchar unsigned charvoid check_addr(void); /* 地址核对*/uchar code slave_addr[4]={00, 01, 02, 255}; /* 从机地址*/uchar idata T0low, T0high,common_count,input_order,cmd_in_permit,interval; ucharsent_ok,speed_change,start_up,start_end,address_true,i;uint y1;uint codeadd[100]={60006,62771,63693,64154,64430,64614,64746,64845,64922,64983,65033,65075,651 11,65141,65167,65190,65211,65229,65245,65260,65273,65285,65296,65306,65315,65323,65331 , 65339,65345,65352,65358,65363,65368,65373,65378,65382,65387,65390,65394,65398,65401,6 5404,65407,65410,65413,65416,65418,65421,65423,65425,65428,65430,65432,65434,65435,654 37,65439,65441,65442,65444,65445,65447,65448,65450,65451,65452,65453,65455,65456,65457 , 65458,65459,65460,65461,65462,65463,65464,65465,65466,65467,65468,65469,65469,65470,6 5471,65472,65472,65473,65474,65475,65475,65476,65477,65477,65478,65478,65479,65480,654 80,65481};sbit P2_0=P2A0; sbit P2_2=P2A2; sbit P1_0=P1A0; sbit WD=P1A7; /* 作输入步进电机的脉冲信号发送口*//* 作输入步进电机的旋转方向信号发送口*//*作串口输出信号的使能口,P1_0=0时接通串口,输出信号*/ /* 看门狗*/main(){P2_0=0;P2_2=0; /* 步进电机的旋转方向待试验后确定*/P1_0=1; /* 开机时需要关断,串口发送功能,需要时再接通*/ WD=1; /* 看门狗先为1,电平翻转为喂狗*/ i=0;common_count=0; cmd_in_permit=0;input_order=0;interval=0; address_true=1;speed_change=0;start_up=0;start_end=0;sent_ok=0; // 允许发送EA=1; /* 开放总中断*/ TMOD=0x21;TH1 = 0xFD; TL1 = 0xFD; SCON = 0xd0; PCON &= 0x00; SM2=1;TR1 = 1;ES=1; // 波特率9600// 设定串行口工作方式// 波特率不倍增// 启动定时器1T2MOD=00;T2CON=0x00;RCAP2H =0xEE; //赋T2 的预置值0xA600,25MS ,0xB800 ,20MS,0xCA00 ,15MS,0xDC00 ,10MS,0xEE00 ,5MSRCAP2L =0x00;TR2=1; //启动定时器ET2=1; //打开定时器2 中断do{if(address_true==1){ address_true=0; check_addr();} if(start_up==1&&start_end==0) //第一次启动{y1=add[common_count];T0high = (uchar)(y1>>8) ; /* 取y1 的高8 位*/T0low = (uchar)(y1&0x00ff); /*取y1的低8位*/TR0 = 1;ET0=1; /* 允许T/C0 中断*/start_end=1;}if(speed_change==1){ if(interval>=0&&interval<=0x63) {if(interval>common_count){common_count=common_count+1; }if(interval<common_count){common_count=common_count-1; }speed_change=0;} if(sent_ok==1){ sent_ok=0; P1_0=0; for(i=0;i<=20;i++) {_nop_();}TI=0; SBUF=T0high; while(TI==0);TI=0; TI=0; SBUF=T0low; while(TI==0);TI=0;P1_0=1; for(i=0;i<=20;i++) {_nop_();}SM2=1;}} while(1);}void timer0(void) interrupt 1 using 3{ P2_0=~P2_0; y1=add[common_count];T0high = (uchar)(y1>>8) ; /* 取y1 的高8 位*/ T0low = (uchar)(y1&0x00ff); /* 取y1 的低8 位*/ THO=TOhigh; /*高8 位TOhigh 送定时器0 的TH0*/ TL0=T0low; /*低8 位T0low 送定时器0 的TL0*/}void timer2(void) interrupt 5 using 2{TF2=0; /*T2 溢出中断需软件清0*/ speed_change=1; //速度可以改变标示,以便主程序处理WD=!WD; /*MAX813 喂狗*/}void inte_SERIAL() interrupt 4 using 1 /*串口0 中断服务子程序*/{uchar key_in ; key_in=0;if(RI){key_in=SBUF;RI=0;if (SM2==1){ if(key_in==slave_addr[2]){SM2=0; address_true=1;}}if ((SM2==0)&& (RB8==0)){ if(key_in==0xff){SM2=1;}if(key_in==0xfe){ /* 接收主机命令引导字节,准备接收主机命令*/ cmd_in_permit=1;} if(cmd_in_permit==1){ input_order=input_order+1;}if (input_order==2){ /* 接收主机命令,使从机开始调节电机*/ cmd_in_permit=0; input_order=0;/*interval 代表控制器发给电机的转速期望值*/ interval= key_in;sent_ok=1; if(start_up==0){start_up=1;}}}}}void check_addr(void){ /* 地址核对成功,发送从机地址给主机*/TB8=1;RB8=0;P1_0=0;for(i=0;i<=25;i++) {_nop_();}SBUF=slave_addr[2]; /* 发送地址核对成功,发送从机地址给主机*/ do{} while(TI==0); TI=0;P1_0=1;for(i=0;i<=25;i++) {_nop_();}TB8=0;。

步进电机控制程序(c语言51单片机)

步进电机控制程序(c语言51单片机)

// pri_dj = Pme );
if( i == set_pwm_width ) { P1 = 0xff; i = 0; one _round_flg = 0; while ( !one_round_flg & key_puse );}
if(!key_puse) { delay(4ms); if(!key_puse) break; }
while ( key_puse & key_clear ); delay ( 8ms );
if ( !key_clear ) { round_num = 0; display(); }
if ( !key_puse ) break; }
while( !key_puse ); delay(8ms);
while( !key_puse ); }
set_display_num(); for(i = 0; i < LEDLen ; i ++){
P0 = 0xf0; P0 = P0 | LEDBuf[i] ; if(i==0) led_1000 = 0; //P0^4 if(i==1) led_100 = 0; //P0^5 if(i==2) led_10 = 0; //P0^6 if(i==3) led_1 = 0; //P0^7
delay ( 1ms ); tmp = (~(P2 | 0xF0)); P2 = 0x7F; // 0111 1111
delay ( 1ms ); tmp = (~(P2 | 0xF0)) * 10 + tmp; set_round_num = set_round_num + tmp * 100; set_round_num = set_round_num * Chilun_Num;

51单片机驱动步进电机电路及程序

51单片机驱动步进电机电路及程序

相绕组通断,P1.1控制B相,P1.2
控制C相。
2021/8/5
13
以A相控制为例:
当 P1 . 0 输 出 为 1 , 发 光管不发光,因此光敏二极 管截止,使担负驱动任务的 达林顿管导通。A相绕组通电。
相反,当P1.0=0→发 光管发光→光敏管导通→达 林顿管截止→A相绕组不通 电。
2021/8/5
2021/8/511 NhomakorabeaSUB: SETB P3.0
SETB P3.0 ;保证输出高电平的时间>5μs
SETB P3.0
CLR P3.0
;变为低电平
MOV R7,30H
LOOP: NOP
;软件延时程序:
NOP
;基本延时(10μs×时间常数)
NOP
DJNZ R7,LOOP
RET
※时间常数事先可装入30H单元,改变30H单元的内容就可改
所以按照 A→AB→B→BC→C→CA→A
的顺序控制,电机将按顺时针方向旋转, 每步转动1.5°,即步距角=1.5°,
由于要经过6步才走完一个齿距 (6×1.5°=9°),所以叫三相六拍。
2021/8/5
7
如果要使步进电机反转,只要按
A→AC→C→CB→B→BA
顺序通电就行了。
结论:从上面两种运行方式可看出,错齿是促使步
进电机旋转的根本原因,当某相通电,相应的齿对
齐,迫使电机旋转一个步距角,未通电的各相的齿
出现了新的错位。改变通电的顺序和通电的相数,
可组合出其它的运行方式。
讨论:三项三拍和三项六拍运行方式,哪种定位
2021更/8/5精确?
8
三、步进电机有如下特点:
❖ 给步进脉冲电机就转,不给步进脉冲电机就不转; ❖ 步进脉冲频率高,步进电机转得快;步进脉冲频率

51单片机驱动步进电机电路及程序

51单片机驱动步进电机电路及程序

51单片机驱动步进电机电路及程序(总4页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--51单片机驱动步进电机电路及程序在这里介绍一下用51单片机驱动步进电机的方法。

这款步进电机的驱动电压12V,步进角为度 . 一圈 360 度 , 需要 48 个脉冲完成!!!该步进电机有6根引线,排列次序如下:1:红色、2:红色、3:橙色、4:棕色、5:黄色、6:黑色。

采用51驱动ULN2003的方法进行驱动。

ULN2003的驱动直接用单片机系统的5V电压,可能力矩不是很大,大家可自行加大驱动电压到12V。

;*********************************************************************************;********** ******************步进电机的驱动***************************************; DESIGN BY BENLADN911 FOSC = 12MHz ;---------------------------------------------------------------------------------; 步进电机的驱动信号必须为脉冲信号!!! 转动的速度和脉冲的频率成正比!!!; 本步进电机步进角为度 . 一圈 360 度 , 需要 48 个脉冲完成!!!;---------------------------------------------------------------------------------; A组线圈对应; B组线圈对应; C组线圈对应; D组线圈对应; 正转次序: AB组--BC组--CD组--DA组 (即一个脉冲,正转度);----------------------------------------------------------------------------------;----------------------------正转--------------------------ORG 0000HLJMP MAINORG 0100HMAIN:MOV R3,#144 正转 3 圈共 144 脉冲START:MOV R0,#00HSTART1:MOV P2,#00HMOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START 对 A 的判断,当 A = 0 时则转到STARTMOV P2,ALCALL DELAYINC R0DJNZ R3,START1MOV P2,#00HLCALL DELAY1;-----------------------------反转------------------------MOV R3,#144 反转一圈共 144 个脉冲START2:MOV P2,#00HMOV R0,#05START3:MOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START2 MOV P2,ACALL DELAYINC R0DJNZ R3,START3MOV P2,#00HLCALL DELAY1LJMP MAINDELAY: MOV R7,#40 步进电机的转速M3: MOV R6,#248DJNZ R6,$DJNZ R7,M3RETDELAY1: MOV R4,#20 2S 延时子程序DEL2: MOV R3,#200DEL3: MOV R2,#250DJNZ R2,$DJNZ R3,DEL3DJNZ R4,DEL2RETTABLE:DB 30H,60H,0C0H,90H 正转表DB 00 正转结束DB 30H,90H,0C0H,60H 反转表DB 00 反转结束END。

51单片机控制两相四线步进电机

51单片机控制两相四线步进电机

源程序如下:ENA EQU P1.0 ENB EQU P1.1IN1 EQU P1.2IN2 EQU P1.3IN3 EQU P1.4IN4 EQU P1.5 SWITCH EQU P3.3 FAST EQU P3.6 SLOW EQU P3.5CYCLENUM EQU 50H ;存放对应定时循环次数TEMP EQU 53H ;存放按键次数。

初值为5,每按加速叠加1,按减速递减MARK EQU 56H ;启动停止标识LEDBUF EQU 57HORG 0AJMP START;*****************检测是否开启启动电机键***************************START:MOV P0,#0 ;清显示SETB MARK ;预启动电机工作,标识为1MOV TEMP,#5 ;开始工作于5HzMOV CYCLENUM,#01H ;循环1次JNB SWITCH,NEXT ;按键按下?SJMP START ;没有返回继续检测NEXT:CALL DELAY ;消抖确认JNB SWITCH,MAIN ;再次确认按键,不为1说明按键按下SJMP START ;没有按下,继续检测;*****************开始运行电机***************************************MAIN:MOV A,TEMPMOV DPTR,#TAB4MOVC A,@A+DPTRMOV LEDBUF,A ;送显示CALL DISPLAYLOOP:JB MARK,WORK ;检测运行标识是否为1,为1则继续运行,为0则停止运行NOTWORK:CLR ENACLR ENBSJMP STARTWORK:MOV P1,#000010111B ;步进电机运行方式为两相四拍CALL TIMERCALL TESTSTOPMOV P1,#000011011B ;第二拍CALL TIMERCALL TESTSTOPMOV P1,#000101011B ;第三拍CALL TIMERCALL TESTSTOPMOV P1,#000100111B ;第四拍CALL TIMERCALL TESTSTOPCALL TESTKEYSJMP MAIN;***************************检测是否有按键按下************************TESTKEY:SETB FASTSETB SLOWNEXT1:JNB FAST,YES2NEXT2:JNB SLOW,YES3SJMP RETURN ;都没有键按下,则返回YES2:MOV A,TEMP ;FAST按下,若此时temp等于9,则保持速度不变,若小于则加1 CJNE A,#9,CANFASTDEC ACANFAST:INC AMOV TEMP,ASJMP RETURNYES3:MOV A,TEMPCJNE A,#1,CANSLOWINC ACANSLOW:DEC AMOV TEMP,ARETURN:RETTESTSTOP:SETB SWITCHJNB SWITCH,GOSJMP ENNDGO:CALL DELAYJNB SWITCH,YESSTOPSJMP ENNDYESSTOP:CPL MARKENND:RET;***********************定时器设置******************* TIMER:MOV TMOD,#10H ;T1工作于定时方式1CALL TIMERSETSETB TR1SETB EASETB ET1 ;启动定时器工作WAIT:JBC TF1,HERESJMP WAIT ;定时未到继续等待HERE:DJNZ CYCLENUM,TIMER ;循环次数未满继续定时MOV A,TEMPMOV DPTR,#TAB3MOVC A,@A+DPTRMOV CYCLENUM,ARETTIMERSET:MOV A,TEMPMOV DPTR,#TAB1 ;获取定时器高位MOVC A,@A+DPTRMOV TH1,A ;存放至定时器高位MOV A,TEMPMOV DPTR,#TAB2MOVC A,@A+DPTR ;获取定时器定位MOV TL1,A ;存放至定时器低位RET;***********************50ms延时**********************DELAY:MOV R0,#100DL1:MOV R1,#10DJNZ R1,$DJNZ R0,DL1RET;************显示子程序****************************DISPLAY:CLR P2.7CLR P2.6CLR P2.5SETB P2.4 ;关闭高三位,保留个位MOV P0,LEDBUFRETTAB1: DB 15H,0AH,07H,05H,04H,03H,03H,02H,02H ;定时器高位TH1TAB2: DB 0B3H,0D9H,3BH,6CH,57H,0A5H,19H,0B6H,69H ;定时器地位TL1 TAB3: DB 01H,01H,01H,01H,01H,01H,01H,01H,01H ;循环次数CYCLENUM TAB4: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;数码显示0~9。

51单片机控制的步进电机C语言程序

51单片机控制的步进电机C语言程序

51单片机控制的步进电机C语言程序用的是L298驱动的和ULN2003一样,你把它换成2003就行拉#include <AT89X51.H>unsigned char codetable[]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9,0x00,0xf1,0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0x f3,0x00};unsigned char temp,temp_old;unsigned char key;unsigned char i,j,k,m,s;void delay(int i){for(m=i;m>0;m--)for(j=250;j>0;j--)for(k=10;k>0;k--);}void saomiao(){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0e:key=1;break;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07:key=4;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}}void main(void){while(1){saomiao();if(key==1){ P1=0;P2=0;saomiao();}if(key==2){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_4=0;delay(13);saomiao();if(key!=temp_old){P1_4=1;break;}}}if(key==3){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==4){temp_old=key; for(s=0;s<8;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}if(key==5){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_7=0;delay(13);saomiao();if(key!=temp_old){P1_7=1;break;}}}if(key==6){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==7){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}}}C语言程序源代码#include <REGX51.H> // 51寄存器定义#include "intrins.h"#define control P1 //P1_0:A相,P1_1:B相,P1_2:C相,P1_3:D相#define discode P0 //显示代码控制端口#define uchar unsigned char //定义无符号型变量#define uint unsigned intsbit en_dm=P3^0; //显示代码锁存控制sbit en_wk=P3^1; //位控锁存控制uchar code corotation[4]= {0x03,0x06,0x0c,0x09};//电机正转uchar code rollback[4]={0x0c,0x06,0x03,0x09}; //电机反转uchar code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示字段uint code Levspeed[5]={500,400,300,200,100};//电机速度等级uchar Hscan,speedcount;//Hscan行扫描,speedcount 速度等级计数uint uu; //频率计数uint step,setstep; //step:电机步伐计数,setstep:手动设置电机步伐uint speed=500; //电机初始速度uchar count;uchar flag[5];uchar butcount; //按键次数//****************************************//flag[0] 正转标志//flag[1] 反转标志//flag[2] 加速标志//flag[3] 减速标志//flag[4] 设置标志//****************************************Delay1mS(unsigned int tt) //延时1ms “Delay1mS”延时子程序,用循环语句延时。

51单片机驱动步进电机电路及程序

51单片机驱动步进电机电路及程序

51单片机驱动步进电机电路及程序在这里介绍一下用51单片机驱动步进电机的方法。

这款步进电机的驱动电压12V,步进角为度 . 一圈 360 度 , 需要 48 个脉冲完成!!!该步进电机有6根引线,排列次序如下:1:红色、2:红色、3:橙色、4:棕色、5:黄色、6:黑色。

采用51驱动ULN2003的方法进行驱动。

ULN2003的驱动直接用单片机系统的5V电压,可能力矩不是很大,大家可自行加大驱动电压到12V。

;********************************************************************************* ;****************************步进电机的驱动*************************************** ; DESIGN BY BENLADN911 FOSC = 12MHz;--------------------------------------------------------------------------------- ; 步进电机的驱动信号必须为脉冲信号!!! 转动的速度和脉冲的频率成正比!!!; 本步进电机步进角为度 . 一圈 360 度 , 需要 48 个脉冲完成!!!;---------------------------------------------------------------------------------; A组线圈对应; B组线圈对应; C组线圈对应; D组线圈对应; 正转次序: AB组--BC组--CD组--DA组 (即一个脉冲,正转度);---------------------------------------------------------------------------------- ;----------------------------正转--------------------------ORG 0000HLJMP MAINORG 0100HMAIN:MOV R3,#144 正转 3 圈共 144 脉冲START:MOV R0,#00HMOV P2,#00HMOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START 对 A 的判断,当 A = 0 时则转到 STARTMOV P2,ALCALL DELAYINC R0DJNZ R3,START1MOV P2,#00HLCALL DELAY1;-----------------------------反转------------------------MOV R3,#144 反转一圈共 144 个脉冲START2:MOV P2,#00HMOV R0,#05START3:MOV A,R0MOV DPTR,#TABLEMOVC A,@A+DPTRJZ START2CALL DELAYINC R0DJNZ R3,START3MOV P2,#00HLCALL DELAY1LJMP MAINDELAY: MOV R7,#40 步进电机的转速M3: MOV R6,#248DJNZ R6,$DJNZ R7,M3RETDELAY1: MOV R4,#20 2S 延时子程序DEL2: MOV R3,#200DEL3: MOV R2,#250DJNZ R2,$DJNZ R3,DEL3DJNZ R4,DEL2RETTABLE:DB 30H,60H,0C0H,90H 正转表DB 00 正转结束DB 30H,90H,0C0H,60H 反转表DB 00 反转结束END。

步进电机C语言代码

步进电机C语言代码

#include <AT89X51.h>static unsigned int count; //计数static int step_index; //步进索引数,值为0-7static bit turn; //步进电机转动方向static bit stop_flag; //步进电机停止标志static int speedlevel; //步进电机转速参数,数值越大速度越慢,最小值为1,速度最快static int spcount; //步进电机转速参数计数void delay(unsigned int endcount); //延时函数,延时为endcount*0.5毫秒void gorun(); //步进电机控制步进函数void main(void){count = 0;step_index = 0;spcount = 0;stop_flag = 0;P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1ET0 = 1; //定时器0中断允许TH0 = 0xFE;TL0 = 0x0C; //设定时每隔0.5ms中断一次TR0 = 1; //开始计数turn = 0;speedlevel = 2;delay(10000);speedlevel = 1;do{speedlevel = 2;delay(10000);speedlevel = 1;delay(10000);stop_flag=1;delay(10000);stop_flag=0;}while(1);}//定时器0中断处理void timeint(void) interrupt 1{TH0=0xFE;TL0=0x0C; //设定时每隔0.5ms中断一次count++;spcount--;if(spcount<=0){spcount = speedlevel;gorun();}}void delay(unsigned int endcount){count=0;do{}while(count<endcount);}void gorun(){if (stop_flag==1){P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 0;return;}switch(step_index) {case 0: //0P1_0 = 1;P1_1 = 0;P1_2 = 0;P1_3 = 0;break;case 1: //0、1P1_0 = 1;P1_1 = 1;P1_2 = 0;P1_3 = 0;break;case 2: //1P1_0 = 0;P1_1 = 1;P1_2 = 0;P1_3 = 0;break;case 3: //1、2P1_0 = 0;P1_1 = 1;P1_2 = 1;P1_3 = 0;break; case 4: //2P1_0 = 0;P1_1 = 0;P1_2 = 1;P1_3 = 0;break; case 5: //2、3P1_0 = 0;P1_1 = 0;P1_2 = 1;P1_3 = 1;break; case 6: //3P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 1;break; case 7: //3、0P1_0 = 1;P1_1 = 0;P1_2 = 0;P1_3 = 1; }if (turn==0){step_index++;if (step_index>7)step_index=0; }else{step_index--;if (step_index<0)step_index=7; }}。

51单片机控制步进电机硬件图及C语言编程

51单片机控制步进电机硬件图及C语言编程

51单片机控制步进电机硬件图#include <reg51.h> //51芯片管脚定义头文件#include <intrins.h> //内部包含延时函数_nop_();#include<absacc.h>#define uchar unsigned char#define uint unsigned intuchar code FFW[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //四相八拍正转编码uchar code REV[8]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01}; ////四相八拍反转编码sbit P14=P1^4; //将P14位定义为P1.4引脚sbit P15=P1^5; //将P15位定义为P1.5引脚sbit P16=P1^6; //将P16位定义为P1.6引脚sbit P17=P1^7; //将P17位定义为P1.7引脚sbit P20=P2^0; //将P20位定义为P2.0引脚sbit P21=P2^1; //将P21位定义为P2.1引脚sbit P22=P2^2; //将P22位定义为P2.2引脚sbit P23=P2^3; //将P23位定义为P2.3引脚sbit P24=P2^4; //将P24位定义为P2.4引脚sbit P25=P2^5; //将P25位定义为P2.5引脚sbit P26=P2^6; //将P26位定义为P2.6引脚sbit P27=P2^7; //将P27位定义为P2.7引脚sbit P34=P3^4; //将P34位定义为P3.4引脚sbit P35=P3^5; //将P35位定义为P3.5引脚sbit P36=P3^6; //将P36位定义为P3.6引脚sbit P37=P3^7; //将P37位定义为P3.7引脚sbit P30=P3^0; //将P30位定义为P3.0引脚sbit P31=P3^1; //将P31位定义为P3.1引脚sbit BEEP=P3^2; // 蜂鸣器bit on=0;bit off=1; //运行与停止标志bit zdirection=0; //方向标志bit fdirection=0; //方向标志uchar h,l,k; //定义行键值//定义列键值uchar idata count[3]; //0-9数值储存unsigned char code Tab[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数字0~9的段码uchar keyval=0; //定义变量储存按键值uchar dat=0; //按键值uint run_i=0;uchar count_i=0;uint run=0; //需要运行的步数uint drun=0; //当前运行的步数bit flag;uint x=60;uint y=60;uint z=0;/* uint k=0; //调速按键次*//**************************************************************/ void led_delay1(void){unsigned char j;for(j=0;j<52;j++);}void beep(){uchar j;for (j=0;j<200;j++){led_delay1();BEEP=!BEEP; //BEEP取反}BEEP=1; //关闭蜂鸣器}/**************************************************************函数功能:数码管动态扫描延时**************************************************************/void led_delay(void){unsigned char j;for(j=0;j<200;j++);}/**************************************************************/**************************************************************函数功能:软件延时去抖动子程序**************************************************************/void delay20ms(void){unsigned char i,j;for(i=0;i<70;i++)for(j=0;j<60;j++);}void display(uint run){ //显示设点步数P31=1; //点亮数码管DS6P30=0;P34=0;P35=0;P36=0;P37=0;P14=0;P15=0;if((run/100)!=0){ P0=Tab[run/100]; //显示百位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;P30=1;P31=0;P34=0;P36=0;P37=0;P14=0;P15=0;if(((run%100/10)==0)&&(run/10==0)) { P0=0xff;led_delay(); //动态扫描延时led_delay();} //点亮数码管DS5else{ P0=Tab[run%100/10]; //显示十位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;P37=1; //点亮数码管DS4P30=0;P34=0;P35=0;P36=0;P31=0;P14=0;P15=0;if((run/10==0)&&(run%100/10==0)&&(run%10==0)){ P0=0xff;led_delay(); //动态扫描延时led_delay(); //动态扫描延时}else{ P0=Tab[run%10]; //显示个位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;}/*********************************************************************/void ddisplay(uint drun){ //显示运行步数P36=1; //点亮数码管DS3P30=0;P34=0;P35=0;P31=0;P37=0;P15=0;if((drun/100)!=0){P0=Tab[drun/100]; //显示百位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;P35=1; //点亮数码管DS2P30=0;P34=0;P31=0;P36=0;P37=0;P14=0;P15=0;if(((drun%100/10)==0)&&(drun/10==0)) { P0=0xff;led_delay(); //动态扫描延时led_delay();}//点亮数码管DS5else{ P0=Tab[drun%100/10]; //显示十位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;P34=1; //点亮数码管DS1P30=0;P31=0;P35=0;P36=0;P37=0;P14=0;P15=0;if((drun/10==0)&&(drun%100/10==0)&&(drun%10==0)){ P0=0xff;led_delay(); //动态扫描延时led_delay(); //动态扫描延时}else{ P0=Tab[drun%10]; //显示个位led_delay(); //动态扫描延时led_delay(); //动态扫描延时}P0=0xff;}void dddisplay(){ P15=1;P36=0;P30=0;P34=0;P35=0;P31=0;P37=0;P14=0;if((fdirection==1)&&(on==1)){P0=0xbf; led_delay(); led_delay(); }P0=0xff;P14=1;P36=0;P30=0;P34=0;P35=0;P31=0;P37=0;P15=0;if(y==60){P0=0x08;led_delay(); led_delay();}if(y==50){P0=0x03; led_delay(); led_delay(); }if(y==40){P0=0x46; led_delay(); led_delay();}if(y==30){P0=0x21 ;led_delay(); led_delay();}if(y==20){P0=0x86; led_delay(); led_delay(); }if(y==10){P0=0x8e; led_delay(); led_delay();}P0=0xff;}/************************************************************** 函数功能:主函数**************************************************************/ void main(void){ x=60;P14=0;P15=0;P16=0;P17=0;EA=1;EX1=1; //允许使用外中断IT1=1; //选择负跳变来触发外中断PT0=1;ET0=1; //定时器T0中断允许TMOD=0x01; //使用定时器T0的模式1TH0=0xec; //定时器T0的高8位赋初值TL0=0x78; //定时器T0的低8位赋初值TR0=1;P30=1; //启动定时器T0P34=1;P35=1;P36=1;P37=1;P31=1;P2=0xf0;while(1){if(flag){P2=0x0f; h=P2&0x0f; //所有行线置为高电平"1",所有列线置为低电平"0",并把值给hif((P2&0x0f)!=0x0f) //行线中有一位为低电平"0",说明有键按下delay20ms(); //延时一段时间、软件消抖else {keyval=16;}if(h!=0x0f) //确实有键按下{h=P2&0x0f; //读取行值P2=0xf0; //反转电位l=P2&0xf0; //读取列值k=h+l; //行列相加,为键位值if(k==0x7e) keyval=12;if(k==0x7d) keyval=0;if(k==0x7b) keyval=13;if(k==0x77) keyval=15;if(k==0xbe) keyval=1;if(k==0xbd) keyval=2;if(k==0xbb) keyval=3;if(k==0xb7) keyval=14; //键位与设定对应if(k==0xde) keyval=4;if(k==0xdd) keyval=5;if(k==0xdb) keyval=6;if(k==0xd7) keyval=11;if(k==0xee) keyval=7;if(k==0xed) keyval=8;if(k==0xeb) keyval=9;if(k==0xe7) keyval=10;}else keyval=16;dat=keyval;if((dat==10)&&(run!=0)) //正转键按下{zdirection=1; //方向标志fdirection=0;on=1; //运行与停止标志off=0;}if((dat==11)&&(run!=0)) //反转键按下{fdirection=1; //方向标志zdirection=0;on=1; //运行与停止标志off=0;}if(dat==12) //加速键{if(y==10) y=10;else y=y-10;}if(dat==13) //减速键{if(y==60) y=y;else y=y+10;}if((dat==14)&&(run!=0)) //开始键按下{ if(z==1) {on=1;}elseon=1;off=0;z=0;if((zdirection==0)&&(fdirection==0)){zdirection=1;}}if(dat==15) { z++;on=0; } //停止键按下一次if((on==0)&&(z==2)) //停止键按下二次{count[0]=0; //显示清零count[1]=0;count[2]=0;drun=0; run=0;z=0;on=0;off=1; //运行与停止标志}if((dat>=0)&&(dat<=9)&&(on==0)&&(off==1)){count[count_i]=dat;if(count[0]!=0){count_i++;}if((count_i==3)&&(on==0)&(off==1)){count_i=0;}if((count_i==0)&&(on==0)&(off==1)){ if(count[0]==0)run=0;else run=count[0]*100+count[1]*10+count[2];}if((count_i==1)&&(on==0)&(off==1)){run=count[0];}if((count_i==2)&&(on==0)&(off==1)){run=count[0]*10+count[1];}}if((dat==0)&&(on==1)){off=1;}if(dat==16);flag=0;}/*if(run!=0){*/ddisplay(drun);dddisplay();display(run);/*} */ //调用按键值的数码管显示子程序if((run==drun)&&run!=0){on=0;off=1;beep();drun=0; run=0;count[0]=0; //显示清零count[1]=0;count[2]=0;count_i=0;}}}/**************************************************************外部中断键盘扫描键值保存在dat中******************************************************************************* ************/void Interrupt1() interrupt 2 using 3{flag=1;}/*************************************************************************/ void Interrupt2() interrupt 1 using 1{ TR0=0;EX1=1;TH0=0xec;TL0=0x78;x--;if(x==0){if((zdirection==1)&&(fdirection==0)&&(on==1)&&(off==0)){P1=FFW[run_i];fdirection=0;led_delay(); //动态扫描延时led_delay(); //动态扫描延时led_delay(); //动态扫描延时led_delay(); //动态扫描延时drun++;run_i++;if(run_i==8)run_i=0;if(run==drun){on=0;off=1;}}if((zdirection==0)&&(fdirection==1)&&(on==1)&&(off==0)){P1=REV[run_i];led_delay(); //动态扫描延时led_delay(); //动态扫描延时led_delay(); //动态扫描延时led_delay(); //动态扫描延时zdirection=0;drun++;run_i++;if(run_i==8)run_i=0;if(run==drun){on=0;off=1;}}if((on==0)&&(off=1))P1=0x00; x=y;}TR0=1;}。

基于51单片机的步进电机控制-设计报告(说明书)及源程序

基于51单片机的步进电机控制-设计报告(说明书)及源程序

南京XX大学指导老师:张X课程设计基于51单片机的步进电机控制机械电子工程学院测控技术与仪器XXXXXXxx2012年1年4日步进电机控制系统[摘要]本课程设计的内容是利用51单片机,达到控制步进电机的启动、停止、正转、反转、两档速度和状态显示的目的,使步进电机控制更加灵活。

步进电机驱动芯片采用ULN2803,ULN2803具有大电流、高电压,外电路简单等优点.利用四位数码管增设电机状态显示功能,各项数据更直观。

实测结果表明,该控制系统达到了设计的要求。

关键字:步进电机、数码管、51单片机、ULN2803一步进电机与驱动电路1.1 什么是步进电机步进电机是一种将电脉冲转化为角位移的执行机构。

通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。

可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时也可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的.步进电机分永磁式(PM)、反应式(VR)、和混合式(HB)三种。

永磁式步进一般为两相,转矩和体积较小,步进角一般为7。

5度或15度;反应式步进一般为三相,可实现大转矩输出,步进角一般为1。

5度,但噪声和振动都很大.在欧美等发达国家80年代已被淘汰;混合式步进是指混合了永磁式和反应式的优点。

它又分为两相和五相:两相步进角一般为1。

8度而五相步进角一般为0。

72度。

这种步进电机的应用最为广泛。

1。

3 步进电机的特点1.精度高一般的步进电机的精度为步进角的3—5%,且不累积。

可在宽广的频率范围内通过改变脉冲频率来实现调速,快速起停、正反转控制及制动等,这是步进电动机最突出的优点2.过载性好其转速不受负载大小的影响,不像普通电机,当负载加大时就会出现速度下降的情况,所以步进电机使用在对速度和位置都有严格要求的场合;3.控制方便步进电机是以“步”为单位旋转的,数字特征比较明显,这样就给计算机控制带来了很大的方便,反过来,计算机的出现也为步进电机开辟了更为广阔的使用市场;4.整机结构简单传统的机械速度和位置控制结构比较复杂,调整困难,使用步进电机后,使得整机的结构变得简单和紧凑。

片机控制的步进电机C语言程序

片机控制的步进电机C语言程序

51单片机控制的步进电机C语言程序用的是L298驱动的和ULN2003一样,你把它换成2003就行拉#include <AT89X51.H>unsigned char codetable[]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9,0x00,0xf1,0xf9,0xf8,0xfc,0xf4, 0xf6,0xf2,0xf3,0x00};unsigned char temp,temp_old;unsigned char key;unsigned char i,j,k,m,s;void delay(int i){for(m=i;m>0;m--)for(j=250;j>0;j--)for(k=10;k>0;k--);}void saomiao(){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0e:key=1;break;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07:key=4;break;}temp=P3;temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f; }}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f) {temp=P3;temp=temp&0x0f; }}}}void main(void){while(1){saomiao();if(key==1){ P1=0;P2=0;saomiao();}if(key==2){temp_old=key;for(s=0;s<8;s++){ P2=table[s]; P1_4=0;delay(13);saomiao();if(key!=temp_old) {P1_4=1;break;}}}if(key==3){temp_old=key;for(s=0;s<8;s++){ P2=table[s]; P1_5=0;delay(5);saomiao();if(key!=temp_old) {P1_5=1;break;}}}if(key==4){temp_old=key;for(s=0;s<8;s++){ P2=table[s]; P1_6=0;delay(20);saomiao();if(key!=temp_old) {P1_6=1;break;}}}if(key==5){temp_old=key;for(s=9;s<17;s++){ P2=table[s]; P1_7=0;delay(13);saomiao();if(key!=temp_old) {P1_7=1;break;}}}if(key==6){temp_old=key;for(s=9;s<17;s++){ P2=table[s]; P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==7){temp_old=key; for(s=9;s<17;s++){ P2=table[s]; P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}}}C语言程序源代码#include <REGX51.H> // 51寄存器定义#include "intrins.h"#define control P1 //P1_0:A相,P1_1:B相,P1_2:C相,P1_3:D相#define discode P0 //显示代码控制端口#define uchar unsigned char //定义无符号型变量#define uint unsigned intsbit en_dm=P3^0; //显示代码锁存控制sbit en_wk=P3^1; //位控锁存控制uchar code corotation[4]= {0x03,0x06,0x0c,0x09};//电机正转uchar code rollback[4]={0x0c,0x06,0x03,0x09}; //电机反转uchar code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示字段uint code Levspeed[5]={500,400,300,200,100};//电机速度等级uchar Hscan,speedcount;//Hscan行扫描,speedcount 速度等级计数uint uu; //频率计数uint step,setstep; //step:电机步伐计数,setstep:手动设置电机步伐uint speed=500; //电机初始速度uchar count;uchar flag[5];uchar butcount; //按键次数//****************************************//flag[0] 正转标志//flag[1] 反转标志//flag[2] 加速标志//flag[3] 减速标志//flag[4] 设置标志//****************************************Delay1mS(unsigned int tt) //延时1ms “Delay1mS”延时子程序,用循环语句延时。

51单片机上画圆弧任意2点坐标就控制步进电机

51单片机上画圆弧任意2点坐标就控制步进电机

#ifndef _MAIN_C_#define _MAIN_C_#include "config.h"#include "lcd1602.h"typedef unsigned char uint8;typedef signed char int8;typedef signed int int16;typedef unsigned int uint16;unsigned char T0RH;T0RL;unsigned int time_count=0;unsigned char n=0;unsigned char pdata str[12];int16 x_start_value=0;int16 y_start_value=0;int16 x_finish_value=0;int16 y_finish_value=0;int16 a;int16 b;int16 x;int16 y;int16 ox;int16 oy;int16 px[2],py[2];int16 r;int16 x_g2;int16 y_g2;int16 x_g3;int16 y_g3;int16 flag_3=0;//F 误差系数uint16 flag_finish=0;uint8 flag_xiangxian=0;unsigned char flag_g=0; //flag_g=0;flag_g=1,flag_g=2,flag_g=3; unsigned char div=0;unsigned char curr_index=0;unsigned char index=0;#define NUM_AS 2typedef struct node{signed int xe;signed int ye;unsigned char flag_g;signed int R;}lnode;//typedef struct node lnode;struct list{signed int x0;signed int y0;signed int xv;signed int yv;unsigned char num;unsigned char state;lnode vlist[8];};typedef struct list sqlist;typedef struct list *sqlist_ptr;/////////////////////////////////////////void configtime0(unsigned int ms);void xiangxian();void init();void addx();void backx();void addy();void backy();void panduan();void getarc(int16 xs,int16 ys,int16 xe,int16 ye);void f(int16 x1,int16 y1,int16 x2,int16 y2);void Draw_polygon2D(sqlist_ptr poly);void main(){ //sqlist idata L[1];//lnode xdata p[22]=0;lnode xdata s[]={{0,0,0,0},{0,400,1,800},{200,600,2,200},{600,600,1,0},{800,400,2,200},{800,0,1,0},{400, 400,2,400},{0,0,2,400}};//lnode xdata s[]={200,600,2,200};//init_mempool(p,sizeof(p));//sqlist_ptr L_ptr;for(curr_index=0;curr_index<2;curr_index++){L[curr_index].state=1;L[curr_index].x0=0;L[curr_index].y0=0;L[curr_index].xv=0;L[curr_index].yv=0;L[curr_index].num=8;//sizeof(s)/sizeof(lnode); //8// L[curr_index].vlist=(lnode *)malloc(8*sizeof(lnode));//L[curr_index].vlist=s;//for(index=0;index<L[curr_index].num;index++){L[curr_index].vlist[index].xe=s[index].xe;L[curr_index].vlist[index].ye=s[index].ye;L[curr_index].vlist[index].flag_g=s[index].flag_g;L[curr_index].vlist[index].R=s[index].R;}}EA=1;configtime0(1);lcdinit();flag_g=0;while(1){for(curr_index=0;curr_index<2;curr_index++){lcdclearfull();IntToString(str,curr_index);lcdshowstr(0,0,str);IntToString(str,L[1].num);lcdshowstr(5,0,str);Draw_polygon2D(&L[curr_index]);}}}//////////////////////////////////////////////////////////////////////////void Draw_polygon2D(sqlist_ptr poly){static unsigned char i=0;// if(poly->state==1)// {do{for(;i<poly->num;){if(poly->vlist[i].flag_g==0&&flag_finish==0){TR0=0;flag_3=0;x_finish_value=poly->vlist[i].xe;y_finish_value=poly->vlist[i].ye;x_start_value=poly->x0;y_start_value=poly->y0;flag_g=poly->vlist[i].flag_g;init();i=i+1;TR0=1;break;}else if(poly->vlist[i].flag_g==1&&flag_finish==0) //斜线的判断{TR0=0;flag_3=0;x_finish_value=poly->vlist[i].xe;y_finish_value=poly->vlist[i].ye;x_start_value=poly->vlist[i-1].xe;y_start_value=poly->vlist[i-1].ye;flag_g=poly->vlist[i].flag_g;init();i++;TR0=1;break;}else if((poly->vlist[i].flag_g==2)&&(flag_finish==0))//顺园的判断{TR0=0;flag_3=0;x_finish_value=poly->vlist[i].xe;y_finish_value=poly->vlist[i].ye;x_start_value=poly->vlist[i-1].xe;y_start_value=poly->vlist[i-1].ye;flag_g=poly->vlist[i].flag_g;r=poly->vlist[i].R;EA=0;f(x_start_value, y_start_value,x_finish_value,y_finish_value);EA=1;/*IntToString(str,px[0]);lcdshowstr(0,0,str);IntToString(str,py[0]);lcdshowstr(6,0,str);IntToString(str,px[1]);lcdshowstr(0,1,str);IntToString(str,py[1]);lcdshowstr(6,1,str);*/getarc( x_start_value, y_start_value,x_finish_value,y_finish_value);init();i++;TR0=1;break;}} //forIntToString(str,i);lcdshowstr(0,1,str);IntToString(str,poly->num);lcdshowstr(3,1,str);IntToString(str,poly->vlist[i].xe);lcdshowstr(5,1,str);IntToString(str,poly->vlist[i].ye);lcdshowstr(9,1,str);}while(i<poly->num);i=0;// }}/////////////////////////////////void init(){if(flag_g==0){a=x_finish_value-x_start_value;if(a<0)a=-a;b=y_finish_value-y_start_value;if(b<0)b=-b;x_finish_value=x_finish_value-x_start_value;y_finish_value=y_finish_value-y_start_value;x_start_value=x_start_value-x_start_value;y_start_value=y_start_value-y_start_value;flag_finish=a+b;xiangxian();x=x_start_value;y=y_start_value;n=10;}if(flag_g==1){x_finish_value=x_finish_value-x_start_value;y_finish_value=y_finish_value-y_start_value;x_start_value=x_start_value-x_start_value;//开始X点位移到原点y_start_value=y_start_value-y_start_value; //开始Y点位移到原点xiangxian(); //flag_finish=x_finish_value+y_finish_value;x=x_start_value;y=y_start_value;n=6;}if(flag_g==2) //顺圆{x_finish_value=x_finish_value-ox;y_finish_value=y_finish_value-oy; //计算y轴上要走步数x_start_value=x_start_value-ox;y_start_value=y_start_value-oy;a=x_finish_value-x_start_value;if (a<0) //当上式结果为负时{a=-a; //调整为正数}b=y_finish_value-y_start_value;if (b<0) //当上式结果为负时{b=-b; //调整为正数}ox=ox-ox;//oy=oy-oy;//flag_finish=a+b;xiangxian();x=x_start_value;y=y_start_value;x_g2=x_start_value;if(x_g2<0){x_g2=-x_g2;}y_g2=y_start_value; //起始位置坐标设定if(y_g2<0){y_g2=-y_g2;}n=6;}if(flag_g==3)//逆圆{}time_count=0;}void xiangxian(){if(flag_g==0){if(x_finish_value>=0){if(y_finish_value>=0){flag_xiangxian=1; // 1}if(y_finish_value<0){y_finish_value=0-y_finish_value;flag_xiangxian=4; // 4}}if(x_finish_value<0){if(y_finish_value>=0){flag_xiangxian=2;}if(y_finish_value<0){y_finish_value=0-y_finish_value;flag_xiangxian=3;}}}if(flag_g==1){if(x_finish_value>=0){if(y_finish_value>=0){flag_xiangxian=1;if(y_finish_value<0){y_finish_value=0-y_finish_value;flag_xiangxian=4;}}if(x_finish_value<0){x_finish_value=0-x_finish_value;if(y_finish_value>=0){flag_xiangxian=2;}if(y_finish_value<0){y_finish_value=0-y_finish_value;flag_xiangxian=3;}}}if(flag_g==2) //当顺圆插补时{if(x_finish_value==0) //当终点坐标在X轴上时{if(y_finish_value>0) //如果终点Y坐标为正{flag_xiangxian=2; //确定插补过程在第二象限}if(y_finish_value<0) //如果终点Y坐标为负{flag_xiangxian=4; //确定插补过程在第四象限y_finish_value=-y_finish_value; //终点Y座标求绝对值}}if(x_finish_value>0) //如果终点X坐标为正{if(y_finish_value>0) //如果终点Y坐标为正{flag_xiangxian=1; //确定插补过程在第一象限}if(y_finish_value==0) //当终点坐标在Y轴上时flag_xiangxian=1; //确定插补过程在第一象限}if(y_finish_value<0) //如果终点Y坐标为负{flag_xiangxian=4; //确定插补过程在第四象限y_finish_value=-y_finish_value; //终点Y座标求绝对值}}if(x_finish_value<0) //如果终点X坐标为负{x_finish_value=-x_finish_value; //终点X座标求绝对值if(y_finish_value>0) //如果终点Y坐标为正{flag_xiangxian=2; //确定插补过程在第二象限}if(y_finish_value==0) //当终点坐标在Y轴上时{flag_xiangxian=3; //确定插补过程在第三象限}if(y_finish_value<0) //如果终点Y坐标为负{flag_xiangxian=3; //确定插补过程在第三象限y_finish_value=-y_finish_value; //终点Y座标求绝对值}}}if(flag_g==3){}}void panduan(){if(flag_g==0){if(flag_finish>0){if(x!=x_finish_value){if(flag_xiangxian==1){addx();}if(flag_xiangxian==2){backx();}if(flag_xiangxian==3){backx();}if(flag_xiangxian==4){addx();}}if(x==x_finish_value){if(flag_xiangxian==1){addy();}if(flag_xiangxian==2){addy();}if(flag_xiangxian==3){backy();}if(flag_xiangxian==4){backy();}}}}if(flag_g==1){if(flag_finish>0){if(flag_3>=0){if(flag_xiangxian==1){addx();}if(flag_xiangxian==2){backx();}if(flag_xiangxian==3){backx();}if(flag_xiangxian==4){addx();}}if(flag_3<0){if(flag_xiangxian==1){addy();}if(flag_xiangxian==2){addy();}if(flag_xiangxian==3){backy();}if(flag_xiangxian==4){backy();}}}}if(flag_g==2) //当顺圆插补时{if(flag_finish>0){if(flag_3>=0) //当偏差式大于等于零时{if(flag_xiangxian==1) //当为第一象限顺圆插补时{backy(); //调用y轴反向走步程序}if(flag_xiangxian==2) //当为第二象限顺圆插补时{addx(); //调用x轴正向走步程序}if(flag_xiangxian==3) //当为第三象限顺圆插补时{addy(); //调用y轴正向走步程序}if(flag_xiangxian==4) //当为第四象限顺圆插补时{backx(); //调用x轴反向走步程序}}if(flag_3<0) //当偏差式小于零时{if(flag_xiangxian==1) //当为第四象限顺圆插补时{addx(); //调用x轴正向走步程序}if(flag_xiangxian==2) //当为第四象限顺圆插补时{addy(); //调用y轴正向走步程序}if(flag_xiangxian==3) //当为第四象限顺圆插补时{backx(); //调用x轴反向走步程序}if(flag_xiangxian==4) //当为第四象限顺圆插补时{backy(); //调用y轴反向走步程序}}}}if(flag_g==3){if(flag_finish>0){}}void addx(){while(time_count>=n){Xdir=0;Xpul=~Xpul;div++;if(div==2){if(flag_g==1){flag_3=flag_3-y_finish_value;}if(flag_g==2) //当顺圆查补时{if(flag_xiangxian==2) //当为第二象限顺圆查补时{flag_3=flag_3-2*x_g2+1; //查补偏差判别式x_g2--; //顺圆x坐标绝对值减一}if(flag_xiangxian==1) //当为第一象限顺圆查补时{flag_3=flag_3+2*x_g2+1; //查补偏差判别式x_g2++; //顺圆x坐标绝对值加一}}if(flag_g==3){}div=0;x=x+1;flag_finish=flag_finish-1;if(flag_finish<=0){TR0=0;}time_count=0;panduan();}}void backx(){while(time_count>=n){Xdir=1;Xpul=~Xpul;div++;if(div==2){div=0;if(flag_g==1){flag_3=flag_3-y_finish_value;}if(flag_g==2) //当顺圆查补时{if(flag_xiangxian==4) //当为第四象限顺圆查补时{flag_3=flag_3-2*x_g2+1; //查补偏差判别式x_g2--; //顺圆x坐标绝对值减一}if(flag_xiangxian==3) //当为第三象限顺圆查补时{flag_3=flag_3+2*x_g2+1; //查补偏差判别式x_g2++; //顺圆x坐标绝对值加一}}if(flag_g==3){}x--;flag_finish--;if(flag_finish<=0){TR0=0;}time_count=0;panduan();}}}void addy(){while(time_count>=n){Ydir=0;Ypul=~Ypul;div++;if(div==2){div=0;if(flag_g==1){flag_3=flag_3+x_finish_value;}if(flag_g==2) //当顺圆查补时{if(flag_xiangxian==3) //当为第三象限顺圆查补时{flag_3=flag_3-2*y_g2+1; //查补偏差判别式y_g2--; //顺圆y坐标绝对值减一}if(flag_xiangxian==2) //当为第二象限顺圆查补时{flag_3=flag_3+2*y_g2+1; //查补偏差判别式y_g2++; //顺圆y坐标绝对值加一}}if(flag_g==3){}y++;flag_finish--;if(flag_finish<=0){TR0=0;}time_count=0;panduan();}}}void backy(){while(time_count>=n){Ydir=1;Ypul=~Ypul;div++;if(div==2){div=0;if(flag_g==1){flag_3=flag_3+x_finish_value;}if(flag_g==2) //当顺圆查补时{if(flag_xiangxian==1) //当为第一象限顺圆查补时{flag_3=flag_3-2*y_g2+1; //查补偏差判别式y_g2--; //顺圆y坐标绝对值减一}if(flag_xiangxian==4) //当为第四象限顺圆查补时{flag_3=flag_3+2*y_g2+1; //查补偏差判别式y_g2++; //顺圆y坐标绝对值加一}}if(flag_g==3){}y--;flag_finish--;if(flag_finish<=0){TR0=0;}time_count=0;panduan();}}}/////////////////////圆上任意4点画圆弧void f(int16 x1,int16 y1,int16 x2,int16 y2) {float pdata d;float pdata dx,dy;float pdata D;float pdata my[2],nx[2];float pdata L;float pdata sink,cosk;float pdata n,m;n=x2-x1;if(n<0)n=-n;m=y2-y1;if(m<0)m=-m;dx=(float)n*n;//a^2+b^2;dy=(float)m*m;d=dx+dy;D=sqrt(d);// ok sqrtsink=n/D; // okcosk=m/D; // okL=(float)r*r-(float)(d/4); //okL=sqrt(L); //oknx[0]=(float)(x2+x1)/2-(float)L*sink ;my[0]=(float)(y2+y1)/2-(float)L*cosk;nx[1]=(float)(x2+x1)/2+(float)L*sink ;my[1]=(float)(y2+y1)/2+(float)L*cosk;px[0]=nx[0];py[0]=my[0];px[1]=nx[1];py[1]=my[1];}void getarc(int16 xs,int16 ys,int16 xe,int16 ye) {if((xs>xe)&&(ys<=ye)) //3{//取Y最大值if(py[1]>py[0]){oy=py[1];ox=px[1];}}else if((xs<xe)&&(ys<=ye)) //2{//取Y最小值if(py[0]<py[1]){oy=py[0];ox=px[1];}}else if((xs<xe)&&(ys>=ye)) //1{//取Y最小值if(py[0]<py[1]){oy=py[0];ox=px[0];}}else if((xs>xe)&&(ys>=ye)) //4{//取Y最大值if(py[1]>py[0]){oy=py[1];ox=px[0];}}}/////////////////////////////////////void configtime0(unsigned int ms){unsigned long tmp;tmp=11059200/12;tmp=(921600*ms)/(5000);tmp=65536-tmp;T0RH=(unsigned char )(tmp>>8);T0RL=(unsigned char)tmp;TMOD=TMOD&0xf0;TMOD=TMOD|0x01;ET0=1;TR0=0;TH0=T0RH;TL0=T0RL;}///////////////void time0() interrupt 1 // 1ms 进一次中断{TH0=T0RH;TL0=T0RL;time_count++;panduan();}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

我上周刚做的这个实验成功拉,给你参考一下吧这可是我当时辛辛苦苦编出来的啊,不过我用的是L298驱动的和ULN2003一样,你把它换成2003就行拉
#include <AT89X51.H>
unsigned char code table[]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf 9,0x00,0xf1,0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0x00};
unsigned char temp,temp_old;
unsigned char key;
unsigned char i,j,k,m,s;
void delay(int i)
{
for(m=i;m>0;m--)
for(j=250;j>0;j--)
for(k=10;k>0;k--);
}
void saomiao()
{
P3=0xff;
P3_4=0;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--); temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case 0x0e:
key=1;
break;
case 0x0d:
key=2;
break;
case 0x0b:
key=3;
break;
case 0x07:
key=4;
break;
}
temp=P3;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
P3=0xff;
P3_5=0;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case 0x0d:
key=5;
break;
case 0x0b:
key=6;
break;
case 0x07:
key=7;
break;
}
temp=P3;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
}
}
}
void main(void)
{
while(1)
{
saomiao();
if(key==1)
{ P1=0;
P2=0;
saomiao();
}
if(key==2)
{
temp_old=key;
for(s=0;s<8;s++)
{ P2=table[s];
P1_4=0;
delay(13);
saomiao();
if(key!=temp_old)
{
P1_4=1;
break;
}
}
}
if(key==3)
{
temp_old=key;
for(s=0;s<8;s++)
{ P2=table[s];
P1_5=0;
delay(5);
saomiao();
if(key!=temp_old)
{
P1_5=1;
break;
}
}
}
if(key==4)
{
temp_old=key;
for(s=0;s<8;s++)
{ P2=table[s];
P1_6=0;
delay(20);
saomiao();
if(key!=temp_old)
{
P1_6=1;
break;
}
}
}
if(key==5)
{
temp_old=key;
for(s=9;s<17;s++)
{ P2=table[s];
P1_7=0;
delay(13);
saomiao();
if(key!=temp_old)
{
P1_7=1;
break;
}
}
}
if(key==6)
{
temp_old=key;
for(s=9;s<17;s++)
{ P2=table[s];
P1_5=0;
delay(5);
saomiao();
if(key!=temp_old)
{
P1_5=1;
break;
}
}
}
if(key==7)
{
temp_old=key;
for(s=9;s<17;s++)
{ P2=table[s];
P1_6=0;
delay(20);
saomiao();
if(key!=temp_old)
{
P1_6=1;
break;
}
}
}
}
}。

相关文档
最新文档