求助:关于CH375的命令端口和数据端口的地址的问题

我用的单片机是内置的4K的RAM,即集成在片内的外部RAM。现在想用并口方式与CH375相连接。但是CH375的命令端口和数据端口的地址问题应该如何选定呢? 我看CH375模块的例程上是这么定义的: #define CH375_CMD_PORT_ADDR 0xBDF1 /* CH375命令端口的I/O地址 */ #define CH375_DAT_PORT_ADDR 0xBCF0 /* CH375数据端口的I/O地址 */

但是我不需要模块中外置的32K的RAM,那么我的单片机应该如何给CH375的命令端口和数据端口分配地址呢? 例如我目前的硬件接法:我的P2.0至P2.7口接CH375的D0至D7,P3.0接CS,P3.1接A0,RD接RD,WR接WR。先将CS置0,然后我想写命令时,将A0也置0,然后将命令写到P2口;想写数据时再将A0置1,再往P2口上写数据。不知道我这种做法正确么

您是操作CH375芯片,还是模块呢?前者A0 = 1,是写命令;A0 = 0,是写数据,后者与其正好相反 您的硬件接口是模拟I/O方式,不存在地址,操作时序参考: /* 本例用I/O引脚模拟产生CH375的并口读写时序 */ /* 本例中的硬件连接方式如下(实际应用电路可以参照修改下述3个并口读写子程序) */ /* 单片机的引脚 CH375芯片的引脚 P3.2 INT# P1.0 A0 P1.1 CS# 如果模拟出的并口上只有CH375,那么CS#可以直接接低电平,强制片选 P1.2 WR# P1.3 RD# P0(8位端口) D7-D0 */ sbit CH375_A0 = P1^0; sbit CH375_CS = P1^1; sbit CH375_WR = P1^2; sbit CH375_RD = P1^3;

void mDelay1_2uS( ) /* 至少延时1.2uS,根据单片机主频调整 */ { return; }

void CH375_PORT_INIT( ) /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */ { CH375_CS = 1; CH375_WR = 1; CH375_RD = 1; CH375_A0 = 0; P0 = 0xFF; /* 并口输入 */ }

void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定义的被CH375程序库调用的子程序,向CH375写命令 */ { mDelay1_2uS( ); mDelay1_2uS( ); /* 至少延时1uS */ P0 = mCmd; /* 向CH375的并口输出数据 */ CH375_A0 = 1; CH375_CS = 0; CH375_WR = 0; /* 输出有效写控制信号, 写CH375芯片的命令端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS */ CH375_WR = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; CH375_A0 = 0; P0 = 0xFF; /* 禁止数据输出 */ mDelay1_2uS( ); mDelay1_2uS( ); /* CH375B至少延时1.6uS */ }

void xWriteCH375Data( UINT8 mData ) /* 外部定义的被CH375程序库调用的子程序,向CH375写数据 */ { P0 = mData; /* 向CH375的并口输出数据 */ CH375_A0 = 0; CH375_CS = 0; CH375_WR = 0; /* 输出有效写控制信号, 写CH375芯片的数据端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS */ CH375_WR = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; P0 = 0xFF; /* 禁止数据输出 */ mDelay1_2uS( ); /* CH37B至少延时0.6uS */ }

UINT8 xReadCH375Data( void ) /* 外部定义的被CH375程序库调用的子程序,从CH375读数据 */ { UINT8 mData; mDelay1_2uS( ); /* 至少延时1.2uS */ P0 = 0xFF; /* 输入 */ CH375_A0 = 0; CH375_CS = 0; CH375_RD = 0; /* 输出有效写控制信号, 读CH375芯片的数据端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS */ mData = P0; /* 从CH375的并口输入数据 */ CH375_RD = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; return( mData ); }


为什么我运行到mStopIfError( i )时,iError的值总是为0x81呢? 而且在i = CH375LibInit( ) 中这个函数的返回值是return( CH375Init( )) 但是CH375Init这个函数好像在子程序库里,我看不到,但是好像调用了: void xWriteCH375Cmd( UINT8 mCmd )/* 外部定义的被CH375程序库调用的子程序,向CH375写命令 */ 和 void xWriteCH375Data( UINT8 mData )/* 外部定义的被CH375程序库调用的子程序,向CH375写数据 */ 这两个函数,真是看不明白啊!!!

UINT8 CH375LibInit( void ) /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ { if ( SP > 0xEE ) return( 0xFC ); /* 单片机的堆栈空间不够,CH375子程序库最多可能有7级子程序,查询方式最多需要14字节的堆栈空间,建议提供余量 */ CH375LibConfig = LIB_CFG_VALUE; /* CH375程序库配置值 */ if ( CH375GetVer( ) < CH375_LIB_VER ) return( 0xFF ); /* 获取当前子程序库的版本号,版本太低则返回错误 */ #if DISK_BASE_BUF_LEN pDISK_BASE_BUF = & DISK_BASE_BUF[0]; /* 指向外部RAM的磁盘数据缓冲区 */ #endif return( CH375Init( ) ); /* 初始化CH375 */ } main( ) { UINT8 i, month, hour; UINT16 date, adc, len; C8051F340_INIT(); CH375_PORT_INIT( ); /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */ LED_OUT_INIT( ); LED_OUT_ACT( ); /* 开机后LED亮一下以示工作 */ mDelaymS( 100 ); /* 延时100毫秒 */ LED_OUT_INACT( ); // mInitSTDIO( ); /* 为了让计算机通过串口监控演示过程 */ // printf( "Start\n" );

i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i );


0x81错误主要是硬件连接和接口程序有问题,请检查: (1)硬件连线 (2)如果是模拟I/O,接口程序参考1楼示例,并检查I/O口配置是否正确


请问如果我用的是FILELBC中的EXAM7,其中他说也可以用串口的方法,我的程序如下:为什么总是在 i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ 这个程序处进入死循环呢? 停止运行后,程序显示运行到:while这一行 UINT8 xReadCH375Data( void ) { while ( RI0 == 0 ); RI0 = 0; return( SBUF0 ); } /* 2004.06.05 **************************************** ** Copyright (C) W.ch 1999-2004 ** ** Web: http://www.winchiphead.com ** **************************************** ** USB Host File Interface for CH375 ** ** TC2.0@PC, KC7.0@MCS51 ** **************************************** */ /* CH375 主机文件系统接口 */ /* 支持: FAT12/FAT16/FAT32 */

/* MCS-51单片机C语言的U盘文件读写示例程序 */ /* 用于以下情况的MCS51单片机 1. 高速MCS51单片机,机器周期小于0.3uS,或者在机器周期为12个时钟时的时钟频率大于40MHz 2. 非总线MCS51单片机,用普通I/O引脚模拟8位并行总线读写,与CH375之间采用并口连接 3. 单片机与CH375之间采用串口连接 */ /* 本程序用于演示将ADC模数采集的数据保存到U盘文件MY_ADC.TXT中 */ /* CH375的INT#引脚采用查询方式处理,本例用普通I/O引脚模拟8位并行总线读写,同时提供串口连接示例, 以字节为单位读写U盘文件,读写速度较扇区模式慢,但是由于字节模式读写文件不需要文件数据缓冲区FILE_DATA_BUF, 所以总共只需要600字节的RAM,适用于单片机硬件资源有限、数据量小并且读写速度要求不高的系统 */

/* C51 CH375HFT.C */ /* LX51 CH375HFT.OBJ , CH375HFC.LIB */ /* OHX51 CH375HFT */ #include"c8051f340.h"

#include

#define MAX_BYTE_IO 35 /* 以字节为单位单次读写文件时的最大长度,默认值是29,值大则占用内存多,值小则超过该长度必须分多次读写 */

/* 以下定义的详细说明请看CH375HFC.H文件 */ #define LIB_CFG_FILE_IO 1 /* 文件读写的数据的复制方式,0为"外部子程序",1为"内部复制" */ #define LIB_CFG_INT_EN 0 /* CH375的INT#引脚连接方式,0为"查询方式",1为"中断方式" */ /*#define LIB_CFG_UPD_SIZE 1*/ /* 在添加数据后是否自动更新文件长度: 0为"不更新",1为"自动更新" */ /* 默认情况下,如果扇区数/字节数不为0那么CH375FileWrite/CH375ByteWrite只负责写入数据而不修改文件长度, 如果需要每次写完数据后会自动修改/更新文件长度,那么可以使全局变量CH375LibConfig的位4为1, 如果长时间不写入数据则应该更新文件长度,防止突然断电后前面写入的数据与文件长度不相符, 如果确定不会突然断电或者后面很快有数据不断写入则不必更新文件长度,可以提高速度并减少U盘损耗(U盘内部的内存寿命有限,不宜频繁改写) */

/* 只使用单片机内置的1KB外部RAM: 0000H-01FFH 为磁盘读写缓冲区, 以字节为单位读写文件不需要文件数据读写缓冲区FILE_DATA_BUF */ #define DISK_BASE_BUF_ADDR 0x0000 /* 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE */ //#define FILE_DATA_BUF_ADDR 0x0000 /* 外部RAM的文件数据缓冲区的起始地址,缓冲区长度不小于一次读写的数据长度,字节模式不用该缓冲区 */ /* 由于单片机内置的外部RAM只有1KB, 有些单片机还要去掉256字节内部RAM, 只剩下768字节的外部RAM, 其中前512字节由CH375子程序用于磁盘数据缓冲 */ //#define FILE_DATA_BUF_LEN 0x0200 /* 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度,字节模式不用该缓冲区 */ /* 如果准备使用双缓冲区交替读写,那么不要定义FILE_DATA_BUF_LEN,而是在参数中指定缓冲区起址,用CH375FileReadX代替CH375FileRead,用CH375FileWriteX代替CH375FileWrite */

#define CH375_INT_WIRE P3^2 /* P3.2, INT0, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态 */

#define NO_DEFAULT_CH375_F_ENUM 1 /* 未调用CH375FileEnumer程序故禁止以节约代码 */ #define NO_DEFAULT_CH375_F_QUERY 1 /* 未调用CH375FileQuery程序故禁止以节约代码 */

#include "CH375HFC.H"

sbit P2_2 = P2^2; #define LED_OUT_INIT( ) { P2_2 = 0; } /* P1.4 高电平 */ #define LED_OUT_ACT( ) { P2_2 = 1; } /* P1.4 低电平驱动LED显示 */ #define LED_OUT_INACT( ) { P2_2 = 0; } /* P1.4 低电平驱动LED显示 */ sbit P2_3 = P2^3; /* 在P1.5连接一个LED用于监控演示程序的进度,低电平LED亮,当对U盘操作时亮 */ #define LED_RUN_ACT( ) { P2_3 = 1; } /* P1.5 低电平驱动LED显示 */ #define LED_RUN_INACT( ) { P2_3 = 0; } /* P1.5 低电平驱动LED显示 */

void mDelay1_2uS( ) /* 至少延时1.2uS,根据单片机主频调整 */ { return; }

void CH375_PORT_INIT( ) { PCA0MD &= ~0x40; //关闭看门狗 OSCICN |= 0x03; //使用内部12M晶振 mDelay1_2uS( ); //延时 TMOD|=0x20; //定时器1工作在方式2:自动重装载8位定时器 CKCON|=0x01; //定时器1的时钟为系统时钟的4分频,即3M频率 TH1=0X64; //设置重装载值,公式为 波特率=(T1clk/2)/(256-T1H)

P0MDIN = 0xFF; P1MDIN = 0xFF; P2MDIN = 0xFF; P2MDOUT = 0xff; P3MDIN = 0xFF; P3MDOUT =0; P3=0XFF; P2_2=0; P2_3=0; XBR0 = 0X01; //把UART的TX0接到P0.4,RX0接到P0.5 P0SKIP=0X30; //交叉开关跳过P0.4和P0.5 XBR1 = 0XC0; //使能交叉开关,关闭弱上拉

SCON0 = 0xD0; //使用UART0的方式1:波特率可编程的9位UART EA=1; //启动中断 ET1=1; TR1=1; //启动定时器1 }

void xWriteCH375Cmd( UINT8 mCmd ) { TI0 = 0; TB80 = 1; SBUF0 = mCmd; while ( TI0 == 0 ); }

void xWriteCH375Data( UINT8 mData ) { TI0 = 0; TB80 = 0; SBUF0 = mData; while ( TI0 == 0 ); }

UINT8 xReadCH375Data( void ) { while ( RI0 == 0 ); RI0 = 0; return( SBUF0 ); }

/* 以毫秒为单位延时,不精确,适用于24MHz时钟 */ void mDelaymS( UINT8 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 */ } }

/* 将程序空间的字符串复制到外部RAM中,返回字符串长度 */ UINT8 mCopyCodeStringToXRAM( UINT8 xdata *iDestination, UINT8 code *iSource ) { UINT8 i = 0; while ( *iDestination = *iSource ) { iDestination ++; iSource ++; i ++; } return( i ); }

/* 检查操作状态,如果错误则显示错误代码并停机 */ void mStopIfError( UINT8 iError ) { if ( iError == ERR_SUCCESS ) return; /* 操作成功 */ printf( "Error: %02X\n", (UINT16)iError ); /* 显示错误 */ while ( 1 ) { LED_OUT_ACT( ); /* LED闪烁 */ mDelaymS( 100 ); LED_OUT_INACT( ); mDelaymS( 100 ); } }

main( ) { UINT8 i, month, hour; UINT16 date, adc, len; CH375_PORT_INIT( ); /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */ LED_OUT_INIT( ); LED_OUT_ACT( ); /* 开机后LED亮一下以示工作 */ // mDelaymS( 100 ); /* 延时100毫秒 */ LED_OUT_INACT( );

// printf( "Start\n" );

i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); /* 其它电路初始化 */

while ( 1 ) { printf( "Wait Udisk\n" ); while ( CH375DiskStatus != DISK_CONNECT ) xQueryInterrupt( ); /* 查询CH375中断并更新中断状态,等待U盘插入 */ LED_OUT_ACT( ); /* LED亮 */ mDelaymS( 200 ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */

/* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */ for ( i = 0; i < 5; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */ mDelaymS( 100 ); printf( "Ready ?\n" ); if ( CH375DiskReady( ) == ERR_SUCCESS ) break; /* 查询磁盘是否准备好 */ } /* 查询磁盘物理容量 */ /* printf( "DiskSize\n" ); i = CH375DiskSize( ); mStopIfError( i ); printf( "TotalSize = %d MB \n", (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec >> 11 ) ); 显示为以MB为单位的容量 */ LED_RUN_ACT( ); /* 开始操作U盘 */

/* 如果MY_ADC.TXT文件已经存在则添加数据到尾部,如果不存在则新建文件 */ printf( "Open\n" ); mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "/MY_ADC.TXT" ); /* 文件名,该文件在根目录下 */ i = CH375FileOpen( ); /* 打开文件 */ if ( i == ERR_SUCCESS ) { /* 文件存在并且已经被打开,移动文件指针到尾部以便添加数据 */ // printf( "File size = %ld\n", CH375vFileSize ); /* V1.5以上子程序库在成功打开文件后,全局变量CH375vFileSize中是文件当前长度 */ // printf( "Locate tail\n" ); mCmdParam.ByteLocate.mByteOffset = 0xffffffff; /* 移到文件的尾部 */ i = CH375ByteLocate( ); mStopIfError( i ); } else if ( i == ERR_MISS_FILE ) {


(1)CH375默认波特率是:9600bps,确认程序中串口设置是否正确 (2)在CH375LibInit之前,先做个测试命令,方法参考手册


楼上请教一下。我的单片机是新华龙的C8051F040的程序,想用串口模式。 我的连线如下:单片机TXD接375的RXD; 单片机RXD接375的TXD; P3.2接375的INT# 以及电源和地线。 我是使用FILELBC中的EXAM7的例子改的,我的串口已经设成9600bps了,但是P3.2我是随便设的IO口(设成数字输入了),没有专门联到单片机的外部中断处,请问这样可以么。 还有我每次都是初始化不成功,使用检测命令后程序也总是停在这里: while这一行: UINT8 xReadCH375Data( void ) { while ( RI0 == 0 ); RI0 = 0; return( SBUF0 ); }


(1)硬件连接没问题 停在while ( RI0 == 0 );原因可能如下: (2)单片机没能发出命令,CH375没有收到,肯定不会有数据返回,自然会停在这里 (3)CH375没正常工作,如复位不好,晶振没起振,后者用示波器检测,前者在正常复位后,26脚为高,25脚为低 先确认单片机和CH375都能正常工作,且硬件连接没问题,然再确认单片机的串口确实能正确收发数据,若方便的话,可以与计算机通信试试


我按照你的办法测了一遍,都没有问题。现在我发现一个问题,你们给的程序里,是用MCS-51编的 其中SCON=0xD0,我查了一下相关的寄存器说明,你们是将串口用在方式3,且不允许多机通讯,那你们的程序里,为什么还要对TB8操作呢?TB8不是用来区分是数据还是地址么


(1)TB8就是第9位数据,在多机通讯中是用来区分是数据还是地址,非多机通讯时,也能作其他用途,如校验位。我们是借用这个位区分命令和数据。 (2)在主程序中,CH375LibInit之前要等待100mS左右,这是等待CH375上电复位完成


请您仔细把SCON这个给我解释一下好么,因为我用的单片机和普通的51有些不一样,只有方式0和方式1,而且TB8,和RB8的定义也不太一样。 请您说一下 1.当串口使用方式3,即波特率可编程的9位UART时,将SM2置0是不是不允许多机通讯? 2.如果不用多机通讯的话,如何使用TB8来区分发送的是地址,还是数据呢? 谢谢!!!


串口使用方式3 是11位数据通讯.即起始位,8位数据位,一位校验位,一位停止位. SM2为0 是禁止使用多机通讯的 用TB8来表示发送的校验位. 当TB8置1时 表示发送的8位数据位作为命令处理 当TB8置0时 表示发送的8位数据位作为数据处理.


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