amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 257|回复: 12

STC15W4K32S4串口4收发不正常问题求助

[复制链接]
发表于 2019-4-16 11:54:00 | 显示全部楼层 |阅读模式
如题,先是写了一个测试程序,让串口1发送01 02,串口4发送02 03,现在串口发送1正常,可是连接到串口4后现,串口4也同样会发送01 02,但是却不会发送02 03,程序如下:
#include "STC15F2K60S2.H"

sbit TEST_LED = P4^1;
bit TEST_B = 0;
unsigned char XT_TIME=100;

void Serial_Init(void)//串口初始化函数
{
        TMOD = 0x00;   //定时器0,16位自动重新模式             
        TL0  = 0x00;   //设置定时器0低8位初值
        TH0  = 0xDC;   //设置定时器0高8位初值 定时为10毫秒
        TF0  = 0;           //清除TF0标志
        TR0  = 1;           //定时器0关闭          
        ET0  = 1;           //                                
       
//        SCON = 0x50;         //8位数据,可变波特率,允许接收
        SCON = 0x40;         //8位数据,可变波特率,不允许接收
        AUXR |= 0x01;         //串口1选择定时器2为波特率发生器
        AUXR &= 0xFB;    //定时器2时钟为Fosc/12,即12T
        T2L = 0xFE;                 //设定定时初值
        T2H = 0xFF;                 //设定定时初值
        AUXR |= 0x10;         //启动定时器2

    S4CON = 0x80;    //8位可变波特率,串口4选择定时器2为波特率发生器
        IE2 = 0x10;                 //允许串口4中断
        EA   = 1;        //开启全局中断                               
}

void send_hex(unsigned char b)         
{       
    ES = 0;              
    SBUF = b;
    while(!TI);        
    TI = 0;            
        ES = 1;               
}

void S4end_hex(unsigned char b)
{
        IE2=0;//关闭串口4中断,不允许定时器2中断
    S4BUF = b;
    while(!(S4CON&0x02));        
    S4CON = 0x80;                     
        IE2=0x10;//打开串口4中断,不允许定时器2中断
}

void main()
{
        Serial_Init();
        P_SW1=0x00;//切换端口               
        while(1)
        {
                if(TEST_B)//测试串口2程序
                {
                        TEST_B=0;
                        send_hex(0x01);
                        send_hex(0x02);
                        S4end_hex(0x03);
                        S4end_hex(0x04);
                        TEST_LED=!TEST_LED;
                }
                                                                                                                                                                                          
        }
}

void Timer0_Int() interrupt 1  //定时器0中断
{
        if(XT_TIME>0)
        {
                XT_TIME--;
                if(XT_TIME==0)
                {
                        XT_TIME=200;
                        TEST_B=1;                       
                }
        }                                                                                                                                           
}

void Serial_Int() interrupt 4  //串口1中断
{
        ES = 0;         
        if(TI)
        {
                TI = 0;
        }
        if(RI)       
        {
                RI = 0;
        }
   ES = 1;       
}

void Uart4() interrupt 18 using 1 //串口4中断
{
        IE2=0x00;
    if (S4CON&0x01)
    {
        S4CON=0x80;         //清除S4RI位
    }
    if (S4CON&0x02)
    {
        S4CON=0x80;         //清除S4TI位
    }
        IE2=0x10;
}
发表于 2019-4-16 12:04:09 | 显示全部楼层
本帖最后由 lcw_swust 于 2019-4-16 12:07 编辑

楼主学一下C语言的位操作吧,
S4CON=0x80;         //清除S4RI位,这样其实也把TI位清掉了。
可写成
S4CON&=~1;

发送数据没必要关中断的,不然在发的同时有收到数据怎么办。
可添加一个标志,在发送中断里置位,使发送等待读取此标志后退出等待。
 楼主| 发表于 2019-4-16 13:35:17 | 显示全部楼层
lcw_swust 发表于 2019-4-16 12:04
楼主学一下C语言的位操作吧,
S4CON=0x80;         //清除S4RI位,这样其实也把TI位清掉了。
可写成

这个只是测试发送,没有测试接收,这个应该不会有影响的吧,问题应该不是出在这里。
发表于 2019-4-16 16:19:03 | 显示全部楼层
wxdn 发表于 2019-4-16 13:35
这个只是测试发送,没有测试接收,这个应该不会有影响的吧,问题应该不是出在这里。 ...


我这边试了下,串口4正常,发送的是03 04,因为程序就是发的03 04,内部时钟11.0592,波特率115200.
S4end_hex(0x03);
S4end_hex(0x04);

程序没问题,检查硬件吧。
 楼主| 发表于 2019-4-16 17:12:12 | 显示全部楼层
lcw_swust 发表于 2019-4-16 16:19
我这边试了下,串口4正常,发送的是03 04,因为程序就是发的03 04,内部时钟11.0592,波特率115200.
S4en ...


测试了一下,发送是正常的,麻烦测试一下接收正常吗,刚刚写了一个测试程序,把收到的数据返回,无法返回。
 楼主| 发表于 2019-4-16 17:20:04 | 显示全部楼层
#include "STC15F2K60S2.H"

sbit TEST_LED = P4^1;
bit TEST_B = 0;
unsigned char XT_TIME;
unsigned char xdata XT_TX_RX_DATA[20];
unsigned char data XT_TR_Su=0;
void Serial_Init(void)//串口初始化函数
{
        TMOD = 0x00;   //定时器0,16位自动重新模式             
        TL0  = 0x00;   //设置定时器0低8位初值
        TH0  = 0xDC;   //设置定时器0高8位初值 定时为10毫秒
        TF0  = 0;           //清除TF0标志
        TR0  = 1;           //定时器0关闭          
        ET0  = 1;           //                                
       
//        SCON = 0x50;         //8位数据,可变波特率,允许接收
        SCON = 0x40;         //8位数据,可变波特率,不允许接收
        AUXR |= 0x01;         //串口1选择定时器2为波特率发生器
        AUXR &= 0xFB;    //定时器2时钟为Fosc/12,即12T
        T2L = 0xFE;                 //设定定时初值
        T2H = 0xFF;                 //设定定时初值
        AUXR |= 0x10;         //启动定时器2

    S4CON = 0x80;    //8位可变波特率,串口4选择定时器2为波特率发生器
        IE2 = 0x10;                 //允许串口4中断
        EA   = 1;        //开启全局中断                               
}

void send_hex(unsigned char b)         
{       
    ES = 0;              
    SBUF = b;
    while(!TI);        
    TI = 0;            
        ES = 1;               
}

void S4end_hex(unsigned char b)
{
        IE2=0;//关闭串口4中断,不允许定时器2中断
    S4BUF = b;
    while(!(S4CON&0x02));        
    S4CON = 0x80;                     
        IE2=0x10;//打开串口4中断,不允许定时器2中断
}
void TEST_S4TX(void)
{
        unsigned char i;
    for (i=0; i<XT_TR_Su; i++)
        {
                S4end_hex(XT_TX_RX_DATA[i]);       
        }
    for (i=0; i<XT_TR_Su; i++)
        {
                XT_TX_RX_DATA[i]=0;       
        }
        XT_TR_Su=0;               
}
void main()
{
        Serial_Init();
        P_SW1=0x00;//切换端口
                        send_hex(0x01);
                        send_hex(0x02);                       
        while(1)
        {
                if(TEST_B==1&&XT_TIME==0)//测试串口2程序
                {
                        TEST_B=0;
                        TEST_S4TX();
                        TEST_LED=!TEST_LED;
                }
                                                                                                                                                                                          
        }
}

void Timer0_Int() interrupt 1  //定时器0中断
{
        if(XT_TIME>0)
        {
                XT_TIME--;
        }                                                                                                                                           
}

void Serial_Int() interrupt 4  //串口1中断
{
        ES = 0;         
        if(TI)
        {
                TI = 0;
        }
        if(RI)       
        {
                RI = 0;                 
        }
   ES = 1;       
}

void Uart4() interrupt 18 using 1 //串口4中断
{
        IE2=0x00;
    if(S4CON&0x01)
    {
        S4CON=0x80;         //清除S4RI位
                XT_TX_RX_DATA[XT_TR_Su]=S4BUF;
                XT_TR_Su++;
                if(XT_TR_Su>20)
                {
                        XT_TR_Su=0;
                }
                XT_TIME=50;
                TEST_B=1;
    }
    if(S4CON&0x02)
    {
        S4CON=0x80;         //清除S4TI位
    }
        IE2=0x10;
}
发表于 2019-4-16 17:41:44 | 显示全部楼层
wxdn 发表于 2019-4-16 17:20
#include "STC15F2K60S2.H"

sbit TEST_LED = P4^1;

有两处错误:
1.S4REN未置位
修改:S4CON = 0x80;
改为:S4CON = 0x90;
2.XT_TR_Su处理有问题
接收时if(XT_TR_Su>20)
                {
                        XT_TR_Su=0;
                }
发送时for (i=0; i<XT_TR_Su; i++) 就发送0个数了。
 楼主| 发表于 2019-4-16 17:58:28 | 显示全部楼层
lcw_swust 发表于 2019-4-16 17:41
有两处错误:
1.S4REN未置位
修改:S4CON = 0x80;

非常感谢您的指点,谢谢,测试了一下,可以收发了,电脑每次发送00-0F,可是返回的数据,但是却不正确,很奇怪,波特率是115200的,你那边是这样的吗?
 楼主| 发表于 2019-4-16 18:38:50 | 显示全部楼层
看了一下,改成10就可以了,谢谢!
发表于 2019-4-16 18:40:35 | 显示全部楼层
wxdn 发表于 2019-4-16 17:58
非常感谢您的指点,谢谢,测试了一下,可以收发了,电脑每次发送00-0F,可是返回的数据,但是却不正确, ...

我这边发AA 55 16 00
返回 AA 55 11 00
也是有错的,所以估计是你的定时器值算得不够准。
 楼主| 发表于 2019-4-16 20:20:01 | 显示全部楼层
lcw_swust 发表于 2019-4-16 18:40
我这边发AA 55 16 00
返回 AA 55 11 00
也是有错的,所以估计是你的定时器值算得不够准。  ...

把S4CON = 0x90;改成S4CON = 0x10一切就正常了
发表于 2019-4-16 20:51:05 | 显示全部楼层
本帖最后由 lcw_swust 于 2019-4-16 20:54 编辑
wxdn 发表于 2019-4-16 20:20
把S4CON = 0x90;改成S4CON = 0x10一切就正常了


哦,原来如此。
分享一下我的代码:
  1. //--------------------------------------------------
  2. //                类型定义
  3. //--------------------------------------------------
  4. typedef unsigned char  U8;  
  5. typedef signed   char  S8;
  6. typedef unsigned int   U16;
  7. typedef signed   int   S16;
  8. typedef unsigned long  U32;
  9. typedef signed   long  S32;
  10. //--------------------------------------------------
  11. //                宏定义
  12. //--------------------------------------------------
  13. #undef  BIT
  14. #define BIT(x)    (1<<(x))

  15. //位置1
  16. #define IOSET(port,x)  (port)|=(x)
  17. //位清0
  18. #define IOCLR(port,x)  (port)&=~(x)
  19. //位取反
  20. #define IOXOR(port,x)  (port)^=(x)
  21. //系统时钟定义,用于计算波特率
  22. #define FOSC 11059200

  23. U8 txok=0;
  24. void uart1_sendbyte(U8 ud)
  25. {
  26.         IOCLR(txok,BIT(0));
  27.         SBUF=ud;
  28.         while((TI==0)&&((txok & BIT(0))==0));//等待它由0变为1
  29.         TI=0;                                                //清发送标志
  30. }
  31. //--------------------------------------------------
  32. //串口4发送单个字符
  33. //--------------------------------------------------
  34. void uart4_sendbyte(U8 ud)//串口发送单个字符
  35. {
  36.         IOCLR(txok,BIT(3));       
  37.         S4BUF=ud;
  38.         while( ((S4CON & BIT(1))==0) && ((txok & BIT(3))==0));//等待它由0变为1
  39.         IOCLR(S4CON,BIT(1));                                                //清发送标志
  40. }
  41. //--------------------------------------------------
  42. //串口1中断
  43. //--------------------------------------------------
  44. void uart1_int(void) interrupt 4        //串口接收中断
  45. {
  46.         U8 d;
  47.         if(TI)
  48.         {
  49.                 TI=0;
  50.                 IOSET(txok,BIT(0));
  51.         }
  52.         if(RI)
  53.         {
  54.                 d=SBUF;
  55.                 RI=0;//清接收标志
  56.                 uart1_mint(d);//数据处理               
  57.         }
  58. }
  59. //--------------------------------------------------
  60. //串口4中断
  61. //--------------------------------------------------
  62. void uart4_int(void) interrupt 18//串口接收中断
  63. {
  64.         U8 d;

  65.         if(S4CON & BIT(1))//S4TI
  66.         {
  67.                 IOCLR(S4CON,BIT(1));       
  68.                 IOSET(txok,BIT(3));
  69.         }
  70.         if(S4CON & BIT(0))//S4RI
  71.         {
  72.                 d=S4BUF;
  73.                 IOCLR(S4CON,BIT(0));
  74.                 uart4_mint(d);//数据处理       
  75.         }
  76. }
  77. //--------------------------------------------------
  78. //串口1初始化,
  79. //baud:波特率
  80. //es:串口中断使能
  81. //--------------------------------------------------
  82. void uart1_init(U32 baud,U8 es)
  83. {
  84.         U16 v;
  85.        
  86.         IOSET(AUXR,BIT(2));//T2x12
  87.         v=65536-((FOSC*10/4/baud+5)/10);//v=65536-(FOSC/4/baud);
  88.         IOCLR(AUXR,BIT(4));//T2R=0;
  89.         T2H=v>>8;
  90.         T2L=v;
  91.         //IOSET(AUXR,BIT(6));//T1x12,让T1的时钟变为原来的12倍,波特率也提高了
  92.         IOSET(AUXR,BIT(4));//T2R=1;
  93.         IOSET(AUXR,BIT(0));//S1ST2=1;选择T2作为波特率
  94.         SCON=0X50;                //0101 0000 方式1,允许接收
  95.         ES        =es;                //允许串行中断
  96.         //EA         =1;                //全局中断允许
  97. }
  98. //--------------------------------------------------
  99. //串口4,T2/T4作为波特率
  100. //--------------------------------------------------
  101. void uart4_init(U32 baud,U8 es)
  102. {
  103.         U16 v;

  104.         IOSET(T4T3M,BIT(5));//T4x12
  105.         v=65536-((FOSC*10/4/baud+5)/10);//v=65536-(FOSC/4/baud);
  106.         IOCLR(T4T3M,BIT(7));//T4R=0;
  107.         T4H=v>>8;
  108.         T4L=v;
  109.         IOSET(T4T3M,BIT(7));//T4R=1;
  110.         S4CON=0X50;                //T4为波特率,允许接收
  111.         if(es)
  112.                 IOSET(IE2,BIT(4));//ES4
  113.         else
  114.                 IOCLR(IE2,BIT(4));//ES4       
  115.         //EA         =1;                //全局中断允许
  116. }
复制代码
 楼主| 发表于 2019-4-16 21:19:12 | 显示全部楼层
lcw_swust 发表于 2019-4-16 20:51
哦,原来如此。
分享一下我的代码:

你们高手写的程序,总是让我看的晕头转向。本人的水平太低,总是喜欢用简单粗暴的方式去操作。
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-8-19 02:26

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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