搞定了stc89c52与ch375b主机方式的串行通信

2015-10-20

无线手柄也能稳定接收到数据了,串口方式每次返回27个字节,分析了一下只有前7个字节有用,其他20个字节都是垃圾数据。

用bushund5.0抓到的数据,确实是7字节。

以前用并行方式接收的数据只有7个,为什么用串口方式会接收到这么多垃圾数据。

 

2015-10-20

现在接无线鼠标已经正常,效果很好,但是接无线手柄的时候,issue_token()会返回一个错误值0x2B,但我查遍你公司有关ch375的手册上可以找到的资料都没有定义这个返回值是什么含义。有高手知道吗?

 

/* 主机接收usb数据操作 */
unsigned char issue_token( unsigned char endp_and_pid )   /* 执行USB事务 */
{
 
 /* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */
 CH375_WR_CMD( CMD_ISSUE_TOKEN );
 CH375_WR_DAT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */

 return(wait_interrupt()); /* 等待CH375操作完成 */
 
}

 

/* 主机端等待操作完成, 返回操作状态 */
unsigned char wait_interrupt(void)
{  
 CH375_INT_WIRE = 1;
 while( CH375_INT_WIRE );
 CH375_WR_CMD( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
 return( CH375_RD_DAT() ); 
}

 

 

 

 

2015-10-17

又有了新的问题,串口host方式连鼠标,用有线的鼠标连接,能读到鼠标数据,连接状况非常好,但换成无线鼠标连接状况却不理想,十次大概有两、三次能连上,不知道什么原因,希望路过的各位神仙能点拨下小弟。

 

原帖: 

我用stc89C52和ch375b串行通信,一直卡在取反测试过不去,返回的值不对,我用T2定时器做串行通信的波特率,感觉是串口初始化不对,也不知道错在哪里,望大神指点一下,如果有测试过的例子,还望能提供一个,不胜感激。

硬件连接如下
 C51                   CH375B    
 P3^0(RXD)       TXD    
 P3^1(TXD)        RXD    
 P1^5                 INT#   

 

执行到下面代码时过不去

CH375_WR_CMD( CMD_CHECK_EXIST );  /* 测试单片机与CH375之间的通讯接口 */
CH375_WR_DAT( 0x65 );
retChar = CH375_RD_DAT( );
if ( retChar != 0x9A )
{
     #ifdef ENABLE_DEBUG
     SendString("CH375 test fail!\nretChar = \n");   //通过IO模拟串口向PC发送监视信息
     SendHex(retChar);
     #endif
     while(1)      //阻塞
     {
          flash_led(); //错误
     }  
}

 

我的串口初始化如下
void UartInit(void)    /* 串行口初始化 */
{
   SCON = 0xD0;    //串口方式1,1个起始位,1个停止位,9位数据
   T2CON = 0x30;   //计数器2,T2用做发送接收时钟,作为串口波特率发生器
   RCAP2H = 0xFF;     //9600波特率,11.0592Mhz晶振
   RCAP2L = 0 - 11059200/32/9600;   /* (0xDC)      11.0592MHz晶振 */
   TH2 = RCAP2H;    
   TL2 = RCAP2L;
   TR2 = 1;             //启动T2
   RI = 0;
}

 

访问ch375b的三个基本函数如下
/* 向CH375的串口写入命令 */
void CH375_WR_CMD( unsigned char mCmd )  /* 向CH375写命令 */
{
     TI = 0;
     TB8 = 1;
     SBUF = mCmd;
     while ( TI == 0 );
}

/* 向CH375的串口写入数据 */
void CH375_WR_DAT( unsigned char mData )  /* 向CH375写数据 */
{
     TI = 0;
     TB8 = 0;
     SBUF = mData;
     while ( TI == 0 );
}

/* 通过串口从CH375读出数据 */
unsigned char CH375_RD_DAT( void ) 
{
     while ( RI == 0 );
     RI = 0;
     return( SBUF );
}

 

首先检查一下硬件有没有问题供电是否正常、晶振是否起振,复位输出25脚(低电平)和26脚(高电平),然后注意一下CH375在复位期间检测到TXD引脚为高才进入串口模式。看了你的初始化程序就初始化和我们是用的定时器1,其他都一样:

void CH375_PORT_INIT( ) {
    SCON = 0xD0; // 设置串口为9位数据
    PCON = 0x80;
    TMOD = 0x20;
    TH1 = 0xf3;  // 24MHz晶振, 9600bps
    TR1 = 1;
    TI = 1;
//  RI = 0;
//设置波特率和其它串口参数
}



谢谢指点,今天晚上看了看文档,找到了问题所在,串行口要在HOST模式下才可用,而我把set_usb_mode()调用放在了取反测试的后面了,所以获取不了正确返回值,把设置HOST模式的函数调用set_usb_mode()放到前面去就可以了,其实我的串口初始化是没问题的。


又有了新的问题,串口host方式连鼠标,用有线的鼠标连接,能读到鼠标数据,连接状况非常好,但换成无线鼠标连接状况却不理想,十次有大概能有两、三次能连上,不知道什么原因,希望路过的各位神仙能点拨下小弟。


无线鼠标和有线原理上是一样的,因为都是由你主机控制的,注意一下IN包发送的时间,最好的方法是将无线鼠标接到电脑上抓一下电脑的采集过程。


无线鼠标和有线原理上是一样的,因为都是由你主机控制的,注意一下IN包发送的时间,最好的方法是将无线鼠标接到电脑上抓一下电脑的采集过程。

 

今天晚上研究了下,现在用串行方式也可以从无线手柄稳定接收到数据了,但是每次都返回27个字节,而且出现大量的端点错误,要不断地清除。分析了一下只有前7个字节有用,其他20个字节都是垃圾数据。

同时用bushund5.0在电脑上抓到的数据,证实了无线手柄确实是只发出了7个字节的数据。

以前用并行方式接收的时候,接收到的数据只有7个字节,为什么用串口方式 ?rd_usb_data() 会接收到这么多垃圾数据,而且出现大量的端点错误。你说的“注意一下IN包发送的时间”是什么意思,具体要如何分析?


理论上串口和并口是一样的,首先你看一下中断状态是否正确(USB_INT_SUCCESS),然后rd_usb_data读出来的数据长度是多少?是不是长度读错了


理论上串口和并口是一样的,首先你看一下中断状态是否正确(USB_INT_SUCCESS),然后rd_usb_data读出来的数据长度是多少?是不是长度读错了

奇怪的是我用有线鼠标和无线鼠标测试结果是正确的,每次返回7个字节,而用无线手柄测试的时候返回的是27个字节,后面20个字节是无效数据。


unsigned char rd_usb_data( unsigned char *buf )   /* 从CH37X读出数据块 */
{
 unsigned char length, lencnt;
 
 CH375_WR_CMD(CMD_RD_USB_DATA);    /* 从CH375的端点缓冲区读取接收到的数据,并释放缓冲区 */
 
length=CH375_RD_DAT();      /* 后续数据长度 */
 
 lencnt=length;
 while( lencnt-- )
 {
  *buf = CH375_RD_DAT();
  buf++;
 }
 return length;
}



我是在切换DATA后发出issue_token指令,返回USB_INT_SUCCESS后才调用rd_usb_data()函数的。相关的几个函数如下

unsigned char wait_interrupt(void)
{  
 CH375_INT_WIRE = 1;
 while( CH375_INT_WIRE );
 CH375_WR_CMD( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
 return( CH375_RD_DAT() ); 
}

 

unsigned char issue_token( unsigned char endp_and_pid )   /* 执行USB事务 */

 /* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */
 CH375_WR_CMD( CMD_ISSUE_TOKEN );
 CH375_WR_DAT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */

 return(wait_interrupt()); /* 等待CH375操作完成 */ 
}

 

unsigned char rd_usb_data( unsigned char *buf )   /* 从CH37X读出数据块 */
{
 unsigned char length, lencnt;
 
 CH375_WR_CMD(CMD_RD_USB_DATA);    /* 从CH375的端点缓冲区读取接收到的数据,并释放缓冲区 */
  length=CH375_RD_DAT();      /* 后续数据长度 */
 
 lencnt=length;
 while( lencnt-- )
 {
  *buf = CH375_RD_DAT();
  buf++;
 }
 return length;
}

 


找到原因了,已经调试完全正常了。

程序并没用错,可能是无线接收器对stc89c52造成干扰,导致接收错误。


只有登录才能回复,可以选择微信账号登录