1、 xxxxxxxxxxxxxxxxxxx#include “reg52.h“#include “INTRINS.H“#include #include #define uint unsigned int#define uchar unsigned char#define ACC_LEVEL 42#define DEC_LEVEL 42#define STOP_LEVEL 42#define UP_LEVEL (ACC_LEVEL-2)#define DOWN_LEVEL 1uchar code slave_addr4=00, 01, 02, 255;uchar code c110=0xF0,0
2、xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xA0,0xA2;uchar code c210=0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0xB0,0xB2;/*加速过程各档速度定时器初值,用 16 位的 T2 实现*/uint code acc_pulse_T2_constACC_LEVEL=64170,64170,64841,65065,65176,65243,65288,65320,65344,65362,65377,65389,65399,65407,65415,65421,65426,65431,65435,65439,6
3、5443,65446,65448,65451,65453,65455,65457,65459,65461,65462,65464,65465,65466,65467,65468,65469,65470,65471,65472,65473,65474,65474;/*加速过程各档速度加速持续时间 (用脉冲数表示),用 16 位的 T0 计数,计数器初值*/uint code acc_time_T0_constACC_LEVEL=65463,65463,65460,65458,65455,65452,65449,65446,65443,65440,65436,65433,65429,65425,6
4、5421,65417,65413,65409,65404,65399,65395,65389,65384,65379,65373,65368,65362,65355,65349,65342,65335,65328,65321,65313,65305,65297,65289,65280,65271,65261,65251,65251;/*减速过程各档速度定时器初值,用 16 位的 T2 实现*/uint code dec_pulse_T2_constDEC_LEVEL=64170,64170,64841,65065,65176,65243,65288,65320,65344,65362,6537
5、7,65389,65399,65407,65415,65421,65426,65431,65435,65439,65443,65446,65448,65451,65453,65455,65457,65459,65461,65462,65464,65465,65466,65467,65468,65469,65470,65471,65472,65473,65474,65474;/*减速过程各档速度减速持续时间 (用脉冲数表示),用 16 位的 T0 计数,计数器初值*/uint code dec_time_T0_constDEC_LEVEL=65463,65463,65460,65458,6545
6、5,65452,65449,65446,65443,65440,65436,65433,65429,65425,65421,65417,65413,65409,65404,65399,65395,65389,65384,65379,65373,65368,65362,65355,65349,65342,65335,65328,65321,65313,65305,65297,65289,65280,65271,65261,65251,65251;/*停机过程各档速度定时器初值,用 16 位的 T2 实现*/uint code stop_pulse_T2_constSTOP_LEVEL=64170
7、,64170,64841,65065,65176,65243,65288,65320,65344,65362,65377,65389,65399,65407,65415,65421,65426,65431,65435,65439,65443,65446,65448,65451,65453,65455,65457,65459,65461,65462,65464,65465,65466,65467,65468,65469,65470,65471,65472,65473,65474,65474;/*停机过程各档速度减速持续时间 (用脉冲数表示),用 16 位的 T0 计数,计数器初值*/uint c
8、ode stop_time_T0_constSTOP_LEVEL=65463,65463,65460,65458,65455,65452,65449,65446,65443,65440,65436,65433,65429,65425,65421,65417,65413,65409,65404,65399,65395,65389,65384,65379,65373,65368,65362,65355,65349,65342,65335,65328,65321,65313,65305,65297,65289,65280,65271,65261,65251,65251;uchar idata acc
9、_count, dec_count, input_count, temp_count, done_no,input_order;uchar idata T0low, T0high, T2low, T2high, key_in; uint idata interval, pulse_counter, common_count;/*common_count 记录当前 T2 定时器初值数组序号,即当前转速,不用到处寻找*/*关键在那里获得 common_count 的值,应该在输出速度脉冲定时器的启动程序里找到*/*当前转速,在哪里获得?在本程序,应该为 T2 定时器当前初值,在 T0 中断服务程序
10、里获得*/*加速减速停机函数经过处理可以合并为一个函数,但分为独立函数效率高一点*/uchar bdata sign0,sign1,test_s0, test_s1;sbit new_speed_in=sign00; /*新速度数据从串口输入标志位*/sbit acc_run_permit=sign01;/*允许电机加速标志位*/ sbit dec_run_permit=sign02; /*允许电机减速标志位*/ sbit carry_acc=sign03; /*执行加速函数标志位*/ sbit carry_dec=sign04; /*执行减速函数标志位*/ sbit carry_stop=s
11、ign05; /*执行停机函数标志位*/ sbit normal_stop=sign06; /*调用停机函数标志位*/ sbit test_p=sign07; /*串口输入停机指令标志位*/ /*-*/sbit check_input_spd=sign10; /*当前输入转速级别处理函数完毕标志位*/sbit first_startup=sign11; /*电机启动过的标志位*/sbit address_true=sign12; /*从机地址正确标志位*/ sbit print_permit=sign13; /*允许输出标志位*/sbit cmd_in_permit=sign14; /*允许主
12、机命令输入标志位*/ /*-*/sbit P2_0=P20; /*作输入步进电机的脉冲信号发送口*/sbit P2_2=P22; /*作输入步进电机的旋转方向信号发送口*/sbit P1_0=P10; /*开机时需要关断串口发送功能 ,需要时再接通*/*作串口输出信号的使能口 , P1_0=0 时接通串口 ,输出信号*/sbit P1_2=P12; /*现在作检测位 ,用仿真机仿真时用该接口*/sbit P1_5=P15; /*作脉冲信号输入 T0 的发送口*/sbit P1_6=P16; /*作脉冲信号输入 T0 的使能口*/sbit WD=P17; /*看门狗*/void ini_down
13、(void); /*初始化硬件函数 */uchar decide_AccDecStop(void); /*确定加速或减速处理函数*/void acc_run(void); /*步进电机加速处理函数 */void dec_run(void); /*步进电机减速处理函数 */void stop_stepper(void); /*步进电机停机处理函数 */void check_addr(void); /*地址核对*/void send_data(void); /*发送数据函数*/*=*/*定时器任务分配:T2 负责输出所需频率脉冲( 因 T2 具有 16 位自动重装功能),T1 负责产生波特率,T0
14、 负责输出脉冲数计数*/*在硬件上 p1_5 经过与非门后与 P3_4 连接,然后把与非门输出脉冲输入 T0 计数*/*这样 P3_4 的脉冲输入是可控的,需要用 MCS 52 芯片*/*或者用软件定时,但不准确,且占用 CPU 时间*/*定时器 2 中断的产生取决与 TF2 和 EXF2 的逻辑或。当定时器 2 溢出或是遇到捕捉/重装事件时这些标志位会置位。当系统执行定时器 2 中断服务程序时,这些标志位不会被硬件清除。软件应当解析定时器 2 中断的类型并清除相应的标志位。*/*=*/main() test_s0=0;test_s1=0;test_s1=0x80;test_s0=0x0f;/
15、*=*/interval=0;done_no=0;pulse_counter=0;common_count=0;acc_count=0;dec_count=0;temp_count=0;T0low=0;T0high=0;T2low=0;T2high=0;new_speed_in=0;acc_run_permit=0;dec_run_permit=0;carry_acc=0;carry_dec=0;carry_stop=0;normal_stop=0;test_p=0;check_input_spd=0;first_startup=0;print_permit=0;cmd_in_permit=0
16、;input_order=0;P2_0=0;P2_2=0; /*步进电机的旋转方向待试验后确定 */P1_0=1; /*开机时需要关断串口发送功能 ,需要时再接通,作串口输出信号的使能口,P1_0=0 时接通串口,输出信号*/P1_2=0; /*现在作检测位 ,用仿真机仿真时用该接口*/P1_5=0;P1_6=0; /*开机时需要关闭脉冲信号输入 T0,需要时再接通,P1_6=1 时脉冲信号可以输入 T0*/WD=1; /*看门狗*/ini_down();TF2=0; /*T2 溢出中断需软件清 0*/*-*/doif(address_true=1) address_true=0;check_
17、addr();if (print_permit=1)print_permit=0;send_data();/*完成数据传送后,才恢复为恢复为多机模式,SM2=1*/SM2=1;if(normal_stop=1) normal_stop=0;if(first_startup=1) stop_stepper();else if(new_speed_in=1) new_speed_in=0;/*假定电机从 0 转速开始运动,开机后电机第一次启动的 common_count=1*/if (check_input_spd=1) check_input_spd=0;input_count=interval
18、;/*取得开机后电机第一次启动时, common_count 的值*/if(first_startup=0) common_count=1; if (common_count=1)|(common_count=1)/*decide_AccDecStop()承担太多任务,可能返不回来,导成嵌套过多死机*/*这是单片机 C 语言与 PC 机 C 语言的区别之一*/*decide_AccDecStop()改为“返回执行标志位”*/if(acc_run_permit=1) acc_run_permit=0;acc_run(); if(dec_run_permit=1) dec_run_permit=0
19、;if(first_startup=1) dec_run();WD=!WD; /*看门狗喂狗*/while(1);/*=*/void ini_down(void)EA=1; /*开放总中断*/ES=1; /*开放 serial_0 中断*/*PCON 电源控制, SMOD=0, 串口 0 波特率不加倍(只对用 T1 产生波特率时有效)*/PCON=0x00;/*SCON = 0xd0;*/ /*SCON 工作方式 3, 允许发送, 11 位,可发送第 9 位 1;与主机通信*/SCON = 0xd0;/*多机通信,初始化时,需设置从机的 SM2=l,根据运行要求在程序子函数中设置SM2=0*/
20、*SM2=0;*/ /*暂时设置从机的 SM2=0,与 PC 机通信必须 SM2=0*/SM2=1; /*设置从机的 SM2=1,与主机通信必须 SM2=1*/*T0 在方式 1,16 位,作外部事件计数器(下降沿触发)*/*T1 在方式 2,8 位,常数自动装入*/TMOD=0x25; /*TL1=0xfa;*/*给 serial_0 产生波特率,波特率为 4.8K, 加倍为 9.6K*/*TH1=0xfa;*/TL1=0xfd; /*给 serial_0 产生波特率,波特率为 9.6K, 加倍为 19.2K*/TH1=0xfd;/*T2MOD=00;*/ /*定时器 2:T2OE=0 输出
21、使能位无效;DCEN=0 向上计数器*/T2MOD=00; /*T2CON 中的 C/T2=0,T2 作内部定时器*/*CP/RL2=0,RCLK=0, TCLK=0,16 位自动重装初始值*/T2CON=0x00;EX0=0; /*允许 INT0 中断*/IT0=1; /*INT0 为边沿触发*/EX1=0; /*允许 INT1 中断*/IT1=1; /*INT1 为边沿触发*/PS=1; /*PS(IP.4)(-BCH)串口中断优先级别控制位,PS=1 串口中断为高优先级别*/*注:主程序需要定时器中断服务,所以开放定时器中断*/ET0=0; /*关闭 T/C0 中断*/ET2=0; /*
22、关闭 T/C2 中断*/TR1=1; /* TCON 启动定时器 1*/*T0 作步进电机步数计数器,启动 T/C0 在主程序里设置 */TR0=0; /*停止 T/C0*/*T2 作步进电机脉冲发生器,启动 T/C2 在主程序里设置 */ TR2=0; /*停止 T/C2*/WD=!WD; /*看门狗喂狗*/*=*/void inte_SERIAL() interrupt 4 using 1 /*串口 0 中断服务子程序 */*接收主机地址,核对,才接受指令 */*调试期间先简化程序,不核对地址,直接接收指令 */uchar idata i ;key_in=0;i=0;if(RI) key_
23、in=SBUF; RI=0;if (SM2=1) /*SM2=1,必须有 RB8=1 串口才中断*/*SM2=1,为多机模式, 接收主机地址*/*接收到的字节为地址 */*接收的地址与本机地址比较,判断是否一致*/if(key_in=slave_addr2) /*确认地址完毕,设置 SM2=0,进入单机模式 */SM2=0;address_true=1;if (SM2=0) /*接收主机命令,使从机设置为多机模式*/if(key_in=0xfe) /*接收主机命令引导字节,准备接收主机命令*/cmd_in_permit=1;if(cmd_in_permit=1) input_order=inp
24、ut_order+1;if (input_order=2) /*接收主机命令,使从机开始调节电机*/cmd_in_permit=0;input_order=0;/*interval 代表控制器发给电机的转速期望值*/interval= key_in ;if(interval=0) normal_stop=1; /*太多开关量 ,会有问题*/new_speed_in=1;check_input_spd=1;print_permit=1;WD=!WD; /*看门狗喂狗*/ /*=*/ uchar decide_AccDecStop(void) /*当前转速,在哪里获得?(应该为 T2 定时器当前初
25、值)*/*应该在输出速度脉冲定时器的启动程序里找到 */if(input_count=1) temp_count=common_count; /*开机第一次运行时的处理? */if (input_count=common_count) /*开机第一次运行时,会有问题吗?经过试验,没有*/dec_run_permit=0;acc_run_permit=0;else if(input_count =common_count) acc_count=input_count-common_count; /*加速时,需要增加 T2 初值*/acc_run_permit=1;else if (input_c
26、ount 1) normal_stop=1;WD=!WD; /*看门狗喂狗*/return 0;/*=*/void acc_run(void) /*步进电机加速处理函数 */uint y1,y2;y1=acc_pulse_T2_constcommon_count;/*设置脉冲周期定时器 T2 初值,确定每档步进电机转速*/T2high = (uchar)(y18) ; /*取 y1 的高 8 位*/T2low = (uchar)(y1 /*取 y1 的低 8 位*/TR2 = 0 ;ET2=0; /*关闭 T/C2 中断*/TH2=T2high; /*高 8 位 T2high 送定时器 2 的
27、 TH2*/TL2=T2low; /*低 8 位 T2low 送定时器 2 的 TL2*/RCAP2H=T2high; /*高 8 位 T2high 送定时器 2 的 RCAP2H*/ RCAP2L=T2low; /*低 8 位 T2low 送定时器 2 的 RCAP2L*/ /*设置脉冲周期定时器 T0 初值,确定每档转速步进电机步数*/y2=acc_time_T0_constcommon_count;T0high = (uchar)(y28) ; /*取 y2 的高 8 位*/T0low = (uchar)(y2 /*取 y2 的低 8 位*/TR0 = 0;ET0 = 0; /*关闭 T
28、/C0 中断*/TH0=T0high; /*高 8 位 T0high 送定时器 0 的 TH0*/TL0=T0low; /*低 8 位 T0low 送定时器 0 的 TL0*/*由 acc_run()启动 T2 一次,余下由 T0 中断服务子启动 T2*/TR2 = 1;ET2=1; /*允许 T/C2 中断*/*由 acc_run()启动 T0 一次,余下由 T0 中断服务子启动 T0*/TR0 = 1;ET0=1; /*允许 T/C0 中断*/P1_6=1;common_count+;acc_count-;carry_acc=1;carry_dec=0; carry_stop=0;WD=!
29、WD; /*看门狗喂狗*/*=*/void dec_run(void) /*步进电机减速处理函数 */uint y1, y2;y1=dec_pulse_T2_constcommon_count;/*设置脉冲周期定时器 T2 初值,确定步进电机转速*/T2high = (uchar)(y18) ; /*取 y1 的高 8 位*/T2low = (uchar)(y1 /*取 y1 的低 8 位*/TR2 = 0 ;ET2=0; /*关闭 T/C2 中断*/TH2=T2high; /*高 8 位 T2high 送定时器 2 的 TH2*/TL2=T2low; /*低 8 位 T2low 送定时器 2
30、 的 TL2*/RCAP2H=T2high; /*高 8 位 T2high 送定时器 2 的 RCAP2H*/ RCAP2L=T2low; /*低 8 位 T2low 送定时器 2 的 RCAP2L*/ y2=dec_time_T0_constcommon_count;T0high = (uchar)(y28) ; /*取 y2 的高 8 位*/T0low = (uchar)(y2 /*取 y2 的低 8 位*/TR0 = 0;ET0=0; /*关闭 T/C0 中断*/TH0=T0high; /*高 8 位 T0high 送定时器 0 的 TH0*/TL0=T0low; /*低 8 位 T0low 送定时器 0 的 TL0*/*由 dec_run()启动 T2 一次,余下由 T0 中断服务子启动 T2*/TR2 = 1;ET2=1; /*允许 T/C2 中断*/*由 dec_run()启动 T0 一次,余下由 T0 中断服务子启动 T2*/TR0 = 1;ET0=1; /*允许 T/C0 中断*/P1_6=1;common_count-;dec_count-;carry_acc=0; carry_dec=1; carry_stop=0;WD=!WD; /*看门狗喂狗*/*=*/void stop_stepper(void) /*步进电机停机处理函数 */
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。