[讨论] 51单片机串行口中断服务程序

SuperStar515   2007-7-6 20:47 楼主
51单片机串行口中断服务程序
  1. //串口中断服务程序,仅需做简单调用即可完成串口输入输出的处理
  2. //出入均设有缓冲区,大小可任意设置。
  3. //可供使用的函数名:
  4. //char getbyte(void);从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
  5. //getline(char idata *line, unsigned char n); 获取一行数据回车结束,已处理backspce和delete,必须定义最大输入字符数
  6. //putinbuf(uchar c);模拟接收到一个数据
  7. //putbyte(char c);放入一个字节到发送缓冲区
  8. //putbytes(unsigned char *outplace,j);放一串数据到发送缓冲区,自定义长度
  9. //putstring(unsigned char code *puts);发送一个字符串到串口
  10. //puthex(unsigned char c);发送一个字节的hex码,分成两个字节发。
  11. //putchar(uchar c,uchar j);发送一个字节数据的asc码表达方式,需要定义小数点的位置
  12. //putint(uint ui,uchar j);发送一个整型数据的asc码表达方式,需要定义小数点的位置
  13. //CR;发送一个回车换行
  14. //*************************************************************************
  15. #include <w77e58.h> //该头文件包括了51,52,80320的特殊寄存器,用在51,52上也可
  16. #define uchar unsigned
  17. char #define uint unsigned int #define OLEN 64
  18. /* size of serial transmission buffer */
  19. idata unsigned char outbuf[OLEN];
  20. /* storage for transmission buffer */
  21. unsigned char idata *outlast=outbuf; //最后由中断传输出去的字节位置
  22. unsigned char idata *putlast=outbuf;
  23. //最后放入发送缓冲区的字节位置
  24. #define ILEN 2 /* size of serial receiving buffer */
  25. idata unsigned char inbuf[ILEN];
  26. unsigned char idata *inlast=inbuf; //最后由中断进入接收缓冲区的字节位置 unsigned
  27. char idata *getlast=inbuf; //最后取走的字节位置 bit outbufsign; //输出缓冲区非空标志 有=1 bit inbufsign;
  28. //接收缓冲区非空标志 有=1
  29. bit inbufful;
  30. //输入缓冲区满标志 满=1
  31. #define CR putstring("\r\n") //CR=回车换行
  32. //*****************************
  33. //放入一个字节到发送缓冲区
  34. putbyte(char c) {uchar i,j; ES=0;
  35. /*暂停串行中断,以免数据比较时出错? */
  36. if (outlast==putlast )
  37. { i=(0-TH1);
  38. do{i--;j=36;
  39. do {j--;}while(j!=0);
  40. }while(i!=0);
  41. //延时一个字节发送时间
  42. }
  43. *putlast=c; //放字节进入缓冲区
  44. putlast++; //发送缓冲区指针加一 if
  45. (putlast==outbuf+OLEN) putlast=outbuf; //指针到了顶部换到底部
  46. if (!outbufsign)
  47. {outbufsign=1;
  48. TI=1;
  49. } //缓冲区开始为空置为有,启动发送
  50. ES=1; }
  51. //****************************** //放一串数据到发送缓冲区
  52. putbytes(unsigned char *outplace,unsigned char j)
  53. { int i; for(i=0;i<j;i++)
  54. {putbyte(*outplace);
  55. outplace++;
  56. }
  57. }
  58. //******************************
  59. //putchar(uchar c,uchar j);发送一个字节数据的asc码表达方式,需要定义小数点的位置
  60. putchar(uchar c,uchar j)
  61. {uchar idata free[4];uchar data i;
  62. i=0;
  63. free[i++]=(c/100+0x30);
  64. if (j==3) free[i++]=‘.‘;
  65. free[i++]=(c%100)/10+0x30;
  66. if (j==2) free[i++]=‘.‘;
  67. if (j==2 && free[i-3]==0x30) free[i-3]=0x20;
  68. free[i++]=(c%10)+0x30;
  69. if (j==1 && free[i-3]==0x30) free[i-3]=0x20;
  70. if (j==1 && free[i-3]==0x20 && free[i-2]==0x30) free[i-2]=0x20;
  71. putbytes(free,i);
  72. }
  73. //******************************
  74. //putint(uint ui,uchar j);发送一个整型数据的asc码表达方式,需要定义小数点的位置
  75. putint(uint ui,uchar j)
  76. {uchar idata free[6];
  77. uchar data i;
  78. //i=0;
  79. free[i++]=(ui/10000+0x30);
  80. if (j==5) free[i++]=‘.‘;
  81. free[i++]=((ui%10000)/1000+0x30);
  82. if (j==4) free[i++]=‘.‘;
  83. if (j==4 && free[i-3]==0x30) free[i-3]=0x20;
  84. free[i++]=((ui%1000)/100+0x30);
  85. if (j==3) free[i++]=‘.‘;
  86. if (j==3 && free[i-4]==0x30) free[i-4]=0x20;
  87. if (j==3 && free[i-4]==0x20 && free[i-3]==0x30) free[i-3]=0x20;
  88. free[i++]=((ui%100)/10+0x30);
  89. if (j==2) free[i++]=‘.‘;
  90. if (j==2 && free[i-5]==0x30) free[i-5]=0x20;
  91. if (j==2 && free[i-5]==0x20 && free[i-4]==0x30) free[i-4]=0x20;
  92. if (j==2 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x30) free[i-3]=0x20;
  93. free[i++]=(ui%10+0x30);
  94. if (j==1 && free[i-5]==0x30) free[i-5]=0x20;
  95. if (j==1 && free[i-5]==0x20 && free[i-4]==0x30) free[i-4]=0x20;
  96. if (j==1 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x30) free[i-3]=0x20;
  97. if (j==1 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x20 && free[i-2]==0x30) free[i-2]=0x20;
  98. putbytes(free,i);
  99. }
  100. //***************************************
  101. //发送一个字符串到串口
  102. putstring(unsigned char *puts)
  103. {for (;*puts!=0;puts++) //遇到停止符0结束
  104. putbyte(*puts);
  105. }
  106. //*************************************
  107. //发送一个字节的hex码,分成两个字节发。
  108. unsigned char code hex_[]={"0123456789ABCDEF"};
  109. puthex(unsigned char c)
  110. {int ch;
  111. ch=(c>>4)&0x0f; putbyte(hex_[ch]); ch=c&0x0f; putbyte(hex_[ch]); } //*************************************
  112. //从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
  113. uchar getbyte (void)
  114. { char idata c
  115. ; while (!inbufsign); //缓冲区空等待
  116. ES=0; c= *getlast; //取数据
  117. getlast++; //最后取走的数据位置加一
  118. inbufful=0; //输入缓冲区的满标志清零
  119. if (getlast==inbuf+ILEN) getlast=inbuf; //地址到顶部回到底部
  120. if (getlast==inlast) inbufsign=0; //地址相等置接收缓冲区空空标志,再取数前要检该标志
  121. ES=1; return (c);
  122. //取回数据 }
  123. //***************************************** //接收一行数据,必须定义放数据串的指针位置和大小
  124. del=0x7f,backspace=0x08,cr=0x0d,lf=0x0a
  125. void getline (uchar idata *line, unsigned char n)
  126. { unsigned char cnt = 0; //定义已接收的长度
  127. char c;
  128. do
  129. { if ((c = getbyte ()) == 0x0d)
  130. c = 0x00; //读一个字节,如果是回车换成结束符
  131. if (c == 0x08 || c == 0x7f) //BACKSPACE 和 DEL 的处理
  132. {
  133. if (cnt != 0) //已经输入退掉一个字符
  134. {cnt--; //总数目减一
  135. line--; //指针减一
  136. putbyte (0x08); //屏幕回显的处理
  137. putbyte (‘ ‘);
  138. putbyte (0x08);
  139. }
  140. }
  141. else
  142. { putbyte (*line = c);
  143. //其他字符取入,回显
  144. line++; //指针加一
  145. cnt++; //总数目加一
  146. }
  147. } while (cnt < n - 1 && c != 0x00 && c!=0x1b); //数目到了,回车或ESC停止
  148. *line = 0; //再加上停止符0 }
  149. //****************************
  150. //模拟接收到一个数据
  151. putinbuf(uchar c)
  152. {ES=0; if(!inbufful)
  153. {*inlast= c; //放入数据 inlast++;
  154. //最后放入的位置加一
  155. if (inlast==inbuf+ILEN)
  156. inlast=inbuf;//地址到顶部回到底部
  157. if (inlast==getlast)
  158. inbufful=1; //接收缓冲区满置满标志
  159. inbufsign=1;
  160. }
  161. ES=1;
  162. }
  163. //*****************************************
  164. //串口中断处理
  165. serial () interrupt 4 { if (TI )
  166. {
  167. TI = 0;
  168. if (outbufsign) //
  169. if (putlast==outlast)
  170. outbufsign=0; //
  171. else {SBUF=*outlast; //未发送完继续发送
  172. outlast++; //最后传出去的字节位置加一
  173. if (outlast==outbuf+OLEN)
  174. outlast=outbuf;//地址到顶部回到底部
  175. if (putlast==outlast)
  176. outbufsign=0; //数据发送完置发送缓冲区空标志
  177. }
  178. }
  179. if (RI)
  180. {
  181. RI = 0; if(!inbufful)
  182. { *inlast= SBUF; //放入数据
  183. inlast++; //最后放入的位置加一
  184. inbufsign=1;
  185. if (inlast==inbuf+ILEN)
  186. inlast=inbuf;//地址到顶部回到底部
  187. if (inlast==getlast)
  188. inbufful=1; //接收缓冲区满置满标志
  189. }
  190. }
  191. }
  192. //*****************************
  193. //串口初始化 0xfd=19200,0xfa=9600,0xf4=4800,0xe8=2400,0xd0=1200
  194. serial_init ()
  195. {
  196. SCON = 0x50; /* mode 1: 8-bit UART, enable receiver */
  197. TMOD |= 0x20; /* timer 1 mode 2: 8-Bit reload */
  198. PCON |= 0x80;
  199. TH1 = 0xfd;//fa, //baud*2
  200. /* reload value 19200 baud */
  201. TR1 = 1; /* timer 1 run */
  202. ES = 1;
  203. REN=1;
  204. EA=1;
  205. SM2=1; //SM2=1时收到的第9位为1才置位RI标志
  206. //TMOD |=0x01; //th1 auto load 2X8,th0 1X16 //TH0=31;
  207. TL0=0; //X 32 =1S //TR0=1; ET0=1; }
世界是个圈,人生也是个圈。

回复评论 (4)

回复:51单片机串行口中断服务程序

好!感谢分享!
点赞  2007-7-13 09:19

回复:51单片机串行口中断服务程序

谢谢LZ, BLESS~~~~~~~~
点赞  2007-7-16 23:59

回复:51单片机串行口中断服务程序

好东西啊,楼主辛苦了
点赞  2007-8-22 15:56
我最近也正在搞这个,谢谢LZ分享
寻求进步
点赞  2010-12-29 22:55
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复