历史上的今天
返回首页

历史上的今天

今天是:2024年12月23日(星期一)

正在发生

2021年12月23日 | 串口收发实验——键盘键入数字**.*,PC端循环接收显示**.*

2021-12-23 来源:eefocus

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


那么,我们只要知道单片机串口收发和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端显示**.*并换行循环显示直至键入新的数

推荐阅读

史海拾趣

FOX [Fox Electronics]公司的发展小趣事

面对物联网、5G通信和汽车电子等新兴技术的快速发展,Fox Electronics敏锐地洞察到未来市场的变革趋势。公司加大了对高频、低抖动和高精度时钟解决方案的研发力度,以满足新兴应用对时钟源的高要求。同时,Fox Electronics还积极布局汽车电子市场,开发适应汽车自动驾驶和车联网需求的专用时钟产品。通过不断创新和布局未来市场,Fox Electronics为自身的持续发展奠定了坚实基础。

请注意,以上故事均为虚构内容,旨在展示电子行业发展的某些方面和可能的趋势。实际上,Fox Electronics的具体发展历程和成就可能有所不同。

CYANLITE公司的发展小趣事

近年来,随着数字化技术的快速发展,CYANLITE公司也积极拥抱数字化转型。他们利用大数据、人工智能等先进技术优化生产流程、提高生产效率,并加强了对市场的分析和预测能力。此外,公司还加强了对电子商务平台的投入和建设,通过线上渠道拓展销售渠道并提高品牌曝光度。展望未来,CYANLITE公司将继续加大在技术研发和数字化转型方面的投入力度,推动公司向更高层次发展。同时他们也将继续关注市场变化和客户需求的变化趋势,不断调整和优化自己的战略方向和产品布局以应对未来的挑战和机遇。

Alliance Fiber Optics Products Inc公司的发展小趣事

近年来,AFOP的发展取得了显著成就,其产品在光网通信领域处于领先地位。202X年,世界500强康宁公司看中了AFOP的技术实力和市场潜力,决定对其进行收购。这一收购使得AFOP获得了更多的资源和支持,加速了公司的技术创新和市场拓展步伐。同时,康宁公司也通过收购AFOP进一步巩固了其在光纤通信领域的领先地位。

DRS Technologies公司的发展小趣事

在21世纪初,DRS接受了价值16亿美元的合同,为美国陆军和海军陆战队的部队现代化计划制造加固式计算机。这一合同不仅展示了DRS在军事领域的实力,也进一步巩固了其在全球电子行业的地位。DRS提供的“探索者”MP加固式轻便多平台工作站,为数字战场提供了强大的支持。

星海公司的发展小趣事

除了钢琴制造,星海公司还积极拓展多元化业务。公司下设多个分厂和子公司,涉及西管乐器、民族乐器、打击乐器、电声乐器和乐器配件等多个领域。此外,星海公司还积极打造音乐教育板块,成立钢琴培训学校,为音乐爱好者提供优质的教育资源。通过多元化发展,星海公司逐渐形成了完整的产业链和强大的品牌影响力。

Holmes Co Inc公司的发展小趣事

面对突如其来的新冠疫情挑战,Holmes Electronics迅速调整策略,加速数字化转型。他们利用云计算、大数据和人工智能等先进技术,构建了高效的远程办公和智能制造体系。通过数字化转型,公司不仅有效保障了员工的安全健康和生产效率,还进一步提升了产品质量和客户满意度。此外,Holmes Electronics还积极开发防疫相关的电子产品,如智能体温检测设备和消毒机器人等,为抗击疫情贡献了自己的力量。

问答坊 | AI 解惑

关于SDRAM的一点总结(原创)

SDRAM工作过程: 1.       上电稳定后经过8个刷新周期,进入模式寄存器设置(MRS),确定芯片的工作模式,CL,BL,突发传输方式。 2.       行有效,同时进行了片选和BANK选择工作。CS RAS有效 CAS WE ...…

查看全部问答>

菜鸟问个问题??急

我用的单片机是mc9s12dg128,现在在调最小系统,情况是: 1、板子只焊了主芯片、电源部分、复位电路部分。电源部分正常,主芯片是新的,没有向里面下载过程序 2、复位电路的输出信号reset应该在没有按按键时是高电平,但是实际上测是低电平(未按 ...…

查看全部问答>

让你的电脑漂亮起来!为你的磁盘装上一见漂亮的衣裳吧!

http://download.eeworld.net/source/2310249(软件地址)这个软件安装好了以后,不单单是现在表面所看到的!图片地址(http://home.51.com/wutuanfeng/photo/item/100133258.html)在这些文件夹里面还是一样的效果背景图也是变化万千的!文件夹的 ...…

查看全部问答>

应用程序调用 wince5.0的 nandflash驱动 错误

使用 CreateFile 但始终都不成功,应用中代码如下                 hFunction = CreateFile( TEXT(\"DSK1:\"),                 GENERIC_ ...…

查看全部问答>

keil文件不能编译

我现在下载的是keil uv3,安装成功后,能够输入程序,但是编译不起来,在编译的时候会出现提示框:uVision3-Path undefined,\'tOOLS.INI\' does contain a tool path ,you have selecteed a device  where no toolchain has been install ...…

查看全部问答>

各位请看图片..

请问怎么实现按红键便会发出一段30多秒的对话?…

查看全部问答>

关于传真通讯过程问题

各位有玩过传真芯片没 传真通讯过程中发送端要发送TCF,是1.5s的“0”串 是1.5s的0x00么 另外 接收端怎样确定正确接收TCF 是判断接收的是不是1.5s的0x00么 各位指点下 谢谢…

查看全部问答>

如何在vs2005上的win32工程中加入一个对话框并且为上面的按钮加入消息处理函数,急急急急急急

如题,在资源界面添加了一个dialog,上面有一个ok和取消键, 自己曾经做过mfc的桌面程序,记得按ctrl+w就调出类向导界面为新对话框添加类, 但win32我就不懂了,请问高手们如何添加界面,并为按钮添加消息处理函数。 多谢。…

查看全部问答>

单片机初学者问题,高人指点,急,在线等。谢谢了!!!!!!!!!!!

本人初学者,下载了平凡的单片机的电子书。本人初学,望高手指点,不要笑话。谢谢了。 问题如下: #include “reg51.h” sbit P1_0=P1^0; void main() { P1_1=0; } 这个是让接在p1.0脚上的led发光。既然都给p1_1赋了0,就是让p1.0脚发光 ...…

查看全部问答>

STM32中到底有没有内部基准?

见stm32CDE中文版数据手册33页5.3.4。 贴不了图啊。。。。…

查看全部问答>