提问 关于串口控制CH375

参考CH375hst例程编写USB打印机程序,获取描述符处一直无法通过,长度数据能获得(len=0x12),后续数据无法读取正确,一直是0x00;

1、命令RD_USB_DATA后单片机必须将后续数据从CH375逐个读出,请问是否需要在for循环中增加数据读取命令RD_USB_DATA;

2、在论坛上找到串行通讯时TB8需要设置,在CH375DS手册上没有找到相关说明,请问那份文件有关于CH375串口操作的详细说明。

例程如下

unsigned char rd_usb_data( unsigned char *buf ) {  //从CH37X读出数据块
 unsigned char i, len;
 CH375_WR_CMD_PORT( CMD_RD_USB_DATA );  //从CH375的端点缓冲区读取接收到的数据
 delay_ms(2);
 len=CH375_RD_DAT_PORT();  //后续数据长度 
 for ( i=0; i!=len; i++ ) *buf++=CH375_RD_DAT_PORT();
 return( len );
}

1、首先确保你的串口通讯正常,可参考下面的子程序:
void CH375_PORT_INIT( ) {
    SCON = 0xD0; // 设置串口为9位数据
    PCON = 0x80;
    TMOD = 0x20;
    TH1 = 0xf3;  // 24MHz晶振, 9600bps
    TR1 = 1;
    TI = 1;
//  RI = 0;
//设置波特率和其它串口参数
}

void xWriteCH375Cmd( UINT8 mCmd ) {
    TI = 0;
    TB8 = 1;
    SBUF = mCmd;
    while ( TI == 0 );
}

void xWriteCH375Data( UINT8 mData ) {
    TI = 0;
    TB8 = 0;
    SBUF = mData;
    while ( TI == 0 );
}

UINT8 xReadCH375Data( void ) {
    while ( RI == 0 );
    RI = 0;
    return( SBUF );
}

2、确保USB设备连接正常,设备描述符的获取进入函数监控setup命令是否发送成功。



1、status=get_descr(1);  // 获取设备描述符

能获得状态数据 0x14;

2、len=rd_usb_data( buffer );  // 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中

只有长度数据返回。

CPU使用的是STM32F103,参考上述程序修改基本操作程序如下:

//基本操作
void CH375_WR_CMD_PORT( unsigned char cmd ) {  //向CH375的命令端口写入命令,周期不小于4us,如果单片机较快则延时
 USART1->DR = (cmd|0x100); //发送CH375控制指令  
 while((USART1->SR&0x40) == 0); //等待发送结束
 delay_us(1);  
}
void CH375_WR_DAT_PORT( unsigned char dat ) {  //向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时
 USART1->DR = (dat&0x0ff); //发送CH375控制指令   
 while((USART1->SR&0x40) == 0); //等待发送结束
 delay_us(1);
}

u8 CH375_RD_DAT_PORT(void) {  //从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时

 delay_us(1);
  return(USART1->DR); 
}

串口初始化程序如下 

void uart_init(u32 pclk2,u32 bound)  //波特率9600
{    
 。。。。。   
 RCC->APB2RSTR|=1<<14;   //复位串口1
 RCC->APB2RSTR&=~(1<<14);//停止复位       
 //波特率设置
  USART1->BRR=mantissa; // 波特率设置  
  USART1->CR1|=0X300C;    //1位停止,9个数据,无校验
#if EN_USART1_RX    //如果使能了接收
 //使能接收中断
 USART1->CR1|=1<<8;    //PE中断使能
 USART1->CR1|=1<<5;    //接收缓冲区非空中断使能      
 MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级
#endif
}

 

问题出在哪里?焦虑中.......

 


在获取设备描述符之前的测试命令,设置模式和检测U盘连接是否正确通过?返回值是多少?另外注意一下buffer的定义。


主机模式,设备为打印机。

长度数据返回0x12。


int usb_Host(void)
 {
 u8 data_to_send[200];  /* 缓冲区 */
// u8 str_to_print[]="OK, support text print\n";
 u8 s;
 delay_ms(200);//mDelaymS( 200 );
 set_usb_mode( 6 );  /* 设置USB主机模式 */
 while ( wait_interrupt()!=USB_INT_CONNECT );  /* 等待USB打印机连接上来 */

/* 如果设备端是CH341转打印口或者是CH37X,那么以下步骤是可选的,如果是其它USB芯片,那么可能需要执行以下步骤 */
#define USB_RESET_FIRST 1  /* USB规范中未要求在USB设备插入后必须复位该设备,但是计算机的WINDOWS总是这样做,所以有些USB设备也要求在插入后必须先复位才能工作 */
#ifdef USB_RESET_FIRST
 set_usb_mode( 7 );  /* 复位USB设备,CH375向USB信号线的D+和D-输出低电平 */
/* 如果单片机对CH375的INT#引脚采用中断方式而不是查询方式,那么应该在复制USB设备期间禁止CH375中断,在USB设备复位完成后清除CH375中断标志再允许中断 */
 delay_ms(10);//mDelaymS( 10 );  /* 复位时间不少于1mS,建议为10mS */
 set_usb_mode( 6 );  /* 结束复位 */
 delay_ms(100);//mDelaymS( 100 );
 while ( wait_interrupt()!=USB_INT_CONNECT );  /* 等待复位之后的设备端再次连接上来 */
#endif

 delay_ms(200);//mDelaymS( 200 );  /* 有些USB设备要等待数百毫秒才能正常工作 */
 if ( init_print()!=USB_INT_SUCCESS ) while(1);  /* 错误 */

......

}

设置主机模式,设备连接返回成功。

进入init_print()初始化程序获取设备描述符始终不能成功,能购获取到status==0x14;len==0x12; 但始终无法获得其他描述符数据。if判断无法通过。

程序如下:

if ( status==USB_INT_SUCCESS ) {
  len=rd_usb_data( buffer );  // 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度
  if ( len<18 || p_dev_descr->bDescriptorType!=1 ) return( UNKNOWN_USB_DEVICE );  //意外错误:描述符长度错误或者类型错误

 


 


if ( len<18 || p_dev_descr->bDescriptorType!=1 ) return( UNKNOWN_USB_DEVICE );  该语句无法通过

 


buffer里面的值是多少?

你可以使用附件中CH375外部固件的方式获取试一下。icon_rar.gifch375print外部固件.rar



ZBin 你好,参考外部固件例程将程序修改,主要为init_print()函数部分

执行到if(get_descr_ex()==1),单步跟踪执行进入get_descr_ex()函数
unsigned char get_descr_ex()
{ unsigned char descr_len,status;
 unsigned char *p=buffer;
 
 toggle_send(0);
 wr_usb_data(8,Request.Req_buf);
    if(issue_token(( 0 << 4 ) | DEF_USB_PID_SETUP)==USB_INT_SUCCESS)
 {
  toggle_recv(1);
 }
 else return(0);
 status=issue_token(( 0 << 4 ) | DEF_USB_PID_IN);
 if(status==USB_INT_SUCCESS)/* DATA阶段操作成功 */
 { if(flag_config_2)descr_len=buffer[2]-rd_usb_data(buffer);
  else descr_len=buffer[0]-rd_usb_data(buffer); 
  ...
 }
....
}

第一个if条件内的issue_token()能返回正确值,能够执行toggle_recv(1);语句。
在status=issue_token(( 0 << 4 ) | DEF_USB_PID_IN);处返回值status=0x2e;表明DATA阶段操作不成功。
获取描述符错误。

其中:

#define DEF_USB_PID_SETUP 0x0D
#define DEF_USB_PID_IN  0x09


从你的现象看SETUP命令已经下发成功,IN包没有取到数据。有可能你的SETUP命令有问题(注意单片机大小端格式,默认是大端格式),还有可能你的USB设备没有响应,你可以换一个其他的USB全速设备试一下。


修改后,描述符能够正确获取到,外部固件模式需要注意大小端格式。基本操作程序修改如下。

 

//基本操作
void CH375_WR_CMD_PORT( unsigned char cmd ) {  //向CH375的命令端口写入命令,周期不小于4us,如果单片机较快则延时
 USART1->DR = ((u16)cmd|0x100); 
 while((USART1->SR&0x40) == 0); //等待发送结束
 delay_us(1);  
}
void CH375_WR_DAT_PORT( unsigned char dat ) {  //向CH375的命令端口写入命令,周期不小于1.5uS,如果单片机较快则延时
 USART1->DR = ((u16)dat&0x0ff);
 while((USART1->SR&0x40) == 0); //等待发送结束
 delay_us(1);
}

u8 CH375_RD_DAT_PORT(void) {  //从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时

 delay_us(1);
 while((USART1->SR&(1<<5))!=USART_SR_RXNE);
 USART1->SR &=~(1<<5);
  return(USART1->DR); 
}


你好,获取配置符时遇到返回0x17,应该如何处理?

USB_INT_BUF_OVER   0x17   /* USB控制传输的数据太多, 缓冲区溢出 */


是否CH375B的内部缓存区不够!


因为CH375的控制传输缓冲区只有64个字节,所以当描述符的长度超过64字节时,CH375将返回操作状态USB_INT_BUF_OVER。使用外置固件模式就没这个问题了。


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