找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3195|回复: 13
收起左侧

怎么调试模拟串口?(有带起始位设置的串口助手?)

[复制链接]
ID:472235 发表于 2019-12-18 21:40 | 显示全部楼层 |阅读模式
本帖最后由 121212121212123 于 2019-12-18 21:44 编辑



stc15 89c52rc微控制器模拟串行调试:发送到串口助手没问题的,但接收就不行了,有大佬搞这个吗??

#include <reg52.h>
#include“ config.h”

sbit PIN_RXD = P1 ^ 2;
比特PIN_TXD = P1 ^ 3;

位RxdEnd = 0;
位RxdOrTxd = 0;
位TxdEnd = 0;

unsigned char RxdBuf = 0;
unsigned charTxdBuf = 0;

void ConfigUART(unsigned int baud);
void StartRXD();
void StartTXD(unsigned char dat);

static unsigned char cnt = 0;

void main()
{
        EA = 1;
        ConfigUART(9600);

        while(1)
        {
                led1 = 0;
                while(PIN_RXD);
                led2 = 0;
                StartRXD();
                while(!RxdEnd);
                StartTXD(RxdBuf);
                while(!TxdEnd);
        }

}
void ConfigUART(unsigned int baud)
{
        TMOD&= 0xF0;
        TMOD | = 0x01;
        TH0 = 256-(11059200/12)/波特;
}
void StartRXD()
{
        TL0 = TH0;
        ET0 = 1;
        TR0 = 1;
        RxdEnd = 0;
        RxdOrTxd = 0;
}
void StartTXD(unsigned char dat)
{
        TxdBuf = dat;
        TL0 = TH0;
        ET0 = 1;
        TR0 = 1;
        PIN_TXD = 0;
        TxdEnd = 0;
        RxdOrTxd = 1;
}
void InterruptTimer0()中断1
{                 
// uint8 i;
//
//                 
// TH0 = 256-(11059200/12)/ 9600;
// TL0 = TH0;
//
// i ++;
// if(i == 10){
// i = 0;
// led4 =〜led4;
//}
                led3 = 0;

        if(RxdOrTxd)
        {//发送
                cnt ++;
                if(cnt <= 8)
                {
                                                
                                                                                                
                        PIN_TXD = TxdBuf&0x01;
                        TxdBuf >> = 1;
                }
                else if(cnt == 9)
                {
                         PIN_TXD = 1;
                }
                else
                {
                        cnt = 0;
                        TR0 = 0;
                        TxdEnd = 1;
                }
        }
        else            
        {
                if(cnt == 0)
                {
                        if(!PIN_RXD)
                        {
                                RxdBuf = 0;
                                cnt ++;
                        }
                        else
                        {
                                TR0 = 0;
                        }
                }
                if(cnt <= 8)
                                {                 
                                                led4 = 0;
                        RxdBuf >> = 1;            
                        if(PIN_RXD)
                        {
                                RxdBuf | = 0x80;
                        }
                        cnt ++;
                }
                其他
                {
                        cnt = 0;
                        TR0 = 0;
                        if(PIN_RXD)
                        {
                                RxdEnd = 1;
                        }
                }
        }
}


回复

使用道具 举报

ID:213173 发表于 2019-12-19 11:04 | 显示全部楼层
STC有模拟串口的官方范例程序:
  1. /*---------------------------------------------------------------------*/
  2. /* --- STC MCU Limited ------------------------------------------------*/
  3. /* --- STC15Fxx 系列 软件模拟串口举例----------------------------------*/
  4. /* --- Mobile: (86)13922805190 ----------------------------------------*/
  5. /* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
  6. /* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
  7. /* --- Web: www.STCMCU.com --------------------------------------------*/
  8. /* --- Web: www.GXWMCU.com --------------------------------------------*/
  9. /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
  10. /* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
  11. /*---------------------------------------------------------------------*/

  12. //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
  13. //若无特别说明,工作频率一般为11.0592MHz


  14. #include "reg51.h"

  15. //-----------------------------------------
  16. //define baudrate const
  17. //BAUD = 65536 - FOSC/3/BAUDRATE/M (1T:M=1; 12T:M=12)
  18. //NOTE: (FOSC/3/BAUDRATE) must be greater then 98, (RECOMMEND GREATER THEN 110)

  19. //#define BAUD  0xF400                  // 1200bps @ 11.0592MHz
  20. //#define BAUD  0xFA00                  // 2400bps @ 11.0592MHz
  21. //#define BAUD  0xFD00                  // 4800bps @ 11.0592MHz
  22. //#define BAUD  0xFE80                  // 9600bps @ 11.0592MHz
  23. //#define BAUD  0xFF40                  //19200bps @ 11.0592MHz
  24. #define BAUD  0xFFA0                    //38400bps @ 11.0592MHz

  25. //#define BAUD  0xEC00                  // 1200bps @ 18.432MHz
  26. //#define BAUD  0xF600                  // 2400bps @ 18.432MHz
  27. //#define BAUD  0xFB00                  // 4800bps @ 18.432MHz
  28. //#define BAUD  0xFD80                  // 9600bps @ 18.432MHz
  29. //#define BAUD  0xFEC0                  //19200bps @ 18.432MHz
  30. //#define BAUD    0xFF60                //38400bps @ 18.432MHz

  31. //#define BAUD  0xE800                  // 1200bps @ 22.1184MHz
  32. //#define BAUD  0xF400                  // 2400bps @ 22.1184MHz
  33. //#define BAUD  0xFA00                  // 4800bps @ 22.1184MHz
  34. //#define BAUD  0xFD00                  // 9600bps @ 22.1184MHz
  35. //#define BAUD  0xFE80                  //19200bps @ 22.1184MHz
  36. //#define BAUD  0xFF40                  //38400bps @ 22.1184MHz
  37. //#define BAUD  0xFF80                  //57600bps @ 22.1184MHz

  38. sfr AUXR = 0x8E;
  39. sbit RXB = P3^0;                        //define UART TX/RX port
  40. sbit TXB = P3^1;

  41. typedef bit BOOL;
  42. typedef unsigned char BYTE;
  43. typedef unsigned int WORD;

  44. BYTE TBUF,RBUF;
  45. BYTE TDAT,RDAT;
  46. BYTE TCNT,RCNT;
  47. BYTE TBIT,RBIT;
  48. BOOL TING,RING;
  49. BOOL TEND,REND;

  50. void UART_INIT();

  51. BYTE t, r;
  52. BYTE buf[16];

  53. void main()
  54. {
  55.     TMOD = 0x00;                        //timer0 in 16-bit auto reload mode
  56.     AUXR = 0x80;                        //timer0 working at 1T mode
  57.     TL0 = BAUD;
  58.     TH0 = BAUD>>8;                      //initial timer0 and set reload value
  59.     TR0 = 1;                            //tiemr0 start running
  60.     ET0 = 1;                            //enable timer0 interrupt
  61.     PT0 = 1;                            //improve timer0 interrupt priority
  62.     EA = 1;                             //open global interrupt switch

  63.     UART_INIT();

  64.     while (1)
  65.     {                                   //user's function
  66.         if (REND)
  67.         {
  68.             REND = 0;
  69.             buf[r++ & 0x0f] = RBUF;
  70.         }
  71.         if (TEND)
  72.         {
  73.             if (t != r)
  74.             {
  75.                 TEND = 0;
  76.                 TBUF = buf[t++ & 0x0f];
  77.                 TING = 1;
  78.             }
  79.         }
  80.     }
  81. }

  82. //-----------------------------------------
  83. //Timer interrupt routine for UART

  84. void tm0() interrupt 1
  85. {
  86.     if (RING)
  87.     {
  88.         if (--RCNT == 0)
  89.         {
  90.             RCNT = 3;                   //reset send baudrate counter
  91.             if (--RBIT == 0)
  92.             {
  93.                 RBUF = RDAT;            //save the data to RBUF
  94.                 RING = 0;               //stop receive
  95.                 REND = 1;               //set receive completed flag
  96.             }
  97.             else
  98.             {
  99.                 RDAT >>= 1;
  100.                 if (RXB) RDAT |= 0x80;  //shift RX data to RX buffer
  101.             }
  102.         }
  103.     }
  104.     else if (!RXB)
  105.     {
  106.         RING = 1;                       //set start receive flag
  107.         RCNT = 4;                       //initial receive baudrate counter
  108.         RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
  109.     }

  110.     if (--TCNT == 0)
  111.     {
  112.         TCNT = 3;                       //reset send baudrate counter
  113.         if (TING)                       //judge whether sending
  114.         {
  115.             if (TBIT == 0)
  116.             {
  117.                 TXB = 0;                //send start bit
  118.                 TDAT = TBUF;            //load data from TBUF to TDAT
  119.                 TBIT = 9;               //initial send bit number (8 data bits + 1 stop bit)
  120.             }
  121.             else
  122.             {
  123.                 TDAT >>= 1;             //shift data to CY
  124.                 if (--TBIT == 0)
  125.                 {
  126.                     TXB = 1;
  127.                     TING = 0;           //stop send
  128.                     TEND = 1;           //set send completed flag
  129.                 }
  130.                 else
  131.                 {
  132.                     TXB = CY;           //write CY to TX port
  133.                 }
  134.             }
  135.         }
  136.     }
  137. }

  138. //-----------------------------------------
  139. //initial UART module variable

  140. void UART_INIT()
  141. {
  142.     TING = 0;
  143.     RING = 0;
  144.     TEND = 1;
  145.     REND = 0;
  146.     TCNT = 0;
  147.     RCNT = 0;
  148. }

复制代码
回复

使用道具 举报

ID:472235 发表于 2019-12-19 22:45 | 显示全部楼层
wulin 发表于 2019-12-19 11:04
STC有模拟串口的官方范例程序:

谢谢了哈,马上去试下
回复

使用道具 举报

ID:472235 发表于 2019-12-19 23:27 | 显示全部楼层
wulin 发表于 2019-12-19 11:04
STC有模拟串口的官方范例程序:

它的芯片好像不是89C52RC的,是intel 8058的,变量太多了
回复

使用道具 举报

ID:213173 发表于 2019-12-20 06:41 | 显示全部楼层
121212121212123 发表于 2019-12-19 23:27
它的芯片好像不是89C52RC的,是intel 8058的,变量太多了

不是intel 8058,只是在Keil开发环境下选择Intel的8058芯片型号进行编译。其差别是增加1个寄存器地址
sfr AUXR = 0x8E;  STC公司的1T芯片才有此特殊功能寄存器,
实验是STC15Fxx。这个程序51核心的芯片都可以用,89C52RC没有AUXR寄存器,只要比特率不是太高,不影响对定时器的操作。
回复

使用道具 举报

ID:213173 发表于 2019-12-20 11:13 | 显示全部楼层
121212121212123 发表于 2019-12-19 23:27
它的芯片好像不是89C52RC的,是intel 8058的,变量太多了

给你改成适合STC89C52RC的模拟串口程序,最高波特率1200,最大数据串16给字节。
  1. #include "reg51.h"

  2. typedef unsigned char uchar;
  3. typedef unsigned int uint;

  4. sbit RXB = P3^0;         //定义UART TX/RX端口
  5. sbit TXB = P3^1;

  6. uchar TBUF,RBUF;
  7. uchar TDAT,RDAT;
  8. uchar TCNT,RCNT;
  9. uchar TBIT,RBIT;
  10. bit TING,RING;
  11. bit TEND,REND;
  12. uchar t, r;
  13. uchar buf[16];

  14. //初始UART模块
  15. void UART_INIT()
  16. {
  17.         TING = 0;
  18.         RING = 0;
  19.         TEND = 1;
  20.         REND = 0;
  21.         TCNT = 0;
  22.         RCNT = 0;
  23.         TMOD = 0x02;   //8位自动重载12T模式
  24.         TL1 = 0xE8;                //设定定时初值(波特率1200)
  25.         TH1 = 0xE8;                //设定定时器重装值
  26. //        TMOD = 0x00;   // 16位自动重载模式中的Time0
  27. //        AUXR = 0x80;   // 1T工作模式
  28. //        TL0 = BAUD;
  29. //        TH0 = BAUD>>8; // 初始Time0和设置重载值
  30.         TR0  = 1;      // tiemr0开始运行
  31.         ET0  = 1;      // 启用Time0中断
  32.         PT0  = 1;      // 提高定时中断优先级
  33.         EA   = 1;      // 打开全局中断开关
  34. }
  35. //
  36. void main()
  37. {
  38.         UART_INIT();   //初始UART模块
  39.         while (1)
  40.         {              //用户功能
  41.                 if (REND)   //接收完成标志为真
  42.                 {
  43.                         REND = 0;//接收完成标志清0
  44.                         buf[r++ & 0x0f] = RBUF;//保存在缓存中
  45.                 }
  46.                 if (TEND)
  47.                 {
  48.                         if (t != r)
  49.                         {
  50.                                 TEND = 0;
  51.                                 TBUF = buf[t++ & 0x0f];//发送缓存中数据
  52.                                 TING = 1;
  53.                         }
  54.                 }
  55.         }
  56. }
  57. //UART定时器中断例程
  58. void tm0() interrupt 1 using 1
  59. {
  60.         if (RING)
  61.         {
  62.                 if (--RCNT == 0)
  63.                 {
  64.                         RCNT = 3;                   //重置发送波特率计数器
  65.                         if (--RBIT == 0)
  66.                         {
  67.                                 RBUF = RDAT;            //将数据保存到RBUF
  68.                                 RING = 0;               //停止接收
  69.                                 REND = 1;               //设置接收完成标志
  70.                         }
  71.                         else
  72.                         {
  73.                                 RDAT >>= 1;
  74.                                 if (RXB) RDAT |= 0x80;  //将RX数据转换为RX缓冲区
  75.                         }
  76.                 }
  77.         }
  78.         else if (!RXB)
  79.         {
  80.                 RING = 1;                       //设置开始接收标志
  81.                 RCNT = 4;                       //初始接收波特率计数器
  82.                 RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
  83.         }                                                                                          //初始接收比特数(8个数据位+ 1个停止位)
  84.         if (--TCNT == 0)
  85.         {
  86.                 TCNT = 3;                       //重置发送波特率计数器
  87.                 if (TING)                       //判断是否发送
  88.                 {
  89.                         if (TBIT == 0)
  90.                         {
  91.                                 TXB = 0;                //发送起始位
  92.                                 TDAT = TBUF;            //加载数据 TBUF 到 TDAT
  93.                                 TBIT = 9;               //initial send bit number (8 data bits + 1 stop bit)
  94.                         }                                                                        //初始发送比特数(8个数据位+ 1个停止位)
  95.                         else
  96.                         {
  97.                                 TDAT >>= 1;             //将数据转换到CY
  98.                                 if (--TBIT == 0)
  99.                                 {
  100.                                         TXB = 1;
  101.                                         TING = 0;           //停止发送
  102.                                         TEND = 1;           //设置发送完成标志
  103.                                 }
  104.                                 else
  105.                                 {
  106.                                         TXB = CY;           //将CY写入TX端口
  107.                                 }
  108.                         }
  109.                 }
  110.         }
  111. }
复制代码
回复

使用道具 举报

ID:472235 发表于 2019-12-20 14:56 | 显示全部楼层
wulin 发表于 2019-12-20 11:13
给你改成适合STC89C52RC的模拟串口程序,最高波特率1200,最大数据串16给字节。

我拷过去了,但它会乱码,而且有时发一次,返回几十个数据
回复

使用道具 举报

ID:213173 发表于 2019-12-20 17:12 | 显示全部楼层
121212121212123 发表于 2019-12-20 14:56
我拷过去了,但它会乱码,而且有时发一次,返回几十个数据

这个程序是在STC89C52RC实验板验证过的,波特率1200。
回复

使用道具 举报

ID:213173 发表于 2019-12-20 17:14 | 显示全部楼层
121212121212123 发表于 2019-12-20 14:56
我拷过去了,但它会乱码,而且有时发一次,返回几十个数据

晶振11.0592MHz
回复

使用道具 举报

ID:472235 发表于 2019-12-21 20:51 | 显示全部楼层

先谢谢大佬,我用之前找到的代码跑成功了,现在在想两字节的串口通信,用的是这个代码:

#include<reg52.h>
sbit PIN_RXD = P3^0;
sbit PIN_TXD = P3^1;
bit RxdEnd = 0;
bit RxdOrTxd = 0;
bit TxdEnd = 0;
unsigned char RxdBuf = 0;
unsigned char TxdBuf = 0;
void ConfigUART(unsigned int baud);
void StartRXD();
void StartTXD(unsigned char dat);
void main()
{
        EA = 1;
        ConfigUART(9600);
      
        while(1)
        {
                while(PIN_RXD);
                StartRXD();
                while(!RxdEnd);
                StartTXD(RxdBuf);
                while(!TxdEnd);
        }
      
}
void ConfigUART(unsigned int baud)
{
        TMOD &= 0xF0;
        TMOD |= 0x02;
        TH0 = 256 - (11059200/12)/baud;
}
void StartRXD()
{
        TL0 = 256 - ((256 - TH0)>>1)+4;//之所以加4是因为实地测试发送数据还行,但接收数据误差率太大,估计是51速度太慢,中断中语句太多,当波特率低于9600时可不加4,波特率等于9600则加3以上
        ET0 = 1;
        TR0 = 1;
        RxdEnd = 0;
        RxdOrTxd = 0;
}
void  StartTXD(unsigned char dat)
{
        TxdBuf = dat;
        TL0 = TH0;
        ET0 = 1;
        TR0 = 1;
        PIN_TXD = 0;
        TxdEnd = 0;
        RxdOrTxd = 1;
}
void InterruptTimer0() interrupt 1
{
        static unsigned char cnt = 0;
        if(RxdOrTxd)
        {
                cnt++;
                if(cnt <= 8)
                {
                        PIN_TXD = TxdBuf & 0x01;
                        TxdBuf >>= 1;
                }
                else if(cnt == 9)
                {
                         PIN_TXD = 1;
                }
                else
                {
                        cnt = 0;
                        TR0 = 0;
                        TxdEnd = 1;
                }
        }
        else
        {
                if(cnt == 0)
                {
                        if(!PIN_RXD)
                        {
                                RxdBuf = 0;
                                cnt++;
                        }
                        else
                        {
                                TR0 = 0;
                        }
                }
                else if(cnt <= 8)
                {
                        RxdBuf >>= 1;            
                        if(PIN_RXD)
                        {
                                RxdBuf |= 0x80;
                        }
                        cnt++;
                }
                else
                {
                        cnt = 0;
                        TR0 = 0;
                        if(PIN_RXD)
                        {
                                RxdEnd = 1;
                        }
                }
        }
}
回复

使用道具 举报

ID:472235 发表于 2019-12-21 20:51 | 显示全部楼层

如果要实现两个字节的模拟串口通信,会不会难度很大??
回复

使用道具 举报

ID:472235 发表于 2019-12-21 21:22 | 显示全部楼层

谢谢大佬,都搞定了
回复

使用道具 举报

ID:472235 发表于 2019-12-21 21:24 | 显示全部楼层
STC89C52RC 双字节两次传输串口通信模拟(可扩展多字节):
#include<reg52.h>
#include "config.h"
#include "lcd1602.h"

sbit PIN_RXD = P3^0;
sbit PIN_TXD = P3^1;

bit RxdEnd = 0;
bit RxdOrTxd = 0;
bit TxdEnd = 0;

unsigned int RxdBuf = 0;
unsigned int TxdBuf = 0;

void ConfigUART(unsigned int baud);
void StartRXD();
void StartTXD(unsigned char dat);

unsigned char *p;
//unsigned char *p2;
unsigned char buff[3];
//unsigned char buff2[2];
unsigned char key;
unsigned char i = 0;

void main()
{
        EA = 1;
        ConfigUART(9600);
      
        while(1)
        {
                                led1 = ~led1;
                                while(PIN_RXD);        //0低电平进入
                while(key <= 1){        //key = 0,下一次key = 1;
                                        while(PIN_RXD);
                        StartRXD();
                        while(!RxdEnd);
                                        key++;                        //高电平时间
                                }
                                led3 = ~led3;
                                key = 0;
                                for(i = 0;i<=1;i++){
                                        StartTXD(buff[i]);
                                        while(!TxdEnd);
                                }                              
                                p = buff;
                                Lcd1602_Init();
                                Lcd1602_Show_String(1,1,p);
                       

        }
      
}
void ConfigUART(unsigned int baud)
{
        TMOD &= 0xF0;
        TMOD |= 0x02;
        TH0 = 256 - (11059200/12)/baud;
}
void StartRXD()
{
        TL0 = 256 - ((256 - TH0)>>1)+20;//之所以加4是因为实地测试发送数据还行,但接收数据误差率太大,估计是51速度太慢,中断中语句太多,当波特率低于9600时可不加4,波特率等于9600则加3以上
        ET0 = 1;
        TR0 = 1;
        RxdEnd = 0;
        RxdOrTxd = 0;
}
void  StartTXD(unsigned char dat)
{
        TxdBuf = dat;
        TL0 = TH0;
        ET0 = 1;
        TR0 = 1;
        PIN_TXD = 0;
        TxdEnd = 0;
        RxdOrTxd = 1;
}
void InterruptTimer0() interrupt 1
{
        static unsigned char cnt = 0;
        if(RxdOrTxd)
        {
                cnt++;
                if(cnt <= 8)
                {
                        PIN_TXD = TxdBuf & 0x01;
                        TxdBuf >>= 1;
                }
                else if(cnt == 9)
                {
                         PIN_TXD = 1;
                }
                else
                {
                               led4 = ~led4;
                                            cnt = 0;
                        TR0 = 0;
                        TxdEnd = 1;
                }
        }
        else
        {
                if(cnt == 0)
                {
                        if(!PIN_RXD)
                        {
                                RxdBuf = 0;
                                cnt++;
                        }
                        else
                        {
                                TR0 = 0;
                        }
                }
                else if(cnt <= 8)
                {
                        RxdBuf >>= 1;            
                        if(PIN_RXD)
                        {
                                RxdBuf |= 0x80;
                        }
                        cnt++;
                }
                else
                {
                                                if(key == 0){
                                                    buff[0] = RxdBuf;
                                                }else if(key == 1){
                                                        buff[1] = RxdBuf;
                                                        buff[2] = '\0';       
                                                }
                                               
//                                                buff[1] = '\0';
                        cnt = 0;
                        TR0 = 0;
                        if(PIN_RXD)         //当两个字节发送时,存不存在不为高电平?
                        {
                                led2 = ~led2;
                                                                RxdEnd = 1;
                        }
                }
        }
}
回复

使用道具 举报

ID:284226 发表于 2023-5-11 20:53 | 显示全部楼层
楼主。太厉害了,我也在看。你那个看懂了?    发送时,PIN_TXD = TxdBuf & 0x01;为什么先要&这个一步,还有接收时
RXDBuf |=0x80;为什么要走这一步呢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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