实验3 串口通信

发布者:梦中的额吉最新更新时间:2017-01-06 来源: eefocus关键字:串口通信  单片机 手机看文章 扫描二维码
随时随地手机看文章

1. 以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

#include

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

/**

题目要求:以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

**/

/**

步骤

接线方式:

1、P0接数码管J12,实现段选

2、译码器和数码管位选输入短接,J15+J16

3、P2用来控制译码器的输入

4、P1是串口接收中断的指示,P1+JP1

5、本实验使用的晶振是11.0592

**/

//=========全局变量区============================================

sbit high=P2^4;

sbit mid=P2^3;

sbit low=P2^2;

uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码

 

uint Received_Flag=0;//用来标志是否接收到信号

uchar ReceiveCount,Data_Received=0;//ReceiveCount是接受的条数,接收到的数据

uchar code table[]="index ";

//=========全局变量区结束========================================

 

 

 

//========函数区开始============================================

/**

    延时

**/

void delay_1ms(uint x){

    uint i=x;

    uint j;

    for(;i>0;--i){

       for(j=110;j>0;--j);

    }

}

/**

    在数码管上显示对应的值

**/

void display(uchar Num)

{

    P0=NumTable[Num];

    delay_1ms(1);

    P0=0;      //送完段选信号后,进行消影的处理

}

 

/**

    控制数码管显示后3位,并分解计数值

**/

void DisplayNumByOrder(uint Value){

       low=0; mid=0; high=0;  display(0);        

        low=1; mid=0; high=0;  display(0);               

        low=0; mid=1; high=0;  display(0);

       low=1; mid=1; high=0;  display(0);

       low=0; mid=0; high=1;  display(0);

       low=1; mid=0; high=1;  display(Value%1000/100);

       low=0; mid=1; high=1;  display(Value%100/10);

       low=1; mid=1; high=1;  display(Value%10);

}

 

void init(){      //初始化定时器T1和串口

    SCON =0x50;  //设置串口工作方式1,并打开接收中断

    TMOD =0x20;  //设置T1工作方式2

    PCON =0x00;  //设置SMOD为串口工作方式1

    TL1 =0xf4;      

    TH1 =0xf4;     //2400bps(12MHZ的晶振)

    TR1 =1;      //开启时钟

    ES =1;           //开启串口中断允许

    EA =1;           //开启中断总允许

}

/**

    发送数据

**/

void SendData(uchar value){

    SBUF=value;

    while(!TI);

    TI=0;

}

/**

    处理接收到的数据

**/

void ProcessData(){

    int i=0;

    for(i=0;i<6;i++){

       SendData(table[i]);

    }

    SendData(ReceiveCount);

    SendData(':');

    SendData(Data_Received);

}

int main(){

 

    init();//初始化数据

    while(1){

       if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示

           ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。

           ProcessData();

           ES=1;

           Received_Flag=0;

       }

       //在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

       DisplayNumByOrder(Data_Received);  //在数码管上显示

    }

    return0;

}

 

//========函数区结束============================================

 

 

//========中断函数区============================================

 

/**

    串口接收中断

**/

void ser_received() interrupt 4

{

    RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来

    Data_Received=(uchar)SBUF;  //从缓冲区内读取数据

    Received_Flag=1;  //设置已经接收到数据

    P1=~P1;

    ReceiveCount++;

}

//========中断函数区结束==========================================

2. 以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。

#include

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

/**

题目要求:  以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。

**/

/**

步骤

接线方式:

1、P0接数码管J12,实现段选

2、译码器和数码管位选输入短接,J15+J16

3、P2用来控制译码器的输入

4、P1是串口接收中断的指示,P1+JP1

5、本实验使用的晶振是11.0592

**/

//=========全局变量区============================================

sbit high=P2^4;

sbit mid=P2^3;

sbit low=P2^2;

uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码

 

uint Received_Flag=0;//用来标志是否接收到信号

uchar ReceiveCount,DecodeCount,Data_Received=0;//ReceiveCount是已经接收的条数,DecodeCount是已经解析的数目,Data_Received是接收到的数据

ulong NumToDisplay=0;

//=========全局变量区结束========================================

 

 

 

//========函数区开始============================================

/**

  延时

**/

void delay_1ms(uint x){

  uint i=x;

  uint j;

  for(;i>0;--i){

     for(j=110;j>0;--j);

  }

}

/**

  在数码管上显示对应的值

**/

void display(uchar Num)

{

  P0=NumTable[Num];

  delay_1ms(1);

  P0=0;      //送完段选信号后,进行消影的处理

}

 

/**

  控制数码管显示后3位,并分解计数值

**/

void DisplayNumByOrder(ulong Value){

     low=0; mid=0; high=0;  display(0);        

      low=1; mid=0; high=0;  display(0);               

      low=0; mid=1; high=0;  display(0);

     low=1; mid=1; high=0;  display(Value%100000/10000);

     low=0; mid=0; high=1;  display(Value%10000/1000);

     low=1; mid=0; high=1;  display(Value%1000/100);

     low=0; mid=1; high=1;  display(Value%100/10);

     low=1; mid=1; high=1;  display(Value%10);

}

 

void init(){    //初始化定时器T1和串口

  SCON =0x50;  //设置串口工作方式1,并打开接收中断

  TMOD =0x20;  //设置T1工作方式2

  PCON =0x00;  //设置SMOD为串口工作方式1

  TL1 =0xf4;      

  TH1 =0xf4;     //2400bps(11.0592MHZ的晶振)

  TR1 =1;      //开启时钟

  ES =1;           //开启串口中断允许

  EA =1;           //开启中断总允许

}

/**

  发送数据

**/

void SendData(uchar value){

  SBUF=value;

  while(!TI);

  TI=0;

}

 

int main(){

 

  init();//初始化数据

  while(1){

     if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示

         ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。

         //ProcessData();

         ES=1;

         Received_Flag=0;

     }

     //在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

     DisplayNumByOrder(NumToDisplay);   //在数码管上显示

  }

  return0;

}

 

//========函数区结束============================================

 

 

//========中断函数区============================================

 

/**

  串口接收中断

**/

void ser_received() interrupt 4

{

  if(RI ==1){//接收到触发中断

     RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来

     Data_Received=(uchar)SBUF;  //从缓冲区内读取数据

     Received_Flag=1;  //设置已经接收到数据

     if(DecodeCount==0){

         NumToDisplay=Data_Received;

         ++DecodeCount;

     }else{

         NumToDisplay =(NumToDisplay <<8)| Data_Received;//相当于原来的数乘以8,然后+现在的数

         DecodeCount++;

         if(DecodeCount ==3)                  //0..65536要接收6位的16进制

            DecodeCount =0;

     }

     P1=~P1;

     ReceiveCount++;

  }

}

//========中断函数区结束==========================================

 

扩展题目:

1.      实现单片机双机通信,实现单片机甲发送一个信息给单片机乙,同时在数码管上显示出来,单片机乙收到信息后,回复OK给单片机甲。

 

//甲机

 

   

#include

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

/**

题目要求:以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

**/

/**

步骤

接线方式:

1、P0接数码管J12,实现段选

2、译码器和数码管位选输入短接,J15+J16

3、P2用来控制译码器的输入

4、P1是串口接收中断的指示,P1+JP1

5、本实验使用的晶振是11.0592

**/

//=========全局变量区============================================

sbit high=P2^4;

sbit mid=P2^3;

sbit low=P2^2;

uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码

 

uint Received_Flag=0;//用来标志是否接收到信号

uchar ReceiveCount,Data_Received=0;//ReceiveCount是接受的条数,接收到的数据

uchar code table[]="index ";

//=========全局变量区结束========================================

 

 

 

//========函数区开始============================================

/**

    延时

**/

void delay_1ms(uint x){

    uint i=x;

    uint j;

    for(;i>0;--i){

       for(j=110;j>0;--j);

    }

}

/**

    在数码管上显示对应的值

**/

void display(uchar Num)

{

    P0=NumTable[Num];

    delay_1ms(1);

    P0=0;      //送完段选信号后,进行消影的处理

}

 

/**

    控制数码管显示后3位,并分解计数值

**/

void DisplayNumByOrder(uint Value){

       low=0; mid=0; high=0;  display(0);        

        low=1; mid=0; high=0;  display(0);               

        low=0; mid=1; high=0;  display(0);

       low=1; mid=1; high=0;  display(0);

       low=0; mid=0; high=1;  display(0);

       low=1; mid=0; high=1;  display(Value%1000/100);

       low=0; mid=1; high=1;  display(Value%100/10);

       low=1; mid=1; high=1;  display(Value%10);

}

 

void init(){      //初始化定时器T1和串口

    SCON =0x50;  //设置串口工作方式1,并打开接收中断

    TMOD =0x20;  //设置T1工作方式2

    PCON =0x00;  //设置SMOD为串口工作方式1

    TL1 =0xf4;      

    TH1 =0xf4;     //2400bps(11.0592MHZ的晶振)

    TR1 =1;      //开启时钟

    ES =1;           //开启串口中断允许

    EA =1;           //开启中断总允许

}

/**

    发送数据

**/

void SendData(uchar value){

    SBUF=value;

    while(!TI);

    TI=0;

}

 

int main(){

 

    init();//初始化数据

    SendData(0x00);//发送数据

    SendData(0x01);

    SendData(0x01);

    while(1){

       if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示

           ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。

          

           ES=1;

           Received_Flag=0;

       }

       //在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

       DisplayNumByOrder(Data_Received);  //在数码管上显示

    }

    return0;

}

 

//========函数区结束============================================

 

 

//========中断函数区============================================

 

/**

    串口接收中断

**/

void ser_received() interrupt 4

{

    RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来

    Data_Received=(uchar)SBUF;  //从缓冲区内读取数据

    Received_Flag=1;  //设置已经接收到数据

    P1=~P1;

    ReceiveCount++;

}

 

//========中断函数区结束==========================================

 

 

 

 

//乙机

#include

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

/**

题目要求:  以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。

**/

/**

步骤

接线方式:

1、P0接数码管J12,实现段选

2、译码器和数码管位选输入短接,J15+J16

3、P2用来控制译码器的输入

4、P1是串口接收中断的指示,P1+JP1

5、本实验使用的晶振是11.0592

**/

//=========全局变量区============================================

sbit high=P2^4;

sbit mid=P2^3;

sbit low=P2^2;

uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码

 

uint Received_Flag=0;//用来标志是否接收到信号

uchar ReceiveCount,DecodeCount,Data_Received=0;//ReceiveCount是已经接收的条数,DecodeCount是已经解析的数目,Data_Received是接收到的数据

ulong NumToDisplay=0;

//=========全局变量区结束========================================

 

 

 

//========函数区开始============================================

/**

    延时

**/

void delay_1ms(uint x){

    uint i=x;

    uint j;

    for(;i>0;--i){

       for(j=110;j>0;--j);

    }

}

/**

    在数码管上显示对应的值

**/

void display(uchar Num)

{

    P0=NumTable[Num];

    delay_1ms(1);

    P0=0;      //送完段选信号后,进行消影的处理

}

 

/**

    控制数码管显示后3位,并分解计数值

**/

void DisplayNumByOrder(ulong Value){

       low=0; mid=0; high=0;  display(0);        

        low=1; mid=0; high=0;  display(0);               

        low=0; mid=1; high=0;  display(0);

       low=1; mid=1; high=0;  display(Value%100000/10000);

       low=0; mid=0; high=1;  display(Value%10000/1000);

       low=1; mid=0; high=1;  display(Value%1000/100);

       low=0; mid=1; high=1;  display(Value%100/10);

       low=1; mid=1; high=1;  display(Value%10);

}

 

void init(){      //初始化定时器T1和串口

    SCON =0x50;  //设置串口工作方式1,并打开接收中断

    TMOD =0x20;  //设置T1工作方式2

    PCON =0x00;  //设置SMOD为串口工作方式1

    TL1 =0xf4;      

    TH1 =0xf4;     //2400bps(11.0592MHZ的晶振)

    TR1 =1;      //开启时钟

    ES =1;           //开启串口中断允许

    EA =1;           //开启中断总允许

}

/**

    发送数据

**/

void SendData(uchar value){

    SBUF=value;

    while(!TI);

    TI=0;

}

 

int main(){

 

    init();//初始化数据

    while(1){

       if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示

           ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。

           SendData(‘o’);

SendData(‘k’);

           ES=1;

           Received_Flag=0;

       }

       //在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。

       DisplayNumByOrder(NumToDisplay);   //在数码管上显示

    }

    return0;

}

 

//========函数区结束============================================

 

 

//========中断函数区============================================

 

/**

    串口接收中断

**/

void ser_received() interrupt 4

{

    if(RI ==1){//接收到触发中断

       RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来

       Data_Received=(uchar)SBUF;  //从缓冲区内读取数据

       Received_Flag=1;  //设置已经接收到数据

       if(DecodeCount==0){

           NumToDisplay=Data_Received;

           ++DecodeCount;

       }else{

           NumToDisplay =(NumToDisplay <<8)| Data_Received;//相当于原来的数乘以8,然后+现在的数

           DecodeCount++;

           if(DecodeCount ==3)                  //0..65536要接收6位的16进制

              DecodeCount =0;

       }

       P1=~P1;

       ReceiveCount++;

    }

}

//========中断函数区结束==========================================


关键字:串口通信  单片机 引用地址:实验3 串口通信

上一篇:实验2 中断和定时计数器实验
下一篇:实验4 IIC通讯与EEPROM接口

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

单片机编程思想——状态机
本文来说一下状态机编程。 什么是状态机? 状态机(state machine)有5个要素: · 状态(state) · 迁移(transition) · 事件(event) · 动作(action) · 条件(guard) 状态 :一个系统在某一时刻所存在的稳定的工作情况,系统在整个工作周期中可能有多个状态。例如一部电动机共有正转、反转、停转这 3 种状态。 一个状态机需要在状态集合中选取一个状态作为初始状态。 迁移 :系统从一个状态转移到另一个状态的过程称作迁移,迁移不是自动发生的,需要外界对系统施加影响。停转的电动机自己不会转起来,让它转起来必须上电。 事件 :某一时刻发生的对系统有意义的事情,状态机之所以发生
[单片机]
单片机驱动dac0832输出方波三角波正玄波程序
电路图 仿真文件及完整的源代码下载地址:http://www.51hei.com/bbs/dpj-20395-1.html 下面是汇编程序源码,可以用按键来控制 org 0000h ajmp main org 0030h main:mov a,#00h clr p1.0 clr p1.1 jnb p3.0, zhengxuan jnb p3.1,juchi jnb p3.2,sanjiao sjmp MAIN sanjiao: mov a,#00h clr p1.0 clr p1.1 loop: mov p0,a inc a mov r0,#10h djnz
[单片机]
<font color='red'>单片机</font>驱动dac0832输出方波三角波正玄波程序
STM32F7高速缓存
STM32F7是第一款带有内部高速缓存的STM32微控制器,所以接下来我们会介绍一些和高速缓存和Cache相关的基本概念,会介绍一些如果是开发者在使用STM32F7的时候需要注意的事情。 STM32F7的内核中带有一级高速缓存,实现了4K的数据缓存和4K的指令缓存。 下面介绍一下什么是高速缓存和与高速缓存相关的一些基本概念。 高速缓存就是高速存储器块,包括地址信息和相关联的数据,它的目的主要是为了提高对存储器的平均访问速度。 执行代码的时候CPU每次都要去访问FLASH,而我们知道FLASH的读取速度是远远低于CPU的主频的,所以需要设置一个等待周期来保证能够正确地从FLASH中把数据读出来。有了Cache之后,第一次访问FL
[单片机]
AVR单片机对数码管数据P0口与P2口的控制设计
//数码管数据P0口,数码管控制P2口 #include #include #include #include #include #define code PROGMEM #define uchar unsigned char #define uint unsigned int code const ucharLED_7[16] = {0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//common of + code const uchar posi ti on[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0x
[单片机]
AVR<font color='red'>单片机</font>对数码管数据P0口与P2口的控制设计
通过单片机来控制蜂鸣器
开发板原理图上面蜂鸣器的电路图是这样的,根据视频知道它是一个无源蜂鸣器。 可以看到蜂鸣器的一端和电阻相连,另一端和引脚BZ相连,注意这个BZ并不是元气名称,有图可知,元气名称都是蓝色的,而这个BZ是红色的。我们在开发板原理图上找一个 BZ引脚,发现在ULN2003D这个芯片上有BZ引脚,所以我们就把蜂鸣器的图和ULN2003D的图放在一张图上,而且把他们该连的引脚连起来了。 有图可知BZ1蜂鸣器的BZ引脚和ULN2003引脚的12引脚相连的,这是一个输出引脚,对应的输入引脚是5引脚,有图可知STC89C52单片机的P15引脚是和ULN2003的5引脚相连的。 所以可以通过单片机来控制蜂鸣器,是这么个道道。 ULN2003
[单片机]
通过<font color='red'>单片机</font>来控制蜂鸣器
解读ARM7内核微控制器LPC2148以太网接口电路
  嵌入式主控模块采用了基于ARM7TDMI-S内核的微控制器LPC2148,集成度非常高。内嵌40kB的片内静态RAM和512kB的片内 Flash存储器,片内集成ADC、DAC转换器,看门狗,实时时钟RTC,2个UART,2个I2C还有SPI等多个总线接口,及USB2.0全速接口。方便扩展USB接口、JTAG调试接口、触摸屏,外扩芯片少,而且采用超小的LQFP64封装,使得仪器的微型化得到了保证。而且电路相对简单,降低了开发和生产的成本。芯片可以实现最高60MHz的工作频率,有着较强的功能,能够满足嵌入式系统μC/OS—II及人性化的人机界面的要求。本设计中 LPC2148所有的接口都有使用。   以太网接口部分采用了具有
[单片机]
解读ARM7内核<font color='red'>微控制器</font>LPC2148以太网接口电路
单片机串行口通信程序设计
单片机串行口通信程序设计硬件连接图 例:用8051单片机串行口外接CD4094扩展8位并行输出口,如图所示,8位并行口的各位都接一个发光二极管,要求发光管呈流水灯状态。 串行口方式0的数据传送可采用中断方式,也可采用查询方式,无论哪种方式,都要借助于TI或RI标志。串行发送时,能靠TI置位(发完一帧数据后)引起中断申请,在中断服务程序中发送下一帧数据,或者通过查询TI的状态,只要TI为0就继续查询,TI为1就结束查询,发送下一帧数据。在串行接收时,则由RI引起中断或对RI查询来确定何时接收下一帧数据。无论采用什么方式,在开始通信之前,都要先对控制寄存器SCON进行初始化。在方式0中将,将00H送SCON就能了。 ---
[单片机]
<font color='red'>单片机</font>串行口通信程序设计
八位微控制器有哪些可以节约代码空间的代码优化技巧?
本文将介绍一些优化技术,帮助设计人员节约多达 10% 的代码空间,从而让容量有限的程序存储器支持更多新特性和补丁。 良好的操作方法 许多程序员在 32 位处理器上学习编写软件,如 Intel 的 Pentium 处理器或某种 ARM 平台。不过,嵌入式领域的软件编写需要不同的思路。在 32 位 CPU 上,存储比特位的最佳方法通常是使用 32 位变量。对 8 位处理器而言,最好的办法就是采用单字节。像增强型 8051s 等某些处理器可能提供特殊的 1 位变量。 嵌入式处理器通常会超出标准的哈佛架构将存储器分散到不同的存储器空间中,有的相互重叠,有的又是相互分离。例如,8051 中常见的存储器空间包括 CODE、XDATA、DA
[单片机]
八位<font color='red'>微控制器</font>有哪些可以节约代码空间的代码优化技巧?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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