⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 newserver507.c

📁 受人之托制作的单片机抢答器。很稳定。但成本高些。
💻 C
📖 第 1 页 / 共 2 页
字号:
//主机发测试程序,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 + -