单片机与单片机通过CH375实现USB之间连接
时间:01-22 11:21 阅读:2046次
*温馨提示:点击图片可以放大观看高清大图
简介:本文给大家介绍了单片机与单片机通过CH375实现USB之间连接。
USB的对象,有主从之分,这样才能在开始时,两个设备之间的握手可以由主设备打破;但是对于CH375,它的主从的配置是完全不同的。通道可以由主机在设置令牌时去做。一般主机配置端口2,它在设置为主机模式时候,有专有的主机通道,即它有两种通道;如果没有配置,默认发送的端口是端点0。而主机发送信息时候,在发送次数为第"奇"次与第“偶”次发送的配置是不同的,这需要在发送的时候不停的修改。
发送信息的过程:首先设置为发送的模式,可以是5也可以是6(两种都是配置主机模式),一般为6。接着将发送的信息配置完后,写到对应的端点,这里为端点2;接着对对应的端点的通道写发送的模式(奇?偶);剩下的发送令牌,根据令牌CH375将数据左对应的操作;
头文件1//是CH375的专属相关命令
#ifndef CH375_H
#define CMD_GET_STATUS 0x22 // 获取中断状态并取消中断请求 ,通过它可以得到中断信息,即什么中断;
#define CMD_SET_USB_MODE 0x15 // 设置USB工作模式 ,设置usb是那种工作模式,是主机的那种,还是从机的那种;
#define CMD_RET_SUCCESS 0x51
#define CMD_SET_ENDP6 0x1C
#define CMD_SET_ENDP7 0x1D
#define CMD_RD_USB_DATA 0x28
#define CMD_WR_USB_DATA7 0x2B
#define CMD_ISSUE_TOKEN 0x4F
#define CMD_CLR_STALL 0x41
#define USB_INT_SUCCESS 0x14
#define USB_INT_CONNECT 0x15
#define DEMO_CXP_CMD 0x56//命令字
#define CMD_CHECK_EXIST 0x06
#define CMD_RESET_ALL 0x05
#define USB_INT_EP2_IN 0x0A
#define CMD_UNLOCK_USB 0x23
#endif
#ifndef BIANLIAN_H
sbit CH375_INT_WIRE = P3^2;//INT0
unsigned char volatile xdata CH375_CMD_PORT _at_ 0xFDff;
unsigned char volatile xdata CH375_DAT_PORT _at_ 0xFCff;
unsigned char endp6_mode,endp7_mode;//两种模式变量,用来奇偶替换;来对应奇偶次传送数据时,改变对应的配置奇偶模式
unsigned char key;//为主程序记录那个键按下
sbit KEYPIN1 = P2^2;
sbit KEYPIN2 = P2^3;
sbit KEYPIN3 = P2^4;
sbit KEYPIN4 = P2^5;
sbit KEYPIN5 = P2^6;
sbit KEYPIN6 = P2^7;
typedef struct _COMMAND_PACKET
{
unsigned char mCommandCode;
unsigned char mCommandCodeNot;
union
{
unsigned char mParameter[5];
struct
{
unsigned char mBufferID;
unsigned int mBufferAddr;
unsigned int mLength;
} buf;
} u;
} mCOMMAND_PACKET, *mpCOMMAND_PACKET;
mCOMMAND_PACKET cmd_cui;
sbit CH375RS = P3^4;
bit FLAG_INT_WAIT;
#endif
#ifndef CUI_H
//两微妙的延时;为了给指令的书写一个缓冲过度时间;谁叫咋东西破了
void Delay2us( )
{
unsigned char i;
#define DELAY_START_VALUE 1
for ( i=DELAY_START_VALUE; i!=0; i-- );
}
void Delay_ms(unsigned char ms) //延时ms
{
unsigned char i;
unsigned char us;
for(i=0; i {
us=100;
while(us--);
}
}
//查当前中断状态,由他来查看当前是什么中断,到底有没有中断
unsigned char wait_complete()
{
while(CH375_INT_WIRE);//这里采用的中断零,故接P3^2;
CH375_CMD_PORT = CMD_GET_STATUS;//中断状态控制字;
Delay2us( );
return CH375_DAT_PORT;
}
//设置usb的工作模式;奇次|偶次
void set_usb_mode(unsigned char mode)
{
CH375_CMD_PORT = CMD_SET_USB_MODE;//命令字模式设置;
Delay2us( );
CH375_DAT_PORT = mode;//什么模式?如果做主机,就是5|6模式两种均可(前提两边都有CH375),如果是从机,模式为2(根据主机要
//求)
endp6_mode = endp7_mode = 0x80;//初始没有发送数据的时候,这个奇偶标志的玩意的状态为奇状态,放在这里相当于延时
while(CH375_DAT_PORT != CMD_RET_SUCCESS);//确认模式设置成功
}
/设置DAT0的奇偶模式,由于CH375在数据发送时,分奇偶的,所以要配对奇偶对应的模式,这里是配置的是通道DAT0/
void set_endp6()
{
CH375_CMD_PORT = CMD_SET_ENDP6;//选通道DAT0
Delay2us( );
CH375_DAT_PORT = endp6_mode;//初始状态为奇0x80;偶为0xC0
endp6_mode ^=0x40;//^=是异或的意思,恰好0x80异或0x40是0xC0,而0xC0以后0x40是0x80;这样每次发送后,这个是变到对应的模式的
Delay2us( );
}
//同上,只是配置的DAT1
void set_endp7()
{
CH375_CMD_PORT = CMD_SET_ENDP7;
Delay2us( );
CH375_DAT_PORT = endp7_mode;
endp7_mode ^=0x40;//;
Delay2us( );
}
//这里是读 usb缓存的数据
unsigned char rd_usb_data(unsigned char *buf)
{
unsigned char i,len;
CH375_CMD_PORT = CMD_RD_USB_DATA;//读当前中断状态下对应的端点,ch375有3种端点,而CMD_RD_USB_DATA,是那个端点的
//收数据缓存来了数据,响应了对应的中断,就读谁。。。即读产生响应的谁谁谁
Delay2us( );
len = CH375_DAT_PORT;//一般第一个数据是长短,即后面发的数据有多大(几个字节,一次最大只能64个)
Delay2us( );
for (i=0;i!=len;i++)
*buf++ = CH375_DAT_PORT;//读啊读,读len个8位数据
return(len);
}
//上面读,下面就是写了
void wr_usb_data(unsigned char len,unsigned char*buf )
{
CH375_CMD_PORT = CMD_WR_USB_DATA7;//写命令
Delay2us( );
CH375_DAT_PORT = len;//自我约定第一个数是要发送数据的大小,当然也可以贱点,设置自己的描述后面数据符号
while(len--)CH375_DAT_PORT = *buf++;
}
unsigned char issue_token(unsigned char endp_and_pid)
{
CH375_CMD_PORT = CMD_ISSUE_TOKEN;//这个了就是发送的令牌的指令了,令牌了,其实也是一种配置,配置你选用什么端口(一般
//为2),是输入还是输出,当然,这是对主机而言的,他有资格发送令牌,
Delay2us( );
CH375_DAT_PORT = endp_and_pid;//这里配置的是端口和输入或输出的方式,高四位是端点号,低四位了,就是输入还是输出
return (wait_complete());//等待配置成功
}
//这里是当发送错误的时候,要将对应的端口经行清洗下;去掉原来的错误数据,为下次接受提供条件
unsigned char ERROR(unsigned char err)
{
CH375_CMD_PORT = CMD_CLR_STALL ;要清楚那个端点的命令;
Delay2us( );
CH375_DAT_PORT = err;//那个端点
return(wait_complete());
}
//左主机时候发送
void host_send(unsigned char len,unsigned char *buf)
{
wr_usb_data(len,buf);//先向对应的端点的缓存中写数据,这里采用的是端点2
set_endp7();//对端点DAT1奇偶配置一下,也为下次左准备
if(issue_token(0x21) !=USB_INT_SUCCESS)ERROR(0x02);//这里的令牌是端点2,低位的1是输出模式
else if(buf == NULL) printf("0kn");
}
//这个是主机接受了
unsigned char host_recv(unsigned char *buf)
{
set_endp6();//端点2的DAT0奇偶配置一下,为下次作准备
if(issue_token(0x29) != USB_INT_SUCCESS)ERROR(0x82);//这里令牌是端点2,低位9为输入模式
return (rd_usb_data(buf));//读啊,读
}
unsigned char GetKeyCode(void)//这个是按键,对应命令
{
if(KEYPIN1==0) return 1;//对应从机的灯打开;
if(KEYPIN2==0) return 2;//对应的从机灯全关
if(KEYPIN3==0) return 3;
if(KEYPIN4==0) return 4;
if(KEYPIN5==0) return 5;
if(KEYPIN6==0) return 6;
return 0;
}
#endif
#include
#include
#include "ch375.h"
#include"bianlian.h"
#include "cui.h"
void init_uart() //uart init串口的配置,为了下载和终端上面检测用的
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x20;
TH1 = 0xfd;
TR1 = 1;
TI = 1;
}
void init_rst() //rst//初始时,复位下
{
CH375RS = 1;
Delay_ms(100);
CH375RS = 0;
Delay_ms(200);
}
void CH375_Init( )//初始化,首先检测单片机与CH375的硬件并口是否连通
{
unsigned char i;
CH375_CMD_PORT = CMD_CHECK_EXIST;
Delay2us( );
CH375_DAT_PORT = 0x55;
Delay2us( );
i = ~ 0x55;
if ( CH375_DAT_PORT != i )
{
for ( i=80; i!=0; i-- )
{
CH375_CMD_PORT = CMD_RESET_ALL;
Delay2us( );
}
CH375_CMD_PORT = 0;
Delay_ms(50);
}
set_usb_mode(6);
//开中断,低电平有效
IT0 = 0;
IE0 = 0;
EX0 = 1;
}
int main()
{
unsigned char *buf;
init_uart();
init_rst();
CH375_Init( );
while(wait_complete() != USB_INT_CONNECT);//查看usb有插入设备
printf("lianjien");
while(1){
key = GetKeyCode();//获取按键
switch(key){
case 1://0x9我整的是从机灯亮
cmd_cui.mCommandCode = DEMO_CXP_CMD;//配置一个命令字给从机,来完成想要的控制
cmd_cui.mCommandCodeNot = ~(DEMO_CXP_CMD);//跟上面数据相反,用来校验
cmd_cui.u.mParameter[1] = 0x8;//控制的模式
cmd_cui.u.mParameter[2] = 0x9;//控制模式,这两个数据根据自己需要,当然整个变量野可以自己修改,东西是死的,人是活的;
//printf("1lallais %cn",cmd_cui.u.mParameter[1]) ;
buf = (unsigned char *)(&cmd_cui);//将上面数据以字节8位的形式发送出去,先取它的首地址,然后一个个字节发送
printf("cmd_cui is %cn",buf[3]);//由于从机要用到此发送的命令信息,在这里可以在终端上面显示,是否数据正确
host_send(7,buf);
// host_send(0,NULL);
break;
case 2://0x8整的是从机灯灭
cmd_cui.mCommandCode = DEMO_CXP_CMD;
cmd_cui.mCommandCodeNot = ~(DEMO_CXP_CMD);
cmd_cui.u.mParameter[1] = 0x9;
cmd_cui.u.mParameter[2] = 0x8;
//printf("1lallais %cn",cmd_cui.u.mParameter[1]) ;
buf = (unsigned char *)(&cmd_cui);
printf("cmd_cui is %cn",buf[3]);
host_send(7,buf);
break;
default:
// printf("errn");
break;
}
key = 0;
// printf("riririn");
}
}