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

📄 serial.c

📁 8051单片机上用C写的ps/2的实验程序
💻 C
字号:
/*
黄 clock 5 红
绿 data  1 黑
黑 地    3
*/
#include <reg51.H>
#include <stdio.h>
#include <string.h>
#include "delay.h"

typedef unsigned char UCHAR;
typedef unsigned long  ULONG;
#define TRUE 1
#define FALSE 0

//UCHAR ucData = 0,i=0;
UCHAR gucBuf[16] = {0};
UCHAR* pBuf = gucBuf;
//bit isDataReady=0;
//bit canReceive=1;
sbit P1_0 = P1^0;
sbit P2_0 = P2^0;
sbit CLK_SND = P1^1;
sbit DAT_SND = P1^2;
//sbit CLK_RCV = P3^2;
sbit CLK_RCV = P1^3;
sbit DAT_RCV = P1^0;
ULONG tick = 0, prevtick = 0;
#define LED P0
UCHAR bitCount = 0;

bit checkP(UCHAR fr);
void rcvBit(UCHAR i);
void exint0_isr(UCHAR i);

idata UCHAR bTmp[80]={0};
UCHAR frCount = 0;
UCHAR rcvFrCount = 0;
/*
1) Set/Reset Data
2) Delay 20 microseconds
3) Bring Clock low
4) Delay 40 microseconds
5) Release Clock
6) Delay 20 microseconds
*/
void sendBit(bit b)
{
	//bTmp[frCount]=b;
	//frCount++;

	DAT_SND=b;
	delay_u(20);
	CLK_SND=0;
	delay_u(40);
	CLK_SND=1;
	delay_u(20);
}

/*
1) Wait for Clock = high.
2) Delay 50 microseconds.
3) Clock still = high?
No--goto step 1
4) Data = high?
No--Abort (and read byte from host)
5) Delay 20 microseconds (=40 microseconds to the time Clock is pulled low in sending the start bit.)
6) Output Start bit (0) \ After sending each of these bits, test
7) Output 8 data bits > Clock to make sure host hasn't pulled it
8) Output Parity bit / low (which would abort this transmission.)
9) Output Stop bit (1)
10) Delay 30 microseconds (=50 microseconds from the time Clock is released in sending the stop bit)
*/
void sendFrame(UCHAR fr)
{
	UCHAR i;
	while(!CLK_SND)
	{
		//delay_u(50);
	}
	//if(!CLK_SND) return;
	if(!DAT_SND) return;
	delay_u(20);
	sendBit(0);
	for(i=0;i<8;i++)
	{
		sendBit(fr&(1<<i));
	}
	sendBit(checkP(fr));
	sendBit(1);
	delay_u(30);
}

bit checkP(UCHAR fr)//奇校验
{
	bit b=1;
	UCHAR i=0;
	for(;i<8;i++)
	{
		b^=(fr&0x01);
		fr>>=1;
	}
	return b;
}

void clock_init() reentrant using 0
{
	TR0=0;
	TF0=0;
	TH0=0xDB;//10ms
	TL0=0xF0;
	//TH0=0XFC;
	//TL0=0X18;
	TR0=1;
}

bit rcvFrame(UCHAR* pucData)
{
	UCHAR i;
	UCHAR ucData = 0,ucDataTmp = 0;
	//while(CLK_RCV);
	//if(CLK_RCV) return FALSE;//时钟为高,表明没有数据
	//ucData = 0;

	//首位
	while(CLK_RCV);//等待时钟线变低
	while(!CLK_RCV);//等待时钟线变高	

	//8个数据位
	for(i=0;i<8;i++)
	{
		while(CLK_RCV);//等待时钟线变低
		ucDataTmp = ucDataTmp<<1;
		ucDataTmp|=DAT_RCV;
		while(!CLK_RCV);//等待时钟线变高
	}

	//奇校验位
	while(CLK_RCV);//等待时钟线变低
	while(!CLK_RCV);//等待时钟线变高	

	//末位
	while(CLK_RCV);//等待时钟线变低
	while(!CLK_RCV);//等待时钟线变高
	
	CLK_RCV = 0;//拉低时钟抑制发送,进行字节序转换
	for(i=0;i<8;i++)
	{
		ucData=ucData<<1;
		ucData|=(ucDataTmp&0x01);
		ucDataTmp=ucDataTmp>>1;
	}
	*pucData = ucData;
	printf("\r\n%bu,0x%bx",ucData,ucData);
	CLK_RCV = 1;
	return TRUE;
}
/*
void rcvBit(UCHAR i)
{
	while(CLK_RCV);//等待时钟线变低
	//CLK = 0;//有数据,拉低时钟,抑制键盘发送,进行处理
	//exint0_isr(i);
	if(1<=i&&i<=8)
	{
		ucData = ucData<<1;
		ucData|=DAT_RCV;
	}
	//CLK = 1;//处理完一位,释放时钟
	while(!CLK_RCV);//等待时钟线变高	
}*/

void main(void)
{
	//long j;
	//unsigned char a;
	//UCHAR j;
	//UCHAR ucBuf[16];
	UCHAR ucData;
	bit bRet;
	
	//sendFrame(0x87);

	SCON = 0xD8; //串口方式1,允许接收
	TMOD |= 0x20; //定时器1 定时方式2
	TH1 = 0xFD; //12MHz 9600 波特率
	TL1 = 0xFD;
	TI = 1;
	TR1 = 1; //启动定时器

	//定时器0初始化
	TMOD|=0X01;
	TF0=0;
	clock_init();
	ET0=1;	
	EA = 1;
	IT0=1;
	EX0=1;



	while(1)
	{
		//CLK_RCV =1;
		bRet = rcvFrame(&ucData);
		sendFrame(ucData);
		//CLK_RCV = 0;
		//if(bRet)
		//	printf("\r\n%bu,0x%bx",ucData,ucData);
		/*sendFrame(0x1c);
		delay_u(200);
		sendFrame(0xf0);
		delay_u(200);
		sendFrame(0x1c);
		delay_u(200);*/
		//while(!isDataReady);

		/*
		if(!P2_0)//50ms打印一次
		{
			EA=0;
			memcpy(ucBuf,gucBuf,sizeof(ucBuf));
			EA=1;

			for(j=0;j<rcvFrCount;j++)
			{
				//if(ucBuf[j]==0) break;

				printf("\r\n%bu,0x%bx",ucBuf[j],ucBuf[j]);
				EA=0;
				pBuf = gucBuf;
				memset(gucBuf,0,sizeof(gucBuf));
				rcvFrCount = 0;
				EA=1;
			}
		}*/
		//ucData=0;
		//isDataReady=0;
		//i=0;//启动接收


		/*if(!P2_0) i=0;
		P0=ucData;*/
	};

}

void clk_int() interrupt 1 using 0
{
	EA=0;
	tick++;
	//if(0==(tick%100)) printf("1");
	clock_init();
	EA=1;
}


//idata char c[100] = {0};
#if 0
void exint0_isr(UCHAR i) //interrupt 0 using 0
{
	//CLK_RCV = 0;
	EA=0;
	bitCount++;
	LED=bitCount;
	//c[0]=0;
	/*if(strlen(c)>90)
		printf("%s",c);
	if(tick-prevtick>5)//超过50ms,新启一帧
	{
		strcat(c,"\r\n");
	}
	if(P1_0)
		strcat(c,"1");
	else
		strcat(c,"0");
	prevtick = tick;*/
	/*
	if(tick-prevtick>5)//超过50ms,新启一帧
	{
		i=0;
		ucData=0;
	}
*/
	//while(!canReceive)
	
	if(0==i) 
	{	
		//prevtick = tick;
		//if(0!=DAT_RCV) goto RET;//首位应为0,否则返回继续等待首位
	}
	else if(1<=i&&i<=8)
	{
		if(DAT_RCV)
		{
			ucData|=(1<<(i-1));
		}
		else
		{
			ucData|=(0<<(i-1));
		}
		/*if(8==i)
		{
			printf("\r\n%bu,0x%bx",ucData,ucData);
		}*/
	}
	else if(9==i)//奇偶检验位
	{
	}
	else if(10==i)//停止位
	{
		/*if(1!=P1_0)
		{
			return;
			//printf("\r\n接受停止位出错!");
		}*/
		//ucData=0;
		//i=0;
		//isDataReady = 1;
		/**pBuf = ucData;
		rcvFrCount++;
		pBuf++;*/
		//ucData=0;
		//i=0;//启动接收
		goto RET;
	}
	else goto RET;
	//i++;
	
RET:
	EA=1;
	//CLK_RCV = 1;
	return;
	
}
#endif

/*void delay_u(UCHAR t)
{
	UCHAR i;
	for(i=0;i<t;i++);	
}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -