C51单片机串口通信之上位机交互

发布者:等放假的Lwj最新更新时间:2018-07-15 来源: eefocus关键字:C51  单片机  串口通信  上位机交互 手机看文章 扫描二维码
随时随地手机看文章

概述:上位机(PC机)向MCU发送指令,MCU串口接收指令并根据列表发送响应。


 


全局变量声明


#include


BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用

UINT nAddress;//ROM中地址计数

UINT nTimeOut;//超时计数

ProWork pw;//编程器一般操作


 


1 定时器延时


1.1 微秒级


void Delay_us(BYTE nUs)//微秒级延时<255us

{

     TH0=0;

     TL0=0;

     TR0=1;

     while(TL0

     TR0=0;

}


分析:


定时器初始值归零,自增1次约1us。


打开定时器中断,BYTE有效值为0~255,因此TL


最后关闭定时器中断。


1.2 毫秒级


void Delay_ms(UINT nMs)   //毫秒级的延时<65535ms

{

     UINT n=0;

     TR0=1;

     while(n

     {

          TH0=0;

          TL0=20;

          while(TH0<4);


           n++;

      }


      TR0=0;


}


TH自增1,即TL自增255,故TH自增4次约1ms,其他同微秒级。


 


2 等待上位机命令


BOOL WaitComm() //等待上位机的命令,18字节

{

 BYTE n=0;

 RI=0;


//*****1******

 while(!RI){}   //等待第一个字节 

 ComBuf[n]=SBUF;

 RI=0;

 n++;


 //*****2******

 for(n;n<=17;n++) 


{

  nTimeOut=0;

  while(!RI)

  {

     nTimeOut++;

     if(nTimeOut>10000)       return 0;     //后17个字节都有超时限制 

  }

  ComBuf[n]=SBUF;

  RI=0;

 }

 return 1;

}


**1** 上位机发送第一个字节,接收中断,接收字符存入ComBuf数组;软件置零,继续接收下一字节。


**2** 下一字节要若在超时计数nTimeOut自增超过1W,则返回0,不再接收;未超时,则把剩下17字节依次存入ComBuf数组。


 


3 等待上位机回应


BOOL WaitResp()//等待上位机回应,1字节,有超时限制 

{

       nTimeOut=0;

       RI=0;

       while(!RI)

       {

            nTimeOut++;

            if(nTimeOut>50000) 

            {

                  return 0;

            }

        }

       RI=0;

       ComBuf[0]=SBUF;

       return 1;

}


上位机在5Wus内回应,存入ComBuf。


 


4 写器件等待上位机,与等待上位机命令有区别


BOOL WaitData()    //写器件时等待上位机数据,18字节,有超时限制 

{

        BYTE n;

        RI=0;

        for(n=0;n<=17;n++)

        {

             nTimeOut=0;

             while(!RI)

             {

                 nTimeOut++;

                 if(nTimeOut>10000)

                 {

                     return 0;

                 }

             }

             RI=0;

             ComBuf[n]=SBUF;

        }

        return 1;

}


所有18字节均有超时限制


 


6 把Com数组内容发送到上位机,回应操作完成


void SendData()   //发送数据或回应操作完成,18字节

{

         BYTE n=0;

         for(n;n<=17;n++)

         {

               TI=0;

               SBUF=ComBuf[n];

               while(!TI){}

               TI=0;

         }

}


 


7  写器件对上位机回应


void SendResp()//回应上位机1个字节,在写器件函数中使用

{

         TI=0;

         SBUF=ComBuf[0];

         while(!TI){}

         TI=0;

}


 


8 读特征字


void ReadSign()  //读特征字

{

      pw.fpReadSign();

      SendData();   //通知上位机,送出读出器件特征字

}


读取PW特殊寄存器


 


 


 


 


附一:源码


//Easy 51Pro编程器主程序,负责通讯,管理编程操作

///////////////////////////////////////////////////////////////////////////////////////////////////


#include


BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用

UINT nAddress;//ROM中地址计数

UINT nTimeOut;//超时计数

ProWork pw;//编程器一般操作


void Delay_us(BYTE nUs)//微秒级延时<255us

{

TH0=0;

TL0=0;

TR0=1;

while(TL0

{

}

TR0=0;

}


void Delay_ms(UINT nMs)//豪秒级的延时<65535ms

{

UINT n=0;

TR0=1;

while(n

{

TH0=0;

TL0=20;

while(TH0<4)

{

}

n++;

}

TR0=0;

}


BOOL WaitComm()//等待上位机的命令,18字节

{

BYTE n=0;

RI=0;

while(!RI){}//等待第一个字节

ComBuf[n]=SBUF;

RI=0;

n++;

for(n;n<=17;n++)

{

nTimeOut=0;

while(!RI)

{

   nTimeOut++;

   if(nTimeOut>10000)//后17个字节都有超时限制 

    return 0;

}

ComBuf[n]=SBUF;

RI=0;

}

return 1;

}


BOOL WaitResp()//等待上位机回应,1字节,有超时限制 

{

nTimeOut=0;

RI=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>50000) 

{

   return 0;

}

}

RI=0;

ComBuf[0]=SBUF;

return 1;

}


BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制 

{

BYTE n;

RI=0;

for(n=0;n<=17;n++)

{

nTimeOut=0;

while(!RI)

{

   nTimeOut++;

   if(nTimeOut>10000)

   {

    return 0;

   }

}

RI=0;

ComBuf[n]=SBUF;

}

return 1;

}


void SendData()//发送数据或回应操作完成,18字节

{

BYTE n=0;

for(n;n<=17;n++)

{

TI=0;

SBUF=ComBuf[n];

while(!TI){}

TI=0;

}

}


void SendResp()//回应上位机1个字节,在写器件函数中使用

{

TI=0;

SBUF=ComBuf[0];

while(!TI){}

TI=0;

}


void SetVpp5V()//设置Vpp为5v

{

P3_4=0;

P3_3=0;

}


void SetVpp0V()//设置Vpp为0v

{

P3_3=0;

P3_4=1;

}


void SetVpp12V()//设置Vpp为12v

{

P3_4=0;

P3_3=1;

}


void RstPro()//编程器复位

{

pw.fpProOver();//直接编程结束

SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同

}


void ReadSign()//读特征字

{

pw.fpReadSign();

SendData();//通知上位机,送出读出器件特征字

}


void Erase()//擦除器件

{

pw.fpErase();

SendData();//通知上位机,擦除了器件

}


void Write()//写器件

{

BYTE n;

pw.fpInitPro();//编程前的准备工作

SendData();//回应上位机表示进入写器件状态,可以发来数据

while(1)

{

if(WaitData())//如果等待数据成功

{

   if(ComBuf[0]==0x07)//判断是否继续写

   {

    for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块

    {

     if(!pw.fpWrite(ComBuf[n]))//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数

     {

      pw.fpProOver();//出错了就结束编程

      ComBuf[0]=0xff;

      SendResp();//回应上位机一个字节,表示写数据出错了

      WaitData();//等待上位机的回应后就结束

      return; 

     }

     nAddress++;//下一个单元

    }

    ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续

    SendResp();

   }

   else if(ComBuf[0]==0x00)//写器件结束

    break;

   else//可能是通讯出错了

   {

    pw.fpProOver();

    return;

   }

}

else//等待数据失败

{

   pw.fpProOver();

   return;

}

}

pw.fpProOver();//编程结束后的工作

Delay_ms(50);//延时等待上位机写线程结束

ComBuf[0]=0;//通知上位机编程器进入就绪状态

SendData();

}


void Read()//读器件

{

BYTE n;

pw.fpInitPro();//先设置成编程状态

SendData();//回应上位机表示进入读状态

while(1)

{

if(WaitResp())//等待上位机回应1个字节

{

   if(ComBuf[0]==0)//ComBuf[0]==0表示读结束

   {

    break;

   }

   else if(ComBuf[0]==0xff)//0xff表示重发

   {

    nAddress=nAddress-0x0010;

   }

   for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块

   {

    ComBuf[n]=pw.fpRead();//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数

    nAddress++;//下一个单元

   }

   ComBuf[0]=6;//向上位机发送读出的数据块

   SendData();

}

else

   break;//等待回应失败


}

pw.fpProOver();//操作结束设置为运行状态

ComBuf[0]=0;//通知上位机编程器进入就绪状态

SendData();

}


void Lock()//写锁定位

{

pw.fpLock();

SendData();

}


///////////////////////////////////////////////////////////////////////////////////////////////////

//所支持的FID,请在这里继续添加

///////////////////////////////////////////////////////////////////////////////////////////////////

extern void PreparePro00();//FID=00:AT89C51编程器

extern void PreparePro01();//FID=01:AT89C2051编程器

extern void PreparePro02();//FID=02:AT89S51编程器


void main()

{

SP=0x60;

SetVpp5V();//先初始化Vpp为5v

SCON=0x00;

TCON=0x00;

//PCON=0x00;//波特率*2

IE=0x00;

//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0

//        0    0   1 0   0    0   0 1

TMOD=0x21;//T0用于延时程序

TH1=0xff;

TL1=0xff;//波特率28800*2,注意PCON

//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI

    //        0   1   0   1   0   0 0 0

SCON=0x50;

TR1=1;

Delay_ms(1000);//延时1秒后编程器自举

ComBuf[0]=0;

SendData();

while(1)//串口通讯采用查询方式

{

if(!WaitComm())//如果超时,通讯出错

{

   Delay_ms(500);

   ComBuf[0]=0;//让编程器复位,使编程器就绪

}

switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针

{

   case 0://at89c51编程器

    PreparePro00();

    break;

   case 1://at89c2051编程器

    PreparePro01();

    break;

   case 2://at89s51编程器

    PreparePro02();

    break;

   //case 3:支持新器件时,请继续向下添加

   // break;

   //case 4:

   // break;

   default:

    ComBuf[0]=0xff;

    ComBuf[1]=0xff;//表示无效的操作

    break;

}

switch(ComBuf[0])//根据操作ID跳到不同的操作函数

{

   case 0x00:

    RstPro();//编程器复位

    break;

   case 0x01:

    ReadSign();//读特征字

    break;

   case 0x02:

    Erase();//擦除器件

    break;

   case 0x03:

    Write();//写器件

    break;

   case 0x04:

    Read();//读器件

    break;

   case 0x05:

    Lock();//写锁定位

    break;

   default:

    SendData();

    break;

}

}

}


关键字:C51  单片机  串口通信  上位机交互 引用地址:C51单片机串口通信之上位机交互

上一篇:(C51学习五)单片机与PC通过串口通信
下一篇:51单片机与PC进行串口通信

推荐阅读最新更新时间:2024-03-16 16:08

ATmega64 MCU控制寄存器MCUCR
ATmega64 MCU 控制寄存器包含了电源管理的控制位。 • Bit 5 – SE: 睡眠使能 为了使MCU 在执行SLEEP 指令后进入睡眠模式, SE 必须置位。为了确保进入睡眠模 式是程序员的有意行为,建议仅在SLEEP 指令的前一条指令置位SE。一旦唤醒立即清 除SE。 • Bits 4..2 – SM2..0: 睡眠模式选择位 如Table 17 所示,这些位用于选择具体的睡眠模式。 Note: 1. 仅在使用外部晶体或谐振器时Standby 模式和扩展的Standby 模式才可用。
[单片机]
ATmega64 <font color='red'>MCU</font>控制寄存器MCUCR
如何用AVR单片机设计太阳能电池控制器
随着能源危机和环境污染的加深,太阳能的研究和利用受到广泛的关注。太阳能是人类取之不尽用之不竭的可再生能源,也是清洁能源,不产生任何的环境污染,在太阳能的有效利用中,太阳能充电是近些年发展最快,最具活力的研究领域,是其中最受瞩目的项目之一。太阳能电池发电是基于“光生伏打效应”原理,将太阳能转化为电能,利用充电效应将太阳辐射直接转化为电能。它具有永久性、清洁性和灵活性大的优点,是其他能源无法比拟的。 1 太阳能控制器的设计 1.1 太阳能电池的输出特性 由它的输出特性曲线(见图1) 可知,太阳能电池的伏安特性具有很强的非线性,即当日照强度改变时,其开路电压不会有太大的改变,但所产生的最大电流会有相当大的变化,所以其输出功率与最大功
[单片机]
如何用AVR<font color='red'>单片机</font>设计太阳能电池控制器
采用PC机实现单片机优化控制
一、用PC机实现单片机优化控制的必要性 目前,单片机的控制很广泛。但是对于复杂的现场控制,大多数单片机的控制程序都是采用单一的汇编语言编写。 其缺点有: 1.由于汇编语言功能的限制,不能形成友好的控制界面。不能很好的反映出控制现场的实时变化情况。 2.对于不同的单片机CPU芯片,还要有不同的汇编语言,可移植性差,增加了编程的难度。 3.当被控对象的工艺条件变化时,单片机很难跟着变化。除非重新编制程序,再一次的固化,这样操作起来就比较困难。 笔者采用了PC机高级语言编程和单片机汇编语言编程相结合解决上述的缺点。 二、实现过程 PC机将各种予置信号通过串行口送给单片机控制系统,再由单片机系统通过D/A变换产生实际的模拟
[单片机]
采用PC机实现<font color='red'>单片机</font>优化控制
基于飞思卡尔MCU的空调(HVAC)与供暖通风方案
方案描述: 空调 ( HVAC ) 与 供暖通风 系统用于调节车内气流,为驾乘者提供舒适的环境。这些系统一般需要根据不同输入条件 (如温度) 控制多个电机 (如运行风机和风扇),高端系统还含有LCD显示屏,甚至触控执行器。 HVAC 系统必须有效、安静且经济地运行。多个电机需要同时控制,而且系统需要满足汽车系统严格的可靠性要求。新型系统使用更少的传感器检测车内环境,因此对计算能力提出了更高的要求。 飞思卡尔 丰富的微控制器 ( MCU ) 产品组合可在存储器容量、性能和引脚数方面,满足车载 HVAC 系统的不同应用要求。此外,由于具备PWM功能、低静态电流、过流保护、过热保护和负载电流反馈等特点,采用电机驱动器 (如MC33
[汽车电子]
基于飞思卡尔<font color='red'>MCU</font>的空调(HVAC)与供暖通风方案
51单片机学习记录——数码管动态显示
正在学习51的数码管以及中断,打算利用六位数码管实现一个时钟的功能。 但使用数码管输出时,如果不添加延时语句,那么一直有显示混乱的现象,有时完全无法分辨清楚数字。 如果在传送完数据以后延时1ms,显示混乱情况会好转。 同时发现延时的时间越长,显示效果越好。但是当然,相应的显示稳定程度也会下降,即数码管闪烁。 程序中在送完段选数据以后已经使用了参考书中的 消影 语句: 1 dula=1; 2 P0=table ; 3 dula=0; 4 P0=0xff;// 消影 可是这个语句只是在有延时的情况下才有效果,如果我不写延时语句,那么显示依旧混乱。 虽然在显示过程延时不会影响中断的计时,但是我总不想依赖for语句写出来的延
[单片机]
51<font color='red'>单片机</font>学习记录——数码管动态显示
为什么AVR单片机需要写1作为清0中断标志位
关于“为何AVR使用写1作为清0中断标志位的手段”这个问题我看过很多的相关资料。在AVR的手册中并没有给出为什么的解释,只是强调了“写1清0中断标志位”。同时我也看到很多新的芯片,如DSP等,也是采用写1清零标志位的。但没有找到更专业的,或从根源上的说明,如果那位有这方面的知识或资料,欢迎深入的讨论学习。 下面是我个人的分析和解释,供参考。 1、首先从硬件上的考虑,通常的读写处理单元是以8BIT字节为单位的,因为数据总线一般是8位的倍数。这样对位的操作就不方便,不能直接写1位(会改变其它的位),需要先读到寄存器,然后改动1位,最后回写,需要更多的时间。 2、对于RAM操作一般采用直接写的方式,所以对RAM基本上没有直接的位操作
[单片机]
为什么AVR<font color='red'>单片机</font>需要写1作为清0中断标志位
基于51单片机的超声波发生器设计方案
  本设计的超声波发生器是利用单片机生成初始信号,然后经过一系列处理电路的作用后生成用来杀灭水蚤的超声波,成本低、效果好,可以在农业上加以采用。在此对3个模块进行设计:   (1)信号发生模块。12 MHz的8051单片机硬件连接及其程序设计。   (2)信号处理模块。驱动电路设计(CD4069非门集成芯片);倍频电路设计(S9014或ECGl08三极管、104普通电容、11 257.9 nH自制电感、1 kΩ电阻);整波电路设计(CD4069非门集成芯片);和频电路设计(CD4081与门集成芯片);选频电路设计(S9014或ECGl08三极管、104普通电容、112.58 nH自制电感、1 kΩ电阻)。   (3)信号检测
[单片机]
基于51<font color='red'>单片机</font>的超声波发生器设计方案
单片机在数控车床切削力测量中的应用
1、问题的提出 在数控车床的加工中,切削力的测量甚为重要。通过对切削力的测量可以分析与研究数控车床各零部件、机构或结构的受力情况和工作状态,验证设计和计算结果的正确性,确定整机工作过程中的负载谱和某些物理现象的机理。因此,他对发展设计理论、保证数控机床安全可靠地运行以及实现数控机床自动加工、自动检测、自动控制和切削力过载报警等都具有十分重要的作用和适用价值。 2、系统硬件接口电路的设计 系统硬件原理框图如图1所示。系统以AT89C51单片机为控制核心,外围电路针对单片机的功能特点而设计,充分利用了AT89C51单片机片内资源丰富的特点,简化了外围电路,提高了可靠性。下面对系统中主要功能模块与硬件可靠性技术逐一分析。
[单片机]
<font color='red'>单片机</font>在数控车床切削力测量中的应用
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved