基于51单片机串口实验设计

基于51单片机串口实验设计

一实验内容:

实现两个单片机系统(A,B)之间通过串口方式 1 传输数据。

1)可以通过一个按键任意指定某个单片机是发送端,之后该单片机发送消 息通知另一个单片机是接收端,并且发送端在本地数码管显示“A”,接 收端显示“B”;
2)发送端依次发送 0~9 给发送端,接收端每接收一个字符就将该字符与前 面接收的字符累加后再发回发送端,发送端和接收端都能在数码管上显
示接收和发送的字符;

3)如果数据传输过程中出现错误需要重新发送;

4)所有数据传输完成后,发送端需要通知接收端结束此次传输,两个系统回到初始状态;
5)给出设计思路并画出程序流程图。思考查询方式和中断方式实现同样功
能在程序设计上有何不同?

二、设计思路

1、发送功能模块的设计:
  • 首先写一个函数用于数据发送的,发送程序先发送一个联络信号等待接受机应答,若接收到正确的应答信号后才开始进行数据发送。

    (说明:这里的联络信号与应答信号是自己与队友接收机或发送机来提前做好协议的)

    若接收到错误的应答信号就继续执行发送联络信号。发送数据采用一个for循环语句来执行。

    在发送模块还有一个校验和sum将发送的数据累加起来,待数据发送完后与接收机返回的校验和数据比较,若不相等就说明错误,此时需要重新发送数据。若相等说明数据正确。发送完所有数据后,此时等待接收来自接收机的结束信号,收到结束信号后,发送机回到初始状态。

2、接收功能模块的设计:
  • 与发送功能模块类似,首先需要接收一个来自发送机的联络信号,若接收到的信号与之前协议好的联络信号不一致,则发送一个报错信号给发送机,让发送机重新发送。

    接收到正确联络信号后,返回一个信号给发送机(这个信号也是与队友协议好的数值),当发送机接收到这个信号后知道接收机已经准备好了,此时发送机可以发送数据,接收机也可以接收数据了。

    在接收机中同样也有一个数据校验和sum,把接收的数据都累加起来,每接受完一帧数据后,再把校验和发给发送机与发送机的校验和比较。若不相等,则需要清除掉接收的数据准备重新接收,直到接收数据正确为止。等接收完所有数据后,此时需要发送一个结束信号给发送机,告知数据接收完毕且正确,接收机回到初始状态。

3、显示函数:
  • 用一个七段数码管,用来显示单片机状态及发送接收数据的数值。首先会由设置好的一个标志位判断这是发送机还是接收机,若为发送机则输出显示A,接收机就显示B,等待发送或接收数据后就通过数码管显示相应的数据,并显示发送和接收的sum。
4、发送机与接收机的选择模块:
  • 通过一个按键控制选择,用一个标志位来表示发送机还是接收机,初始时为显示0000的状态,这里的用一个串口中断和一个外部中断来控制,按下按键后通过外部中断将本机设置为接收机,同时在中断函数中发送一个信号给另一台单片机。另一台接收到正确信号后执行串口中断,在中断函数里通过一个标志位将串口中断关闭,同时将其设置位发送机。等待数据发送完后,又打开串口中断,将两台单片机又设置为初始状态。

    实验时,先都开始初始化默认是接收机的,再将一个通过按键设置为发送机,然后发送机执行发送功能模块,接收机执行接收功能模块。发送机显示A,接收机会显示B,
    然后就是发送联络信号,之后发送数据,知道依次发送完后又回到初始状态。

    三、源程序:



/**********************双机串口通信函数*********************/

/***********************************************************/

#include<reg52.h>

#define uchar unsigned char

#define uint unsigned int

uchar
buf[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};

uchar
address[]={0x7f,0xbf,0xef,0xf7,0xfd,0xfe};//数码管位选亮的位置为11011011

uchar
show[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极段码0~9

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

sbit LE1=P2^1;

sbit LE2=P2^2;

sbit LE3=P2^3;

sbit LE4=P2^4;

sbit key=P3^2;

static uchar start=0;

uchar begin=0;

uchar all=0;

uchar sum;

void pick_wela(uchar address)       //选择要显示的数码管

{

       LE2=1;

       P1=address;

       LE2=0;                                                   


}

void show_dula(uchar n)    //显示需要的数字

{

       LE1=1;

       P1=table[n];

       LE1=0;

}

void delay(uint ms)

{     
uchar i;

       while(ms--)

       {

              for(i=0;i<123;i++);

       }

}

void display(uchar num,uchar sum,uchar A)//数码管显示函数

{

              uchar
a,b;

              a=sum/10;

              b=sum%10;

       LE1=1;

       P1=table[num];

       LE1=0;

       LE2=1;

       P1=table[b];

       LE2=0;

       LE3=1;

       P1=table[a];

       LE3=0;

       LE4=1;

       P1=table[A];

       LE4=0;

 

}

void key_scan()interrupt 0

//将测到按键后就将本机设置为接收机,并发送协议给另一台将其设置为发送机

{     if(key==0)

        {

             delay(10);

              if(key==0)

              {

                     

                            begin=0;

                            start=1;

                            SBUF=0XAA;,

                            while(TI==0);     

                                   TI=0;

              }

        } 

}

void A_send()

{

       uchar
i,j;

              sum =0;

              for(i=0;i<10;i++)

              {
          

                     sum+=buf[i];

                     

                     SBUF=buf[i];     

                     while(TI==0);     

                     TI=0;//甲机发送数据完毕,清零

                     for(j=0;j<150;j++)

            
{display(i,sum,10);}

                        delay(50);  


              }     

              

       SBUF=sum;

       while(TI==0);TI=0;

       while(RI==0);RI=0;

       if(SBUF==0X00)

       {

              begin=0;

              all=0;

              start=0;

              sum=0;

       }

       if(SBUF==0Xff)//出错时

       {

              begin=0;

              all=0;

              start=1;

              sum=0;

       }


}

void A_receive()

{

       uchar
i,j;

              sum=0;

       for(i=0;i<10;i++)

       {

              while(RI==0);

              RI=0;

              buf[i]=SBUF;

              sum+=buf[i];

        for(j=0;j<150;j++)

        {display(i,sum,11);}

       delay(50);    

       }

       while(RI==0);

       RI=0;

       if(SBUF==sum)

       {      

              SBUF=0x00;
//发送结束信号

              while(TI==0);

              TI=0;

              begin=0;

              all=0;

              start=0;

              sum=0;

       }

       else

       {

              SBUF=0xFF;//出错时ff,重新接受

              while(TI==0);

              TI=0;

              begin=1;

              all=0;

              start=1;

              sum=0;

       }  

 

}

void A_init()//串口初始化

{

       TMOD=0x20;

       TH1=0xf4;

       TL1=0xf4;

       PCON=0x00;//波特率不加倍

       SCON=0x50;//串口工作方式1

       TR1=1;

}

void call()interrupt 4

{

       if(TI==0&&all==0)

       {      RI=0;

              all=1;    //置一后将不再使用串口中断

              if(SBUF==0XAA)//如果接收到正确的通信协议就将本机设置为发送机

                     {

                     begin=1;

                     start=1;

                     }            

       }

}

void main()

{     LE1=0;


       LE2=0;

       LE3=0;

       LE4=0;

 
while(1)

       {  

              A_init();

              IT0=1;

              EA=1;

              ES=1;

              EX0=1;

         display(0,0,0);

         while(start==1)

         {

              if(begin==0)

               {    

                uchar j;

               for(j=0;j<250;j++)

               {

               display(0,0,11);

               }

               delay(300);

              A_receive();        

           }

              if(begin==1)

              {

                             uchar j;

               for(j=0;j<250;j++)

               {display(0,0,10);}

               delay(500);

                            A_send();                   

              }

          start=0;

       

        }

}

}

 

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基于51单片机的热电阻温度变送器设计实验的程序可以分为以下几个步骤: 1. 初始化:设置ADC的相关参数,包括参考电压、通道选择和工作模式。 2. 循环读取:通过ADC模块读取热电阻的电压值,并进行转换成温度值。 3. 温度转换:使用合适的算法将热电阻电压值转换成温度值。可以根据热电阻的特性曲线进行线性插值,或者使用查表法进行转换。 4. 输出显示:将转换后的温度值发送到显示屏,可以是LCD屏或者数码管显示。也可以通过串口或者无线模块发送到其他设备进行显示。 5. 延迟等待:通过延时函数等待一段时间,可以根据需要设置采样频率。 整个程序可以使用C语言进行编写,利用51单片机的开发环境进行编译和烧录。根据具体的硬件连接,需要在程序中设置适当的引脚和通道,并调整相关的参数。 在Proteus中,可以进行仿真验证程序的正确性和可靠性。首先,需要添加51单片机模块,并连接相应的引脚。然后,可以添加ADC模块和显示模块,以模拟实际硬件环境。在仿真过程中,输入模拟的热电阻电压值,观察输出的温度值是否与预期一致。 通过该实验,可以验证热电阻温度变送器的设计是否准确,并对51单片机的程序进行调试和改进。同时,Proteus的仿真功能可以提前发现潜在的问题,并进行调整和优化,最终实现一个稳定可靠的热电阻温度变送器设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值