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

📄 cmpmnck.c

📁 51单片机模拟串口
💻 C
字号:
//本程序为Franklin/keil  C51源程序,可以在所有51系列(或兼容)单片机中运行。
//完成功能:使用任意2个引脚模拟串行接口,实现对触摸屏控制器数据的接收
//          和对KY系列智能液晶终端进行控制.
//程序中给出了设计方法,通过修改TIMEzq使本程序适用于各种晶振及各种波特率.
//本例为:当通讯波特率=9600Hz,单片机晶振=18.432MHz时,TIMEzq=50
//        使用P1.0模拟串口输入,使用P1.1模拟串口输出,使用P1.2检测"忙"信号.
//本程序在Wave For windows ver 2.80仿真软件编译成功。
//在AT89C51(9600Hz,18.432MHz)中运行通过.运行结果是:将接收的XY坐标在屏幕左上角显示并划点.
//=========================================================================================
#include "reg51.h"
#define  uchar     unsigned char
#define  uint     unsigned int
sbit     CMP_DATA   =P1^0; //由此接收触摸屏发出的串行数据,可以使用任一引脚.
sbit     ZD_DATA   =P1^1; //向液晶终端输出串行数据,使用模拟串口输出数据时,可以使用任一引脚.
sbit     ZD_BUSY   =P1^2; //接收液晶终端发来的"忙"(BUSY)信号,可以连接于任意一位输入引脚上.
//=========================================================================================
bdata char  DATA; 
sbit    mb0=DATA^0;
sbit    mb1=DATA^1;
sbit    mb2=DATA^2;
sbit    mb3=DATA^3;
sbit    mb4=DATA^4;
sbit    mb5=DATA^5;
sbit    mb6=DATA^6;
sbit    mb7=DATA^7;
//=========================================================================================
#define  TIMEzq    50   //修改TIMEzq可使本程序适用于各种晶振及各种波特率.计算方法见文件尾。
//本例:AT89C51(9600Hz,18.432MHz)时 TIMEzq=50
//=========================================================================================
//延时函数TIME()
//为了得到精确的延时时间,不要修改本函数的形式,绝对不要修改!
void     TIME(void)
  {
  uchar i;
  for(i=0;i<TIMEzq;i++);
  }
//=========================================================================================
//延时函数TIME1B()
//为了得到精确的延时时间,不要修改本函数的形式,绝对不要修改!
void     TIME1B(void)
  {
  uchar i;
  for(i=0;i<(TIMEzq/2);i++);
  }
//=========================================================================================
//将sj(仅低4位有效)转换为对应的ASCII码
uchar zh16(uint sj)
{
  uchar sj1;
  sj1=sj&0xf;
  if (sj1>=0x0a) sj1=sj1+7;
  sj1=sj1+0x30;
  return sj1;
}
//=========================================================================================
//向终端发送一字节数据
//为了得到精确的延时时间,不要修改本函数的形式,绝对不要修改!
void FSsj(uchar sj)
  {
	 while(ZD_BUSY);
	 ZD_DATA =0;       //起始位=0
	 TIME();
	 ZD_DATA =sj&1;    //D0;12+24+24+24
	 TIME();
	 ZD_DATA =sj&2;    //D1
	 TIME();
	 ZD_DATA =sj&4;    //D2
	 TIME();
	 ZD_DATA =sj&8;    //D3
	 TIME();
	 ZD_DATA =sj&0x10; //D4
	 TIME();
	 ZD_DATA =sj&0x20; //D5
	 TIME();
	 ZD_DATA =sj&0x40; //D6
	 TIME();
	 ZD_DATA =sj&0x80; //D7
	 TIME();
	 ZD_DATA =0;       //奇偶位=0
	 TIME();
	 ZD_DATA =1;       //停止位=1
	 TIME();
  }
//=========================================================================================
//用CMP_DATA模拟串口接收数据
//为了得到精确的延时时间,不要修改本函数的形式,绝对不要修改!
//读触摸屏1个字节
uchar JSsj(void)
{
  	while(CMP_DATA);	//CMP_DATA=1,则等待.
    	TIME1B();
    	TIME();
    	mb0=CMP_DATA;	//D0
    	TIME();
    	mb1=CMP_DATA;	//D1
    	TIME();
    	mb2=CMP_DATA;	//D2
    	TIME();
    	mb3=CMP_DATA;	//D3
    	TIME();
    	mb4=CMP_DATA;	//D4
    	TIME();
    	mb5=CMP_DATA;	//D5
    	TIME();
    	mb6=CMP_DATA;	//D6
    	TIME();
    	mb7=CMP_DATA;	//D7
    	TIME();
    	TIME();
        return DATA;
}
//=========================================================================================
void main(void)
  {
        uchar zj2,zj3,zj4,zj5;  //接收触摸屏数据的第2,3,4,5字节。
        uint Xzb,Yzb;//X坐标在Xzb中,Y坐标在Yzb中
        CMP_DATA=1;
        ZD_BUSY=1;
        ZD_DATA=1;
//清屏幕(黑色)
        FSsj(0X1B);
        FSsj(0X51);
        FSsj(0);
//循环接收数据,完成显示和划点任务
        while(1)
        {
        while(1){if(JSsj()==0xa0)break;}
        zj2=JSsj();
        zj3=JSsj();
        zj4=JSsj();
        zj5=JSsj();
//X坐标在Xzb中,Y坐标在Yzb中
    	Xzb=zj2;
    	Xzb=Xzb<<6;
    	Xzb=Xzb+zj3;
    	Yzb=zj4;
    	Yzb=Yzb<<6;
    	Yzb=Yzb+zj5;
//在左上角显示收到数据
        FSsj(0X1B);
        FSsj('z');
        FSsj(0X90);
        FSsj(0);
        FSsj(0X80);
        FSsj(0);
        FSsj('X');
        FSsj('=');
        FSsj(zh16(Xzb>>8));
        FSsj(zh16(Xzb>>4));
        FSsj(zh16(Xzb));
        FSsj('H');
        FSsj(',');
        FSsj('Y');
        FSsj('=');
        FSsj(zh16(Yzb>>8));
        FSsj(zh16(Yzb>>4));
        FSsj(zh16(Yzb));
        FSsj('H');
//XY坐标除以4后划点
        Xzb=Xzb/4;
        Yzb=Yzb/4;
        FSsj(0X1B);//划点指令
        FSsj('d');
        FSsj(0XF0);//划白点
        FSsj(Xzb);
        FSsj(0);
        FSsj(Yzb);
        }
  }
//=========================================================================================
//例1:当通讯波特率F=9.6KHz,单片机晶振Z=18.432MHz时,TIMEzq=50
//计算方法:
//当波特率为9.6KHz时,每个二进制位的宽度为104uS.振荡周期数zq=(1000/9.6)*18.432MHz=1920个振荡周期
//调用本函数的其它指令执行时间为(12+24*3+12*3)=120个振荡周期.
//执行每个循环需要(12+24=36)个振荡周期,则TIMEzq=(zq-120)/36=(1920-120)/36=50
//即:TIMEzq=[((1000/F)*Z)-120]/36=50
//-------------
//例2:当通讯波特率F=4.8KHz,单片机晶振Z=18.432MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=103
//-------------
//例3:当通讯波特率F=19.2KHz,单片机晶振Z=18.432MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=23
//-------------
//例4:当通讯波特率F=9.6KHz,单片机晶振Z=12.000MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=31
//-------------
//例5:当通讯波特率F=4.8KHz,单片机晶振Z=12.000MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=66
//-------------
//例6:当通讯波特率F=19.2KHz,单片机晶振Z=12.000MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=14
//-------------
//例7:当通讯波特率F=9.6KHz,单片机晶振Z= 6.000MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=14
//-------------
//例8:当通讯波特率F=9.6KHz,单片机晶振Z=11.0592MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=28
//-------------
//例9:当通讯波特率F=9.6KHz,单片机晶振Z=22.1184MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=60
//-------------
//例10:当通讯波特率F=9.6KHz,单片机晶振Z=24.0000MHz时:
//     TIMEzq=[((1000/F)*Z)-120]/36=66
//------------

⌨️ 快捷键说明

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