📄 main.c
字号:
/* 2004.03.05, 2004.8.18, 2005.12.29
******************************************
** Copyright (C) W.ch 1999-2005 **
** Web: http://www.winchiphead.com **
****************************************
** USB 1.1 Host Examples for CH375 **
** 板砖移植 WINAVR20070122@MEGA128 **
** mail:chairang@126.com **
******************************************
*/
// 单片机通过CH375控制USB打印机
// 程序示例,C语言,CH375中断为查询方式,只负责数据传输,不涉及打印格式及打印描述语言
// 另可提供多台计算机共享一台USB打印机的方案
// 以下定义适用于AVR 单片机,其它单片机参照修改,为了提供C语言的速度需要对本程序进行优化
#include <avr/io.h>
#include <util/delay.h>
// 以下为通用的单片机C程序
#include <string.h>
#include <stdio.h>
// 定义CH375命令代码及返回状态
#include "CH375INC.H"
//unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; // CH375命令端口的I/O地址
//unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; // CH375数据端口的I/O地址
#define CH375_CMD_PORT_ADDR 0x8021 //命令口
#define CH375_DAT_PORT_ADDR 0x8020 //数据口
#define delay1us( ) _delay_us(1)
#define delay2us( ) _delay_us(2)
#define mDelaymS(delay) _delay_ms(delay)
//sbit CH375_INT_WIRE = 0xB0^2; // P3.2, INT0, 连接CH375的INT#引脚,用于查询中断状态
#define CH375_INT_WIRE ( PIND & 0x01 ) // PIND.0, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态
typedef unsigned char BOOL1; // typedef bit BOOL1;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef struct _USB_DEVICE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
typedef struct _USB_INTERF_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
typedef struct _USB_ENDPOINT_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
UCHAR wMaxPacketSize;
UCHAR wMaxPacketSize1;
UCHAR bInterval;
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR_LONG {
USB_CFG_DESCR cfg_descr;
USB_ITF_DESCR itf_descr;
USB_ENDP_DESCR endp_descr[4];
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
unsigned char buffer[64]; // 公用缓冲区
/*
// 延时2微秒,不精确
void delay2us( )
{
unsigned char i;
for ( i = 2; i != 0; i -- );
}
// 延时1微秒,不精确
void delay1us( )
{
unsigned char i;
for ( i = 1; i != 0; i -- );
}
// 以毫秒为单位延时,不精确,适用于24MHz时钟
void mDelaymS( unsigned char delay )
{
unsigned char i, j, c;
for ( i = delay; i != 0; i -- ) {
for ( j = 200; j != 0; j -- ) c += 3; // 在24MHz时钟下延时500uS
for ( j = 200; j != 0; j -- ) c += 3; // 在24MHz时钟下延时500uS
}
}
*/
// 基本操作
void xWriteCH375Cmd( unsigned char cmd ) { // 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时
delay1us( );
delay1us( ); // 至少延时1uS
*(volatile unsigned char *)CH375_CMD_PORT_ADDR = cmd; //通过并口直接读写CH375而非普通I/O模拟
/* PORTB |= 0x08; // 输出A0=1
PORTA = mCmd; // 向CH375的并口输出数据
DDRA = 0xFF; // 并口D0-D7输出
PORTB &= 0xF9; // 输出有效写控制信号, 写CH375芯片的命令端口, A0=1; CS=0; WR=0; RD=1;
DDRA = 0xFF; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS
PORTB |= 0x07; // 输出无效的控制信号, 完成操作CH375芯片, A0=1; CS=1; WR=1; RD=1;
DDRA = 0x00; // 禁止数据输出
PORTB &= 0xF7; // 输出A0=0; 可选操作
*/
delay1us( );
delay1us( ); // 至少延时2uS
}
void xWriteCH375Data( unsigned char dat ) { // 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时
delay1us( );
delay1us( ); // 至少延时1uS
*(volatile unsigned char *)CH375_DAT_PORT_ADDR = dat; //通过并口直接读写CH375而非普通I/O模拟
/*
PORTA = mData; // 向CH375的并口输出数据
DDRA = 0xFF; // 并口D0-D7输出
PORTB &= 0xF1; // 输出有效写控制信号, 写CH375芯片的数据端口, A0=0; CS=0; WR=0; RD=1;
DDRA = 0xFF; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS
PORTB |= 0x07; // 输出无效的控制信号, 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1;
DDRA = 0x00; // 禁止数据输出
*/
delay1us( );
delay1us( ); // 至少延时1.2uS
}
unsigned char xReadCH375Data(void) { // 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时
unsigned char mData;
mData = *(volatile unsigned char *)CH375_DAT_PORT_ADDR; //通过并口直接读写CH375而非普通I/O模拟
delay1us( );
delay1us( ); // 至少延时1.2uS
delay1us( );
/*
DDRA = 0x00; // 数据输入
PORTB &= 0xF2; // 输出有效读控制信号, 读CH375芯片的数据端口, A0=0; CS=0; WR=1; RD=0;
DDRA = 0x00; // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS
mData = PINA; // 从CH375的并口PA输入数据
PORTB |= 0x07; // 输出无效的控制信号, 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1;
*/
return( mData );
}
unsigned char wait_interrupt(void) { // 主机端等待操作完成, 返回操作状态
unsigned short i;
// while( CH375_INT_WIRE ); // 查询等待CH375操作完成中断(INT#低电平)
for ( i = 0; CH375_INT_WIRE != 0; i ++ ) { // 如果CH375的中断引脚输出高电平则等待,通过计数防止超时
mDelaymS( 1 );
//if ( i == 0xF000 ) xWriteCH375Cmd( CMD_ABORT_NAK ); // 如果超时达61mS以上则强行终止NAK重试,中断返回USB_INT_RET_NAK
if ( i == 0x40 ) xWriteCH375Cmd( CMD_ABORT_NAK ); // 如果超时达64mS以上则强行终止NAK重试,中断返回USB_INT_RET_NAK
}
xWriteCH375Cmd( CMD_GET_STATUS ); // 产生操作完成中断, 获取中断状态
return( xReadCH375Data() );
}
#define TRUE 1
#define FALSE 0
unsigned char set_usb_mode( unsigned char mode ) { // 设置CH375的工作模式
xWriteCH375Cmd( CMD_SET_USB_MODE );
xWriteCH375Data( mode );
mDelaymS(2);
while ( xReadCH375Data()!=CMD_RET_SUCCESS )
{
printf("set usb mode error!\n\r");
mDelaymS(200);
}
printf("set usb mode %d ok\n\r",mode);
return( TRUE ); // 成功
//return( FALSE ); // CH375出错,例如芯片型号错或者处于串口方式或者不支持
}
// 数据同步
/* USB的数据同步通过切换DATA0和DATA1实现: 在设备端, USB打印机可以自动切换;
在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1.
主机端的程序处理方法是为设备端的各个端点分别提供一个全局变量,
初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1 */
void toggle_recv( BOOL1 tog ) { // 主机接收同步控制:0=DATA0,1=DATA1
xWriteCH375Cmd( CMD_SET_ENDP6 );
xWriteCH375Data( tog ? 0xC0 : 0x80 );
delay2us();
}
void toggle_send( BOOL1 tog ) { // 主机发送同步控制:0=DATA0,1=DATA1
xWriteCH375Cmd( CMD_SET_ENDP7 );
xWriteCH375Data( tog ? 0xC0 : 0x80 );
delay2us();
}
unsigned char clr_stall( unsigned char endp_addr ) { // USB通讯失败后,复位设备端的指定端点到DATA0
xWriteCH375Cmd( CMD_CLR_STALL );
xWriteCH375Data( endp_addr );
return( wait_interrupt() );
}
// 数据读写, 单片机读写CH375芯片中的数据缓冲区
unsigned char rd_usb_data( unsigned char *buf ) { // 从CH37X读出数据块
unsigned char i, len;
xWriteCH375Cmd( CMD_RD_USB_DATA ); // 从CH375的端点缓冲区读取接收到的数据
len=xReadCH375Data(); // 后续数据长度
for ( i=0; i!=len; i++ ) *buf++=xReadCH375Data();
return( len );
}
void wr_usb_data( unsigned char len, unsigned char *buf ) { // 向CH37X写入数据块
xWriteCH375Cmd( CMD_WR_USB_DATA7 ); // 向CH375的端点缓冲区写入准备发送的数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -