串口收发实验——键盘键入数字**.*,PC端循环接收显示**.*

发布者:Amy啊111111最新更新时间:2022-01-18 来源: eefocus关键字:串口收发  PC端 手机看文章 扫描二维码
随时随地手机看文章

小编今天笔记一下串口的收发实验,实验的灵感来源于对蓝牙模块收发的学习。我们在电路中使用蓝牙,其实就是把蓝牙看做是一个中转站,这个中转站在透传的模式下,不会对接收到的数据做任何变动,而是直接转发出去。


那么,我们只要知道单片机串口收发和PC端键盘的输入都是以字符的ASCII码的形式进行的,PC端收到后显示则是正常字符的形式

即:

键盘键入字符(ASCII码形式)–>单片机收到字符(ASCII码形式)

敲击3,实质键入0x33–>单片机读buff收到消息0x33

单片机发送字符(ASCII吗形式)–>模拟PC收到字符(正常形式显示)

单片机发送字符3,实质写buff发0x33–>模拟PC收到后显示3


废话少说,上仿真电路图

代码:

main.c


#include

#include


#define uint unsigned int

#define uchar unsigned char

#define ulong unsigned long


sbit LSA=P2^2;

sbit LSB=P2^3;

sbit LSC=P2^4; //38译码器的片选


bit lanya = 0 ;  //蓝牙发送标志,单片机发送给PC

uchar LanYa_DATA_count=0;  //用于后面LnaYa_receive[]数组的各位数赋值,相当于[i]中的i

uchar LanYa_receive[4]; //LanYa串口接收数据缓存

uint Receive_Data;  //最后单片机接收的整合的数据 ,必须是uint,因为uchar不能超过255

uchar Display_Data[3]; //处理要显示在数码管的数据缓冲数组

uchar Computer[4];  //要发给PC的数组

uchar T0RH = 0;   //用于后面的TH0赋值

uchar T0RL = 0;   //用于后面的TL0赋值

uchar UART_data;   /*设一个中间变量,获取读sbuf的数据,在串口中断服务函数中用到*/

uchar code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79};


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

函数名称:void delay(uint i)

函数作用:延时函数

参数说明:

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

void delay(uint i){ //延时函数

 while(i--);

}


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

函数名称:ConfigUart(uint baud)

函数作用:串口初始化函数

参数说明: baud:要设置的波特率

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

void ConfigUart(uint baud){

 SCON  = 0x50;  //配置串口:工作方式1,既可以接,也可以收

    TMOD |= 0x20;  //配置定时器T1为工作方式2:自动重装 ;使用T1的目的就是作为波特率发生去的一部分

    TH1 = 256 - (11059200/12/32)/baud;  //利用公式,加上参数,计算T1重载值

    TL1 = TH1;     //初值等于重载值

    ET1 = 0;       //禁止定时器T1中断(因为它作为波特发生器一部分)

    TR1 = 1;       //启动T1,即使能T1

 EA=1;     //开总中断

 ES=1;     //开串行口中断

}


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

函数名称:send_char_com(uchar ch)

函数作用:利用串口发送一个字符 ,串口接/收的其实就是8位的ASCII,即一个字符

参数说明: uchar ch:要发送的字符

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

void send_char_com(uchar ch) { 

 SBUF=ch;  //发sbuf,发送字符ch 

 while(TI==0);      //TI被硬件置1表示发送成功,跳出死循环

 TI=0;       //软件将TI置零,接着准备下次发送


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

函数名称:send_string_com(unsigned char *str,unsigned int strlen)

函数作用:利用串口发送字符串

参数说明: unsigned char *str:指针指向字符串的首地址,unsigned int strlen:想发送的长度(这个字符串的字符个数)

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

void send_string_com(uchar *str,uint strlen){ 

 uint k=0;    

 do 

 {  

  send_char_com(*(str + k)); /*这里应该是用来指针的首地址+偏移量*/ 

  k++;     

 }

 while(k < strlen);

}


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

函数名称:void ConfigTimer0(unsigned int ms)

函数作用:定时器0初始化函数,ms级定时溢出中断

参数说明: unsigned int ms:设置定时溢出的ms数

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

void ConfigTimer0(uint ms){ 

 ulong tmp;

 tmp = 11059200/12;

 tmp = (tmp * ms)/1000;

 tmp = 65536 - tmp;

 tmp = tmp + 18;

 EA = 1;

 T0RH = (uchar)(tmp >> 8);

 T0RL = (uchar)tmp;  //上面的这些行直接用就行

 TMOD &= 0xF0;

 TMOD |= 0x01;    //设置TMOD的定时器0,方式1,需要重装初值的

 TH0 = T0RH;

 TL0 = T0RL;

 ET0 = 1;      //开定时器0的中断允许

 TR0 = 1;      //开定时器0的使能

}


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

函数名称:void dispiay()

函数作用:数据处理并显示

参数说明: 无

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

void dispiay(){  

 uchar i;

 Display_Data[0]=smgduan[Receive_Data/100];

 Display_Data[1]=smgduan[Receive_Data%100/10] | 0x80; //0x80是加个小数点

 Display_Data[2]=smgduan[Receive_Data%10]; 

 for(i=0;i<3;i++){ //先分别选中位,循环和switch实现

  switch(i){

   case 0: LSA=0;LSB=0;LSC=0;break;

   case 1: LSA=1;LSB=0;LSC=0;break;

   case 2: LSA=0;LSB=1;LSC=0;break; 

  }

 P0=Display_Data[2-i]; //选中位后,传段选数据 

 delay(100);  //延时1ms

 P0=0x00; //消隐 

 }

}


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

函数名称:void main()

函数作用:数据处理并显示

参数说明: 无

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

void main(){  //主程序

 uchar i;

 ConfigUart(9600);  //波特率设置为9600

 ConfigTimer0(5); //定时器T0 5ms

 while(1){

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

   Computer[i]= LanYa_receive[i];

  }

  dispiay();   //显示在数码管 

  if(lanya==1&&(UART_data=='r')){//蓝牙标志位置1,表单片机发送,并且读buff收到回车字符(表示PC端发送结束)

   send_string_com(Computer,4);  //将从PC端接收到的数据发送给PC端

   send_char_com('r');     //发送r,表换行

   lanya = 0; //蓝牙标志清零,单片机发送结束

  } 

 }

}


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

函数名称:void InterruptTimer0() interrupt 1

函数作用:定时器0中断服务程序

参数说明: 无

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

void InterruptTimer0() interrupt 1{

 static uchar tmr1s = 0;

 TH0 = T0RH;  //重新加载重载值

 TL0 = T0RL;

 tmr1s++;

 if(tmr1s >= 200)  //这个tmr1s变量起缓冲的

 {

  tmr1s = 0;

  lanya = 1;  //将”lanya“标志位置1,准备在main中单片机发送数据

 }

}


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

函数名称:void uart(void) interrupt 4

函数作用:串口中断服务程序

参数说明: 无

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

void uart(void) interrupt 4 {   

 uchar  a,b,c;

 if(RI)

 {

  UART_data=SBUF;

  if(UART_data=='r'){ //如果检测到回车按键则得到Receive_Data,将其(PC发送给单片机的数)通过display函数显示在数码管上

       a = LanYa_receive[0]-0x30;   /*这些数都减0x30的原因是:微机原理中,数字0-9,对应ASCII吗为30H-39H

                 字母A-Z 对应ASCII码就是41H-5AH,字母a-z ASCII码就是61H-7AH

              这样减30H就可以得到显示正确的数字*/

        b = LanYa_receive[1]-0x30;

c = LanYa_receive[3]-0x30;

      Receive_Data = a*100+b*10+c; 

     LanYa_DATA_count=0;

  }

  else{ //否则将PC传来的字符串一个字符一个字符的存放至LanYa_receive[]数组中

   LanYa_receive[LanYa_DATA_count]=UART_data;

   LanYa_DATA_count++;

  }

 }

 RI=0;

}


仿真结果

键盘键入**.则

数码管显示*.*

PC端显示**.*并换行循环显示直至键入新的数

关键字:串口收发  PC端 引用地址:串口收发实验——键盘键入数字**.*,PC端循环接收显示**.*

上一篇:51单片机实验1——串行通信(TX/RX)
下一篇:小白学习HC-05蓝牙透传模块

推荐帖子

IAR_EW430使用入门
IAR_EW430的使用贴,是我学习时找到的资料IAR_EW430使用入门
lu331364648 TI技术论坛
【藏书阁】模拟电子技术基础实验与课程设计
目录:第一编模拟电子技术基础实验基本知识第一章概述第二章实验程序第三章模拟电子技术基础实验常用仪器使用练习第四章万用表对常用电子元器件的检测第五章集成运算放大器的主要参数测试第六章电路故障分析、排除及抗干扰、噪声抑制和自激振荡的消除第二编基本设计性实验第一章单管放大电路的设计与调试第二章集成运算放大电路设计实验第三章反馈放大器实验第四章波形产生电路的实验第五章直流稳压电源的研究与设计第三编课程设计(综合设计性实验)第一章课程设计
wzt 模拟电子
CMOS的正常工作电流下CMOS电路设计问题
这次遇到的问题是这样的,由于LDO的电源输出能力有限,同时也是保证可靠性,某些保护电路必须直接电源上,这里需要注释的是,LIMPHOME跛行回家即使我们的5V系统出现了问题,我们也必须保证部分重要的功能能继续工作,因此为了满足这个条件,关键信号的供电只能是直接接电池。这次第一个出问题的是一个CMOS的与门(HE4000B系列的)。我们的控制信号出自MCU(5V的系统),而与门的系统供电是12V的,因此两个电平不兼容,导致了MCU的高低电平统一被与门CMOS芯片识别成低电平
火辣西米秀 模拟与混合信号
多功能随身电源设计
引言现在,市场上可移动的电子设备越来越多,设备的电源容量和功耗却远远不能满足市场的要求,对日常生活,特别是户外活动造成诸多不便。为此,本文设计了一种多功能、高效、低功耗、安全的随身电源,以满足户外需求,将有很大的实用价值。多功能随身电源的系统设计本文论述的电路系统设计由五部分组成:锂芯容量指示电路、电芯保护电路、充电管理电路、DC-DC升压电路和功能扩展电路。锂芯容量指示电路由XC61CC系列的电压监控芯片组成。电芯保护电路由过充保护、过放保护、过温保护三部分组成,HAT2027、R540
黑衣人 电源技术
stm32的IO口操作方法
菜鸟求助:stm32的IO口能不能像51那样总线操作,就是同时读取或写入某几个IO口,请高手们赐教stm32的IO口操作方法比如我有个8位的拨码开关,但8位不是接在同一组IO上,有几位接在PA,另几位接PB,该怎么读取拨码开关的值呢?用寄存器操作,可以和51一样的操作啊1111
wangbin65530 stm32/stm8
关于if else 代码中 else 后代码执行条件的问题
if((buffer==0x01)||(total0)){代码1;}else{代码2;}请问以上代码可否实现只要buffer!=0x01或者total=0两条件之一满足就执行代码2的要求吗?关于ifelse代码中else后代码执行条件的问题上面是或,下面就是与了请问以上代码可否实现只要bu
一沙一世 单片机
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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