找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1941|回复: 0
打印 上一主题 下一主题
收起左侧

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

[复制链接]
跳转到指定楼层
楼主

小编今天笔记一下串口的收发实验,实验的灵感来源于对蓝牙模块收发的学习。我们在电路中使用蓝牙,其实就是把蓝牙看做是一个中转站,这个中转站在透传的模式下,不会对接收到的数据做任何变动,而是直接转发出去。
那么,我们只要知道单片机串口收发和PC端键盘的输入都是以字符的ASCII码的形式进行的,PC端收到后显示则是正常字符的形式
即:
键盘键入字符(ASCII码形式)–>单片机收到字符(ASCII码形式)
敲击3,实质键入0x33–>单片机读buff收到消息0x33
单片机发送字符(ASCII吗形式)–>模拟PC收到字符(正常形式显示)
单片机发送字符3,实质写buff发0x33–>模拟PC收到后显示3

废话少说,上仿真电路图:

代码:

仿真结果
键盘键入**.[ i]则
数码管显示*.*
PC端显示**.*并换行循环显示直至键入新的数

小编水平有限,有啥不对的地方,请路过的大佬指出。今天溜了。。。。

/*******个人之前的原创文章非抄袭*************/


  1. main.c
  2. #include <reg52.h>
  3. #include <intrins.h>

  4. #define uint unsigned int
  5. #define uchar unsigned char
  6. #define ulong unsigned long

  7. sbit LSA=P2^2;
  8. sbit LSB=P2^3;
  9. sbit LSC=P2^4; //38译码器的片选

  10. bit lanya = 0 ;  //蓝牙发送标志,单片机发送给PC
  11. uchar LanYa_DATA_count=0;  //用于后面LnaYa_receive[]数组的各位数赋值,相当于中的i
  12. uchar LanYa_receive[4]; //LanYa串口接收数据缓存
  13. uint Receive_Data;  //最后单片机接收的整合的数据 ,必须是uint,因为uchar不能超过255
  14. uchar Display_Data[3]; //处理要显示在数码管的数据缓冲数组
  15. uchar Computer[4];  //要发给PC的数组
  16. uchar T0RH = 0;//用于后面的TH0赋值
  17. uchar T0RL = 0;//用于后面的TL0赋值
  18. uchar UART_data;/*设一个中间变量,获取读sbuf的数据,在串口中断服务函数中用到*/
  19. uchar code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79};

  20. /********************************************************
  21. 函数名称:void delay(uint i)
  22. 函数作用:延时函数
  23. 参数说明:
  24. ********************************************************/
  25. void delay(uint i){ //延时函数
  26. while(i--);
  27. }

  28. /********************************************************
  29. 函数名称:ConfigUart(uint baud)
  30. 函数作用:串口初始化函数
  31. 参数说明: baud:要设置的波特率
  32. ********************************************************/
  33. void ConfigUart(uint baud){
  34. SCON  = 0x50;  //配置串口:工作方式1,既可以接,也可以收
  35. TMOD |= 0x20;  //配置定时器T1为工作方式2:自动重装 ;使用T1的目的就是作为波特率发生去的一部分
  36. TH1 = 256 - (11059200/12/32)/baud;  //利用公式,加上参数,计算T1重载值
  37. TL1 = TH1;  //初值等于重载值
  38. ET1 = 0; //禁止定时器T1中断(因为它作为波特发生器一部分)
  39. TR1 = 1; //启动T1,即使能T1
  40. EA=1;  //开总中断
  41. ES=1;  //开串行口中断
  42. }

  43. /********************************************************
  44. 函数名称:send_char_com(uchar ch)
  45. 函数作用:利用串口发送一个字符 ,串口接/收的其实就是8位的ASCII,即一个字符
  46. 参数说明: uchar ch:要发送的字符
  47. ********************************************************/
  48. void send_char_com(uchar ch) {
  49. SBUF=ch;  //发sbuf,发送字符ch
  50. while(TI==0);//TI被硬件置1表示发送成功,跳出死循环
  51. TI=0; //软件将TI置零,接着准备下次发送
  52. }

  53. /********************************************************
  54. 函数名称:send_string_com(unsigned char *str,unsigned int strlen)
  55. 函数作用:利用串口发送字符串
  56. 参数说明: unsigned char *str:指针指向字符串的首地址,unsigned int strlen:想发送的长度(这个字符串的字符个数)
  57. ********************************************************/
  58. void send_string_com(uchar *str,uint strlen){
  59. uint k=0;
  60. do
  61. {  
  62.   send_char_com(*(str + k)); /*这里应该是用来指针的首地址+偏移量*/
  63.   k++;  
  64. }
  65. while(k < strlen);
  66. }

  67. /********************************************************
  68. 函数名称:void ConfigTimer0(unsigned int ms)
  69. 函数作用:定时器0初始化函数,ms级定时溢出中断
  70. 参数说明: unsigned int ms:设置定时溢出的ms数
  71. ********************************************************/
  72. void ConfigTimer0(uint ms){
  73. ulong tmp;
  74. tmp = 11059200/12;
  75. tmp = (tmp * ms)/1000;
  76. tmp = 65536 - tmp;
  77. tmp = tmp + 18;
  78. EA = 1;
  79. T0RH = (uchar)(tmp >> 8);
  80. T0RL = (uchar)tmp;  //上面的这些行直接用就行
  81. TMOD &= 0xF0;
  82. TMOD |= 0x01; //设置TMOD的定时器0,方式1,需要重装初值的
  83. TH0 = T0RH;
  84. TL0 = T0RL;
  85. ET0 = 1;//开定时器0的中断允许
  86. TR0 = 1;//开定时器0的使能
  87. }

  88. /********************************************************
  89. 函数名称:void dispiay()
  90. 函数作用:数据处理并显示
  91. 参数说明: 无
  92. ********************************************************/
  93. void dispiay(){  
  94. uchar i;
  95. Display_Data[0]=smgduan[Receive_Data/100];
  96. Display_Data[1]=smgduan[Receive_Data%100/10] | 0x80; //0x80是加个小数点
  97. Display_Data[2]=smgduan[Receive_Data%10];
  98. for(i=0;i<3;i++){ //先分别选中位,循环和switch实现
  99.   switch(i){
  100. case 0: LSA=0;LSB=0;LSC=0;break;
  101. case 1: LSA=1;LSB=0;LSC=0;break;
  102. case 2: LSA=0;LSB=1;LSC=0;break;
  103.   }
  104. P0=Display_Data[2-i]; //选中位后,传段选数据
  105. delay(100);  //延时1ms
  106. P0=0x00; //消隐
  107. }
  108. }

  109. /********************************************************
  110. 函数名称:void main()
  111. 函数作用:数据处理并显示
  112. 参数说明: 无
  113. ********************************************************/
  114. void main(){  //主程序
  115. uchar i;
  116. ConfigUart(9600);  //波特率设置为9600
  117. ConfigTimer0(5); //定时器T0 5ms
  118. while(1){
  119.   for(i=0;i<4;i++){
  120. Computer= LanYa_receive[  i];
  121.   }
  122.   dispiay();//显示在数码管
  123. f(lanya==1&&(UART_data=='\r')){//蓝牙标志位置1,表单片机发送,并且读buff收到回车字符(表示PC端发送结束)
  124. send_string_com(Computer,4);  //将从PC端接收到的数据发送给PC端
  125. send_char_com('\r');  //发送\r,表换行
  126. lanya = 0; //蓝牙标志清零,单片机发送结束
  127.   }
  128. }
  129. }

  130. /********************************************************
  131. 函数名称:void InterruptTimer0() interrupt 1
  132. 函数作用:定时器0中断服务程序
  133. 参数说明: 无
  134. ********************************************************/
  135. void InterruptTimer0() interrupt 1{
  136. static uchar tmr1s = 0;
  137. TH0 = T0RH;  //重新加载重载值
  138. TL0 = T0RL;
  139. tmr1s++;
  140. if(tmr1s >= 200)  //这个tmr1s变量起缓冲的
  141. {
  142.   tmr1s = 0;
  143.   lanya = 1;  //将”lanya“标志位置1,准备在main中单片机发送数据
  144. }
  145. }

  146. /********************************************************
  147. 函数名称:void uart(void) interrupt 4
  148. 函数作用:串口中断服务程序
  149. 参数说明: 无
  150. ********************************************************/
  151. void uart(void) interrupt 4 {
  152. uchar  a,b,c;
  153. if(RI)
  154. {
  155.   UART_data=SBUF;
  156. f(UART_data=='\r'){ //如果检测到回车按键则得到Receive_Data,将其(PC发送给单片机的数)通过display函数显示在数码管上
  157. a = LanYa_receive[0]-0x30;/*这些数都减0x30的原因是:微机原理中,数字0-9,对应ASCII吗为30H-39H
  158.   字母A-Z 对应ASCII码就是41H-5AH,字母a-z ASCII码就是61H-7AH
  159.   这样减30H就可以得到显示正确的数字*/
  160.   b = LanYa_receive[1]-0x30;
  161.   c = LanYa_receive[3]-0x30;
  162. Receive_Data = a*100+b*10+c;
  163.   LanYa_DATA_count=0;
  164.   }
  165.   else{ //否则将PC传来的字符串一个字符一个字符的存放至LanYa_receive[]数组中
  166. LanYa_receive[LanYa_DATA_count]=UART_data;
  167. LanYa_DATA_count++;
  168.   }
  169. }
  170. RI=0;
  171. }
  172. /******************************************************/
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表