51单片机 STC89C52 AT89S52模拟串口收发数据程序(半双工)

[复制链接]
查看36 | 回复0 | 2021-6-9 02:16:34 | 显示全部楼层 |阅读模式
本程序实现51单片机如STC89C52、AT89S52等单机模拟串口半双工收发数据,即接收数据时不能发送数据,发送数据时不能接收数据。占用系统资源定时器1或定时器2、外部中断1。当使用定时器1时,波特率固定为4800bps;当使用定时器2时,波特率在300~4800bps之间可调。

1.png 2.png

部分程序:(完整程序见本文尾部的附件)
  1. /************************************************************
  2. *  名称:  51单片机模拟半双工串口收发数据
  3. *  CPU :  STC89C52 @ 11.0592MHz
  4. *  IDE :  KeilC51 UV4
  5. *  作者 : 舒世宽
  6. *  日期 : 2021-06-08

  7. ************************************************************/


  8. #include "at89x52.h"


  9. #define BAUD                                     (4800)                                                                                        //波特率范围 300 ~  4800
  10. #define FOSC                                            (11059200UL)                                                                //晶振频率
  11. #define TMR_VAL                                   (65536UL-FOSC/12/BAUD)                        


  12. #define MYUART_TX_PIN                                   P2_3                        //可定义为除P3_3外的任意引脚
  13. #define MYUART_RX_PIN                                           P3_3                        //因为使用了外部中断,所以必须为P3_3
  14. #define MYUART_RX_BUF_LEN                   20                                //接收缓冲区长度

  15. #define MYUART_RX_LED                                          P1_0                        //接收数据指示灯
  16. #define MYUART_TX_LED                                   P1_1                        //发送数据指示灯


  17. bit MYUART_TX_FLAG = 0;                                                                                //发送模式
  18. bit MYUART_RX_FLAG = 0;                                                                                //接收模式
  19. bit MYUART_TX_BYTE_DONE = 0;                                                        //发送完成一个字节


  20. unsigned char sbufdata = 0;
  21. unsigned char data_bit_i = 0;                                                        
  22. unsigned char byte_i= 0;
  23. unsigned char myuart_rxbuf[MYUART_RX_BUF_LEN] = {0};


  24. void delay()
  25. {
  26.         
  27.                 unsigned int i,j;
  28.                 for(i=0;i<100;i++)
  29.                                 for(j=0;j<100;j++);
  30.         
  31. }



  32. void myuart_init_time()
  33. {        
  34.                 T2MOD = 0;                                                                                        //默认值
  35.                 T2CON = 0;                                                                                         //默认为16位自动重装定时器
  36.                 RCAP2L = TL2 = TMR_VAL;                                        //设置定时初值低字节
  37.                 RCAP2H = TH2 = TMR_VAL>>8;                  //设置定时初值高字节
  38.                 TF2 = 0;                                                                                                //清除TF2标志
  39.                 TR2 = 1;                                                                                                //定时器2停止计时
  40.                 ET2 = 1;                                                                                                //允许定时器2中断
  41. }

  42. void myuart_init_recv()
  43. {
  44.                 //初始化外部中断1
  45.                 IT1 = 1;   // 1 --- 下降沿触发, 0 --- 低电平持续触发
  46.           EX1 = 1;   // 开启外部中断1
  47. }


  48. //外部中断1处理程序
  49. void isr_ext1(void) interrupt 2
  50. {
  51.           unsigned char i;
  52.           if(MYUART_RX_PIN == 0)
  53.                 {
  54.                                 for(i = 0;i<5;i++);                                //延时,软件滤波
  55.                                 if(MYUART_RX_PIN == 0)
  56.                                 {
  57.                                                  EX1 = 0;                                                  //禁止外部分中断1
  58.                                           MYUART_RX_FLAG = 1;        
  59.                                           sbufdata = 0;
  60.                                                 data_bit_i = 0;
  61.                                           myuart_init_time();                                                        
  62.                                 }
  63.                 }
  64. }

  65. void isr_timer2(void) interrupt 5
  66. {
  67.                 unsigned char tmp;
  68.                 TF2 = 0;                //定时器2中断标志必须由软件清零
  69.         
  70.                 //接收
  71.                 if(MYUART_RX_FLAG == 1)
  72.                 {                        
  73.                                 MYUART_RX_PIN = 1;                        //先置位,再读取数据
  74.                           if(data_bit_i < 8){
  75.                                                 if(1==MYUART_RX_PIN)sbufdata |=  1<<data_bit_i;
  76.                                                 data_bit_i++;
  77.                                           MYUART_RX_LED  = 0;
  78.                                 }else if(data_bit_i == 8 && MYUART_RX_PIN == 1){
  79.                                                 myuart_rxbuf[byte_i++]=sbufdata;
  80.                                                 byte_i %= MYUART_RX_BUF_LEN;                 //防止溢出接收缓冲区
  81.                                           TR2 = 0;                                                                         //关闭定时器2
  82.                                                 EX1 = 1;                                                                  //允许外部分中断1        
  83.                                           MYUART_RX_LED  = 1;
  84.                                                 MYUART_RX_FLAG  =                0;                //接收结束
  85.                                           MYUART_RX_PIN = 1;                                //置位,准备后面数据接收
  86.                                 }else{
  87.                                                 TR2 = 0;                                                                         //关闭定时器2
  88.                                                 EX1 = 1;                                                                  //允许外部分中断1        
  89.                                           MYUART_RX_LED  = 1;               
  90.                                                 MYUART_RX_FLAG  =                0;                //接收结束
  91.                                           MYUART_RX_PIN = 1;                                //置位,准备后面数据接收
  92.                                 }
  93.                 }
  94.                
  95.                 //发送
  96.                 if(MYUART_TX_FLAG == 1)
  97.                 {  

  98.                                 if(data_bit_i ==0){                                                        
  99.                                                 MYUART_TX_PIN = 0;                                        //拉低,发送起始位               
  100.                                                 MYUART_TX_LED = 0;
  101.                                 }else if(data_bit_i < 9){
  102.                                                 tmp = sbufdata & (1<<(data_bit_i-1));//先发送低位再发送高位
  103.                                                 if(tmp == 0)
  104.                                                                 MYUART_TX_PIN = 0;               
  105.                                                 else
  106.                                                                 MYUART_TX_PIN = 1;
  107.                                          
  108.                                 }else if(data_bit_i < 12){    //连续3个停止位的时间
  109.                                                 MYUART_TX_PIN = 1;                          //拉高,发送停止位
  110.                                 }else{
  111.                                                 TR2 = 0;  
  112.                                                 RCAP2L = TL2 = TMR_VAL;                                        //设置定时初值低字节
  113.                                                 RCAP2H = TH2 = TMR_VAL>>8;                  //设置定时初值高字节
  114.                                                 MYUART_TX_BYTE_DONE = 1;        // 发送完成一个字节        
  115.                                                 MYUART_TX_LED = 1;
  116.                                                 MYUART_TX_PIN = 1;                          //拉高,准备后面数据发送
  117.                                                 
  118.                                 }
  119.                                 data_bit_i++;
  120.                 }

  121.                
  122.                
  123. }

  124. void myuart_write_byte(unsigned char dat)
  125. {        
  126.           data_bit_i = 0;
  127.                 sbufdata = dat;
  128.            TR2 = 1;                                                                                         //启动定时器
  129.           MYUART_TX_BYTE_DONE = 0;        
  130.                 while(MYUART_TX_BYTE_DONE==0);
  131. }

  132. void myuartSendString(char * pstr)
  133. {   
  134.           if(*pstr)
  135.           {
  136.                                 MYUART_TX_FLAG = 1;
  137.                                 myuart_init_time();        
  138.                                 while(*pstr)
  139.                                 {
  140.                                                 myuart_write_byte(*pstr++);
  141.                                 }
  142.                                 MYUART_TX_FLAG = 0;
  143.                 }
  144.          
  145. }

  146. void myuartSendBuffer(unsigned char * pbuf,unsigned char len)
  147. {   
  148.                 unsigned  char i;
  149.           if(len>0)
  150.                 {
  151.                                 MYUART_TX_FLAG = 1;
  152.                           myuart_init_time();        
  153.                                 for(i=0;i<len;i++)myuart_write_byte(pbuf[i]);
  154.                                 MYUART_TX_FLAG = 0;
  155.                 }
  156. }



  157. void main(void)
  158. {
  159.         
  160.           int a,b,i;
  161.                 MYUART_TX_PIN  = 1;
  162.                 MYUART_RX_PIN  = 1;
  163.           EA = 1;                                                                //开启全局中断
  164.                 myuart_init_recv();                //串口接收初始化
  165.                 while(1){
  166.                                 
  167.                                 
  168.                                 delay();a  = byte_i;
  169.                                 delay();b = byte_i;
  170.                                 if(a==b && a>0)
  171.                                 {
  172.                                             myuartSendBuffer(myuart_rxbuf,byte_i);
  173.                                             for(i=0;i<MYUART_RX_BUF_LEN;i++)myuart_rxbuf[i] = 0;
  174.                                             a=0;b=0;byte_i=0;
  175.                                 }
  176.                                 //myuartSendString("my uart demo test! shushikuan@163.com 12345 ok!!!!");  //50个字符
  177.                                 //myuartSendString("my uart demo test ok");  
  178.                         
  179.                 }

  180. }
复制代码
51单片机模拟串口通信完整源码.zip (51.66 KB, 售价: 2 工控币)
回复

使用道具 举报

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

本版积分规则