📄 newserver507.c
字号:
//主机发测试程序,2008-5-7-22:40
//键盘测试程序
//主机发送协议:5字节定长,7E(开始),00(命令字),地址高,地址低,7F结束。其中地址位用位的位置来表示。
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SL_NUM 16 //定义从几个数 change:可以通过拨吗开关设置从机数量
#define DELAY 100 //change定义轮询时主机等待从机返回数据的时间。超过这个时间主机将和下一个从机通讯。单位ms
#define SETMODE 0X10 //设置 工作状态
#define STARTMODE 0X20 //开始 工作状态。
#define TESTMODE 0X30 //测试 工作状态。
#define SWAITMODE 0X80 //等待 工作状态。
#define OVERMODE 0X00 //结束 工作状态。
#define RESETCOMMAND 0X01 //复位命令,
#define STARTCOMMAND 0X02 //开始命令,此时后两个字节每一位(第0位除外。)表示每一个从机,从第1位,到第十位。
#define STOPCOMMAND 0X03 //停止命令,未用到。
#define TESTCOMMAND 0X04 //测试命令。
#define ASKCOMMAND 0X06 //查询命令。
#define LAMPCOMMAND 0X09 //点亮从机灯命令。
#define ANSWERCOMMAND 0XA0 //从机回应命令。
//键盘
#define NUM1 0x80
#define NUM2 0x40
#define NUM3 0x20
#define NUM4 0x10
#define NUM5 0x08
#define NUM6 0x7f
#define NUM7 0x3f
#define NUM8 0x1f
#define NUM9 0x0f
#define NUM10 0x07
#define A_M 0x04
#define START 0x02
#define TEST 0x03
#define RST 0x01
//主机键盘灯 每一2进制位的1代表亮
//主机键盘灯 每一2进制位的1代表亮
#define NUM1_L 0x0080
#define NUM2_L 0x0040
#define NUM3_L 0x0020
#define NUM4_L 0x0010
#define NUM5_L 0x0008
#define NUM6_L 0x8000
#define NUM7_L 0x4000
#define NUM8_L 0x2000
#define NUM9_L 0x1000
#define NUM10_L 0x0800
#define Number_ALL_light 0xf8 //所有数字灯亮 数字灯均为同一数。
#define Number_ALL_dark 0x07 //所有数字灯灭
//硬件定义
sbit INT=P3^2; //中断脚用于从机向主机发送数据的请求
#define key_row P1//键盘行
sbit KEY_GR1=P2^0; //键盘行 1
sbit KEY_GR2=P2^1; //键盘行 2
sbit LED_GR1=P2^6; //灯行1
sbit LED_GR2=P2^7; //灯行2
sbit R_T =P2^2;
sbit R_T1 =P2^3;
//状态定义
#define NOP {_nop_();_nop_();_nop_();_nop_();}
#define RESET_KL {LED_GR1=LED_GR2=KEY_GR1=KEY_GR2=1; _nop_();}
#define LED1_LIGHT {KEY_GR1=KEY_GR2=LED_GR2=1;LED_GR1=0;_nop_();}
#define LED2_LIGHT {KEY_GR1=KEY_GR2=LED_GR1=1;LED_GR2=0;_nop_();}
#define KEY_ENABLE {LED_GR2=LED_GR1=1;key_row=0XFF;KEY_GR2=KEY_GR1=0;_nop_();}
#define KEY1_ENABLE {KEY_GR2=LED_GR2=LED_GR1=1;key_row=0XFF;KEY_GR1=0;_nop_();}
#define KEY2_ENABLE {LED_GR1=KEY_GR1=LED_GR2=1;key_row=0XFF;KEY_GR2=0;_nop_();}
//#define CPL_BIT(x,y) ((x)!=0x0001<<(y))
#define Recive_485 {R_T=R_T1=0;}
#define Send_485 {R_T=R_T1=1;}
//变量定义
uchar code key_val[14]={NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9,NUM10,A_M,START,TEST,RST};
//uint code ledVal[]={NUM1_L,NUM2_L,NUM3_L,NUM4_L,NUM5_L,NUM6_L,NUM7_L,NUM8_L,NUM9_L,NUM10_L};
uchar sendata[5]={0x7e,0x00,0x00,0x00,0x7f};//向外发送的数据。0x7E+命令+机器编号+数据+0x7F
uchar ReceiveData[5]={0x00,0x00,0x00,0x00,0x00};//接收的数据。0x7E+命令+机器编号+数据+0x7F
bit scan=1; //动态扫描5MS一次。
bit led_bit; //扫LED换行标志
uchar data time_5ms;
uchar data time_s;
uchar data time_coms;//以5MS为单位测试有无从机返回标志。
uchar bdata disp_bufh; //位寻址位 显示缓冲区。
uchar bdata disp_bufl;
bit key_bit;
uchar data key_time;
uchar data key_buffer; //键值存贮区
uchar data key_state; //多次按键标志
uchar data key_hurry=0;
uchar bdata out_n_bufh; //输出禁止、允许标志存贮,位寻址。每一位代表一个从机,从第1位至第十位。0位无效。
uchar bdata out_n_bufl;
uchar data work_state=0; //工作状态标志,以上面定义为准。
uchar data task_count; //轮询和查询时用的计数器即当前的从机号码
uchar data ask_count; //轮询次数,容错控制,超过3次视为无效。
bit slave_int_bit=0; //INT引脚下降沿有效,若开始抢答后引起INT中断置位,表示有从机引起的抢答。是哪个从机要等待查询。
bit comm_rec_bit=0; //串口接收成功标志,接收成功置位。
bit com_answer_bit=0; //从机应答标志。
bit com_ask_bit=0; //主机已发送标志位。未发送为0 ,已发送则置1。
sbit LED_N1=disp_bufh^7; //显示缓冲区各位。
sbit LED_N2=disp_bufh^6;
sbit LED_N3=disp_bufh^5;
sbit LED_N4=disp_bufh^4;
sbit LED_N5=disp_bufh^3;
sbit LED_N6=disp_bufl^7;
sbit LED_N7=disp_bufl^6;
sbit LED_N8=disp_bufl^5;
sbit LED_N9=disp_bufl^4;
sbit LED_N10 =disp_bufl^3;
sbit LED_AM =disp_bufh^2;
sbit LED_START=disp_bufh^1;
sbit LED_TEST =disp_bufl^2;
sbit LED_RST =disp_bufl^1;
sbit OUT_N1=out_n_bufl^1; //用于开始命令时输出各从机位的位标志。
sbit OUT_N2=out_n_bufl^2;
sbit OUT_N3=out_n_bufl^3;
sbit OUT_N4=out_n_bufl^4;
sbit OUT_N5=out_n_bufl^5;
sbit OUT_N6=out_n_bufl^6;
sbit OUT_N7=out_n_bufl^7;
sbit OUT_N8=out_n_bufh^0; //第八个。
sbit OUT_N9=out_n_bufh^1;
sbit OUT_N10=out_n_bufh^2;
//程序开始
//由于STC比ATMEL快近4位,暂时这样用估计接近1MS
delay(uchar ms)
{
uchar i,t;
for (t=0;t<ms;t++)
{
for (i=0;i<250;i++)
{
NOP
}
}
}
//初始化子程序,包含各、寄存器初始化。
void initMCU(void)
{
/*与初始化有关的寄存器
计时控制寄存器 TCON TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
与中断相关 TF1 TF0 IE1 IT1 IE0 IT0
定时器相关寄存器 //TH0 //TL0 //TH1 //TL1
计时工作方式 TMOD GATE C/T M1 M0 GATE C/T M1 M0
中断允许寄存器 IE EA ES ET1 EX1 ET0 EX0
串口中断寄存器 SCON SM0 SM1 SM2 REN TB8 RB8 TI RI
中断优先级 IP PS PT1 PX1 PT0 PX0
特殊功能寄存器 PCON SMOD
*/
EA=0;
TMOD=0x21; //置定时器1为方式2,定时器0为方式1
SCON=0x50; //MODE 1 ,ALLOW RECEIVE
TH1=TL1=0x0Fd;//9600 TH1=TL1=0X0FA;//4800 //定时器1做为波特率发生器
TL0=0x00;TH0=0xee;
TR0=1; //TCON^4 定时器0开始运行
TR1=1; //TCON^6 定时器1开始运行
PS=1; //IP^4 串行通信中断优先级
TI=0; //SCON^1 复位发送位
REN=1; //SCON^4 允许接收
IT0=1; //外部中断0为边沿触发方式。
ES=1; //允许串口中断以接收数据
EX0=0; //关INT1中断用于从机向主机发送通讯请求 ,初始化时必须关闭中断,待必要时才能打开。
ET0=1; //开定时器0中断5MS用于扫描显示
EA=1; //IE= 0x80;中断使能
}
void SEND_DATA(void)
{
uchar i;
TI=0;
Send_485
delay(1);
for(i=0;i<5;i++)
{
SBUF=sendata[i];
while(TI==0) ;
TI=0;
NOP
}
Recive_485
}
//点亮某个数字灯
LEDN_LIGHT(uchar n)
{
if (n<=10)
{
switch (n)
{
case 1:
LED_N1=1;
break;
case 2:
LED_N2=1;
break;
case 3:
LED_N3=1;
break;
case 4:
LED_N4=1;
break;
case 5:
LED_N5=1;
break;
case 6:
LED_N6=1;
break;
case 7:
LED_N7=1;
break;
case 8:
LED_N8=1;
break;
case 9:
LED_N9=1;
break;
case 10:
LED_N10=1;
break;
}
}
}
//键盘扫描关显示扫键长按键。
//显示的是disp_buffer的值。
void LED_KEY()
{
if(scan)
{
scan=0;
RESET_KL
KEY_ENABLE //关显示,测键。
if(key_row!=0xff) //判断按键是否被按下
{
key_time++; //5MS加一次。
switch (key_state) //是否单次
{
case 0:
if (key_time>20) //按键去抖动100MS
{
key_state=1;
key_bit=1;
KEY1_ENABLE
if (key_row!=0xff)
{
key_buffer=~key_row;
}
else
{
KEY2_ENABLE
if (key_row!=0xff)
{
key_buffer=~key_row-1;
}
}
}
break;
case 1:
if (key_time>100) //多次按键间隔时间为400MS
{
key_state=0;
key_time=20;
}
break;
default:
break;
}
}
else
{
key_state=0;
key_time=0;
}
RESET_KL
//显示
if(led_bit)
{
key_row=disp_bufh; //显示第一行的值
NOP
led_bit=0;
LED1_LIGHT
}
else
{
key_row=disp_bufl; //另5MS显示第二行的值
NOP
led_bit=1;
LED2_LIGHT
}
}
}
//键值处理
void KEY_PROCESS()
{
uchar i;
if (key_bit)
{
key_bit=0;
for(i=0;i<14;i++)
{
if (key_buffer==key_val[i]) //各数字键及功能键。
{
switch (i)
{
case 0:
if (work_state==OVERMODE)
{
LED_N1=!LED_N1;
OUT_N1=!OUT_N1;
}
else if (work_state==STARTMODE)
{
// LED_N1=1;
key_hurry=1;
}
break;
case 1:
if (work_state==OVERMODE)
{
LED_N2=!LED_N2;
OUT_N2=!OUT_N2;
}
else if (work_state==STARTMODE)
{
// LED_N2=1;
key_hurry=2;
}
break;
case 2:
if (work_state==OVERMODE)
{
LED_N3=!LED_N3;
OUT_N3=!OUT_N3;
}
else if (work_state==STARTMODE)
{
// LED_N3=1;
key_hurry=3;
}
break;
case 3:
if (work_state==OVERMODE)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -