STM32f103使用模拟并口与CH376S通信。使用CMD11_CHECK_EXIST测试返回0x57

硬件:买的CH376S模块。

1:5V供电采用并口方式。

2:测试晶振起振了。

3:上电RST和RST#都是低电平。与手册不符合。25脚  RST  输出  电源上电复位和外部复位输出,高电平有效,26脚  RST#  输出  电源上电复位和外部复位输出,低电平有效。

软件:


#if ( CH375_PORT_MODE==2 || CH375_PORT_MODE==3 )


//DATAPORT: B0~B7

//WR: B8

//CS: B9

//A0: B10

//RD: B11

//INT: C13


#define CH375_WR                      PBout(8)

#define CH375_CS                      PBout(9)

#define CH375_A0                      PBout(10)

#define CH375_RD                      PBout(11)

#define CH375_DATA_DIR_IN()           GPIOB->CRL = 0x44444444

#define CH375_DATA_DIR_OUT()          GPIOB->CRL = 0x33333333

#define CH375_DATA_DAT_OUT( mCmd )    GPIOB->ODR = (GPIOB->ODR & 0xFF00) | (uint8_t)mCmd

#define CH375_DATA_DAT_IN( )          (uint8_t)GPIOB->IDR


//CH375写命令函数

void xWriteCH375Cmd( UINT8 mCmd )

{

CH375_DATA_DAT_OUT( mCmd );  /* 向CH376的并口输出数据 */

CH375_DATA_DIR_OUT( );  /* 设置并口方向为输出 */

CH375_A0 = 1;

CH375_CS = 0;

CH375_WR = 0;  /* 输出有效写控制信号, 写CH376芯片的命令端口 */

CH375_WR = 0;  /* 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS */

CH375_WR = 1;  /* 输出无效的控制信号, 完成操作CH376芯片 */

CH375_CS = 1;

CH375_A0 = 0;

CH375_DATA_DIR_IN( );  /* 禁止数据输出 */

delay_us(2);

}

//CH375写数据函数

void xWriteCH375Data( UINT8 mData )

{

CH375_DATA_DAT_OUT( mData );  /* 向CH376的并口输出数据 */

CH375_DATA_DIR_OUT( );  /* 设置并口方向为输出 */

CH375_A0 = 0;

CH375_CS = 0;

CH375_WR = 0;  /* 输出有效写控制信号, 写CH376芯片的数据端口 */

CH375_WR = 0;  /* 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于40nS */

CH375_WR = 1;  /* 输出无效的控制信号, 完成操作CH376芯片 */

CH375_CS = 1;

CH375_DATA_DIR_IN( );  /* 禁止数据输出 */

delay_us( 1 );  /* 确保读写周期大于0.6uS */

}

//CH375读数据函数

UINT8 xReadCH375Data( void )

{

UINT8mData;

delay_us( 1 );  /* 确保读写周期大于0.6uS */

CH375_DATA_DIR_IN( );  /* 设置并口方向为输入 */

CH375_A0 = 0;

CH375_CS = 0;

CH375_RD = 0;  /* 输出有效读控制信号, 读CH376芯片的数据端口 */

CH375_RD = 0;  /* 该操作无意义,仅作延时 */

mData = CH375_DATA_DAT_IN( );  /* 从CH376的并口输入数据 */

CH375_RD = 1;

CH375_CS = 1;  /* 输出无效的控制信号, 完成操作CH376芯片 */

return( mData );

}


void CH375_Init( void )

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitStructure.GPIO_Pin = 0x0FFF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);


#ifdef CH375_INT_WIRE

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//INT

    GPIO_Init(GPIOC, &GPIO_InitStructure);

#endif

CH375_CS = 1;

CH375_WR = 1;

CH375_RD = 1;

CH375_A0 = 0;

CH375_DATA_DIR_IN( );                                   /* 设置并口输入 */

}


int main(void)

{

unsigned char i,s;

unsigned short len;

delay_init();

USART_Config();

CH375_Init();

printf("start...\n");

// 发送测试命令 

xWriteCH375Cmd(CMD11_CHECK_EXIST); 

// 发送测试数据 

xWriteCH375Data(0x11); 

// 读数据 

s = xReadCH375Data(); 

printf("s:%x\n",s);

spacer.gif


您好,RST引脚是高电平有效,上电是低电平。

取反指令无法得到正确的值,您可以检查一下接口配置是否正确,并口时序是否正常。


嗯!查看了是STM32引脚配置问题。PB3。PB4默认是调试脚,需要关掉。现在是接了键盘扫描键盘。设置配置有误。



chip-id:0x43

mode:1

wait connect...

check rate

low rate

设备描述符是:12 01 10 01 00 00 00 08 4f 1c 02 00 10 01 01 02 00 01 

09 02 3b 00 02 01 00 a0 31 09 04 00 00 01 03 01 01 00 09 21 10 01 00 01 22 36 00 07 05 81 03 08 00 0a 09 04 01 00 01 03 00 00 00 09 21 10 01 00 01 22 32 00 07 05 82 03 03 00 0a 

set config

set idle

get report

get report descr failed

set idle

set idle failed

get report

get report descr failed

set report

00 00 00 00 00 00 00 00 



设置配置的大小端数据没有改到。修改了,但是设置idle有问题。



chip-id:0x43

mode:1

wait connect...

check rate

low rate

设备描述符是:12 01 10 01 00 00 00 08 4f 1c 02 00 10 01 01 02 00 01 

09 02 3b 00 02 01 00 a0 31 09 04 00 00 01 03 01 01 00 09 21 10 01 00 01 22 36 00 07 05 81 03 08 00 0a 09 04 01 00 01 03 00 00 00 09 21 10 01 00 01 22 32 00 07 05 82 03 03 00 0a 

set config

set idle

get report

05 01 09 06 a1 01 05 08 19 01 29 03 15 00 25 01 75 01 95 03 91 02 95 05 91 01 05 07 19 e0 29 e7 95 08 81 02 75 08 95 01 81 01 19 00 29 91 26 ff 00 95 06 81 00 c0 

set idle

set idle failed

get report

05 0c 09 01 a1 01 85 01 19 00 2a 3c 02 15 00 26 3c 02 95 01 75 10 81 00 c0 05 01 09 80 a1 01 85 02 19 81 29 83 25 01 75 01 95 03 81 02 95 05 81 01 c0 

set report

00 00 00 00 00 00 00 00 



您好,建议先检查set idle这一步发的请求是否正确,请求无误的话,可以检查一下set idle failed发生的原因,查看代码报错的位置。


你好!请问下扫码枪需不需要设置空闲模式了?我没有设置扫码枪空闲模式,现在的问题是读取扫码枪数据不稳定,扫几次能获取数据,然后就不一直获取不到了。


获取扫码枪是全是模式,不能获取扫码枪数据后,我查看了INT引脚波形就不正常了。


/* 主函数 */

void main() 

{

unsigned char i,s;

unsigned short len;


max_package = MAXSETUPPACK;

mInitSTDIO( );


s = read_id();

printf("chip-id:0x%02x\n",(unsigned short)s);


set_usb_mode( 5 );  /* 设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 */

printf("wait connect...\n");

while(1)

{

while ( wait_interrupt()!=USB_INT_CONNECT );  /* 等待设备端连接上来 */

delayms(200);                    /* 等待连接稳定 */

/***** 复位检测USB设备速度 *****/

printf("check rate\n");

s = get_freq();

reset_device();

        if( s&0x10 )

{

printf("low rate\n");

set_freq();/* 切换使375B进入低速模式 */

}

else

printf("full rate\n");

delayms(100);         //复位之后,相当于重连,必须有延时保证设备稳定

/***** 获取设备描述符 *****/

get_descr(0x01);//获取设备描述符

max_package = data_buf[7];  //端点0最大包大小


//Request.Req.bmRequestType=0x80;

//Request.Req.bRequest=0x06;

//Request.Req.wValue=0x0001;      /* 因为51单片机是大端存储,否则写成0x0100,下面类似 */

//Request.Req.wIndex=0x0000;

//Request.Req.wLength=0x0800;

//if( SETUP_Transfer(data_buf, &len) == USB_INT_SUCCESS )

//{

//max_package = data_buf[7];  //端点0最大包大小

//Request.Req.wLength=0x1200;

//if( SETUP_Transfer(data_buf, &len) )

//{

//for(i=0; i!=len; i++)

//printf("%02x ",(unsigned int)data_buf[i]);

//printf("\n");

//}

//}

//else 

//printf("get device descr failed\n");

/***** 复位 *****/

reset_device();

        if( s&0x10 )set_freq();/* 切换使375B进入低速模式 */

delayms(100);                   //复位之后,相当于重连,必须有延时保证设备稳定

/***** 设置地址  *****/

set_addr(5);//设置地址

/***** 获取配置描述符 *****/

//get_descr(0x02);//获取配置描述符

Request.Req.bmRequestType=0x80;

Request.Req.bRequest=0x06;

Request.Req.wValue=0x0002;

Request.Req.wIndex=0x0000;

Request.Req.wLength=0x0400;

if(SETUP_Transfer(data_buf, &len)==USB_INT_SUCCESS)

{

Request.Req_buf[6] = data_buf[2];

Request.Req_buf[7] = data_buf[3];

SETUP_Transfer(data_buf, &len);

for(i=0;i!=len;i++)

printf("%02x ",(unsigned int)data_buf[i]);

printf("\n");

}

else printf("get config descr failed\n");

/***** 分析配置描述符 *****/

parse_config_descr(data_buf);   //保存描述符中一些值

/***** 设置配置 *****/

    printf("set config\n");

set_config(config_value);     //设置配置

/***** HID类命令 *****/

for(s=0;s

{

printf("set idle\n");

Request.Req.bmRequestType=0x21;

Request.Req.bRequest=0x0A;

Request.Req.wValue=0x0000;

Request.Req.wIndex=0x0000;

Request.Req.wLength=0x0000;

Request.Req_buf[4] = s;

if(SETUP_Transfer(NULL, NULL)!=USB_INT_SUCCESS)

printf("set idle failed\n");

printf("get report\n");

Request.Req.bmRequestType=0x81;

Request.Req.bRequest=0x06;

Request.Req.wValue=0x0022;

Request.Req.wIndex=0x0000;

Request.Req_buf[4] = s;

if(s==0) Request.Req.wLength=0x0000|((unsigned short)(report_descr0_len+0x40)<<8);

else Request.Req.wLength=0x0000|((unsigned short)(report_descr1_len+0x40)<<8);

if(SETUP_Transfer(data_buf, &len)==USB_INT_SUCCESS)

{

for(i=0;i!=len;i++)

printf("%02x ",(unsigned short)data_buf[i]);

printf("\n");

}

else printf("get report descr failed\n");

}

printf("set report\n");//对于键盘这一步,是点亮指示灯

Request.Req.bmRequestType=0x21;

Request.Req.bRequest=0x09;

Request.Req.wValue=0x0002;

Request.Req.wIndex=0x0000;

Request.Req.wLength=0x0100;

data_buf[0]=1;

if(SETUP_Transfer(data_buf, &len)!=USB_INT_SUCCESS)

printf("set report failed\n");

/* 设置对响应NAK的重试次数 */

set_retry(3);  //超时重试3次,但收到NAK不重试

/* 获取数据 */

endp6_mode=0x80;  //复位同步标志

toggle_recv();

while(1)

{

s = issue_token( endp_int,DEF_USB_PID_IN);

if(s==USB_INT_SUCCESS)

{

toggle_recv();

len = rd_usb_data( data_buf );

for(i=0;i!=len;i++)

printf("%02x ",(unsigned short)data_buf[i]);

printf("\n");

}

}

}

}



您好,您的问题可能出在大小端没有修改,您可以在SETUP_Transfer函数前面加个打印,按顺序打印Request.Req_buf[]数组的值,看打印的值是否正确。打印如下所示

for(i=0;i<8;i++)

printf("%02x ",Request.Req_buf[i]);

正确的打印值如下所示:

获取配置描述符应该是:80 06 00 02 00 00 04 00 

set idle应该是:21 0a 00 00 s  00 00 00

get report应该是:81 06 00 22 s  00 00 xx

 set report应该是:21 09 00 02 00 00 01 00


你好。我的大小端是改正确了的。我贴的那个是忘了把大小端改过来了。

chip-id:0x43

wait connect...

check rate

full rate

设备描述符是:12 01 10 01 00 00 00 08 45 01 12 00 00 01 01 02 00 01 

配置描述符是:09 02 22 00 01 01 00 a0 32 09 04 00 00 01 03 01 01 00 09 21 10 01 00 01 22 49 00 07 05 81 03 08 00 05 

start meiju 

80 06 00 02 00 00 04 00 start meiju 

80 06 00 02 00 00 22 00 09 02 22 00 01 01 00 a0 32 09 04 00 00 01 03 01 01 00 09 21 10 01 00 01 22 49 00 07 05 81 03 08 00 05 

set config

set idle

start meiju 

21 0a 00 00 00 00 00 00 set idle failed

get report

start meiju 

81 06 00 22 00 00 00 89 get report descr failed

set report

start meiju 

21 09 00 02 00 00 01 00 












我现在的代码是这样的。没有对扫码枪设置set idle 和 那个键盘点灯的。就是工作不稳定,扫一会儿就死了。就获取不到扫码枪数据了,请问是不是需要设置什么东西了?感觉那个设置不对。

int main(void)

{

unsigned char i,j,s;

unsigned short len;

deviceCode[0] = SEND_DEVICE_CODE_VALUE;

delay_init();

USART_Config();

CH375_Init();

s = read_id();

printf("chip-id:0x%02x\n",(unsigned short)s);


set_usb_mode( 5 );  /* 设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 */

printf("wait connect...\n");

while(1){

while (wait_interrupt()!=USB_INT_CONNECT);

delay_ms(500);                    /* 等待连接稳定 */

/***** 复位检测USB设备速度 *****/

reset_device();

printf("check rate\n");

s = get_freq();

    if( s&0x10 )

{

printf("low rate\n");

set_freq();/* 切换使375B进入低速模式 */

}

else

printf("full rate\n");

delay_ms(100);         //复位之后,相当于重连,必须有延时保证设备稳定

/***** 获取设备描述符 *****/

get_descr(0x01);//获取设备描述符

max_package = data_buf[7];  //端点0最大包大小

//Request.Req.bmRequestType=0x80;

//Request.Req.bRequest=0x06;

//Request.Req.wValue=0x0100;      /* 因为51单片机是大端存储,否则写成0x0100,下面类似 */

//Request.Req.wIndex=0x0000;

//Request.Req.wLength=0x0008;

//if( SETUP_Transfer(data_buf, &len) == USB_INT_SUCCESS )

//{

//max_package = data_buf[7];  //端点0最大包大小

//Request.Req.wLength=0x1200;

//if( SETUP_Transfer(data_buf, &len) )

//{

//for(i=0; i!=len; i++)

//printf("%02x ",(unsigned int)data_buf[i]);

//printf("\n");

//}

//}

//else 

//printf("get device descr failed\n");

/***** 复位 *****/

reset_device();

//    if( s&0x10 )set_freq();/* 切换使375B进入低速模式 */

delay_ms(100);                   //复位之后,相当于重连,必须有延时保证设备稳定

/***** 设置地址  *****/

set_addr(5);//设置地址

/***** 获取配置描述符 *****/

get_descr(0x02);//获取配置描述符

Request.Req.bmRequestType=0x80;

Request.Req.bRequest=0x06;

    Request.Req.wValue = 0x0200;

Request.Req.wIndex=0x0000;

Request.Req.wLength=0x0004;

if(SETUP_Transfer(data_buf, &len)==USB_INT_SUCCESS)

{

Request.Req_buf[6] = data_buf[2];

Request.Req_buf[7] = data_buf[3];

SETUP_Transfer(data_buf, &len);

for(i=0;i!=len;i++)

printf("%02x ",(unsigned int)data_buf[i]);

printf("\n");

}

else printf("get config descr failed\n");

/***** 分析配置描述符 *****/

parse_config_descr(data_buf);   //保存描述符中一些值

/***** 设置配置 *****/

    printf("set config\n");

set_config(config_value);     //设置配置

/***** HID类命令 *****/

//for(s=0;s

//{

//printf("set idle\n");

//Request.Req.bmRequestType=0x21;

//Request.Req.bRequest=0x0A;

//Request.Req.wValue=0x0000;

//Request.Req.wIndex=0x0000;

//Request.Req.wLength=0x0000;

//Request.Req_buf[4] = s;

//if(SETUP_Transfer(NULL, NULL)!=USB_INT_SUCCESS)

//printf("set idle failed\n");

//

//printf("get report\n");

//Request.Req.bmRequestType=0x81;

//Request.Req.bRequest=0x06;

//Request.Req.wValue=0x2200;

//Request.Req.wIndex=0x0000;

//Request.Req_buf[4] = s;

//if(s==0) Request.Req.wLength=0x0000|((unsigned short)(report_descr0_len+0x40)<<8);

//else Request.Req.wLength=0x0000|((unsigned short)(report_descr1_len+0x40)<<8);

//

//if(SETUP_Transfer(data_buf, &len)==USB_INT_SUCCESS)

//{

//for(i=0;i!=len;i++)

//printf("%02x ",(unsigned short)data_buf[i]);

//printf("\n");

//}

//else printf("get report descr failed\n");

//}

//printf("set report\n");//对于键盘这一步,是点亮指示灯

//Request.Req.bmRequestType=0x21;

//Request.Req.bRequest=0x09;

//Request.Req.wValue=0x0200;

//Request.Req.wIndex=0x0000;

//Request.Req.wLength=0x0001;

//data_buf[0]=1;

//if(SETUP_Transfer(data_buf, &len)!=USB_INT_SUCCESS)

//printf("set report failed\n");

/* 设置对响应NAK的重试次数 */

set_retry(3);  //超时重试3次,但收到NAK不重试

/* 获取数据 */

endp6_mode=0x80;  //复位同步标志

toggle_recv();

i = 1;

while(1)

{

s = issue_token( endp_int,DEF_USB_PID_IN);

if(s==USB_INT_SUCCESS)

{

toggle_recv();

len = rd_usb_data(data_buf);

for(j=0;j!=len;j++)

printf("%02x ",(unsigned short)data_buf[j]);

printf("\n");

}


}

}

}



你好!现在新买了个扫码枪后,发现使用无线接收,不能设置空闲模式。使用有线的就完全没有问题。也没有出现扫码死情况了。原来那个扫码枪是别人设置的,只能使用无线接收。就出现空闲模式设置不正确的问题。谢谢你的回复。


使用不稳定有可能是信号不稳定,可能跟供电,线材等有关系。

在USB中断传输中有一个查询时间,需要按照这个查询时间来向设备发送IN包,进而接收数据,否则可能丢失数据,具体的查询时间需要按照端点描述符设置。


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