读写
u
盘
C51
示例源程序
#include "datatype.h"
#include "console.h"
#include "44b0x.h"
#include <string.h>
/*
以下定义的详细说明请看
CH375HF9.H
文件
*/
#define LIB_CFG_FILE_IO 1 /*
文件读写的数据的复制方式
,0
为
"
外部子程序
",1
为
"
内部复制
" */
#define LIB_CFG_INT_EN 1 /* CH375
的
INT#
引脚连接方式
,
接
s3c44b0x
外部中断
2
引脚
" */
/*
单片机的
RAM
有限
,
其中
CH375
子程序用
512
字节
,
剩余
RAM
部分可以用于文件读写缓冲
*/
#define FILE_DATA_BUF_LEN 0x2000 /*
外部
RAM
的文件数据缓冲区
,
缓冲区长度不小于一次读写的数据
长度
*/
#include "CH375HF9.H"
#define CH375Cmd *(volatile U8 *)(0x4000001)
/*
总线方式
*/
#define CH375Dat *(volatile U8 *)(0x4000000)
extern U32 MCLK
/* CH375
主机文件系统接搜州源口
*/
/*
支持
: FAT12/FA
T16/F
AT32 */
/* ARM
单片机
C
语言的
U
盘文件读写示例程序
*/
/*
该
程
序
将
U
盘
中
的
/世态C51/CH375HFT.C
文
件
中
的
小
写字
母
转
成
大
写
字
母
后
,
写
到
新
建
的
文
件
NEWFILE.TXT
中
,
如果找不到原文件
CH375HFT.C,
那么该程序将显示
C51
子目录下所有以迹丛
CH375
开头的文件名
,
并新建
NEWFILE.TXT
文件并写入提示信息
,
如果找不到
C51
子目录
,
那么该程序将显示根目录下的所有文件名
,
并新建
NEWFILE.TXT
文件并写入
提示信息
*/
/*
CH375
的
INT#
引脚采用查询方式处理
,
数据复制方式为
"
内部复制
",
本程序适用于
s3c44b0x
单片机
,
串
口
0
输出监控信息
,57600bps */
/* ENDIAN = "little" */
void mDelay1_2uS( )
/*
至少延时
1.2uS,
根据单片机主频调整
*/
{
UINT32 i
for ( i = 30i != 0i -- )
}
CH375是一个国产USB转接芯片,集成了U盘 *** 作固件,可以直接把U盘当做一个一个的扇区来读写,加上一个文件系统,你就可以在U盘上拷贝,粘贴,新建等Windos下具备的文件 *** 作功能了。另外其还支持从机模式,可以让单片机或DSP通过它连接到电脑上实现一个自制的USB鼠标/键盘或U盘等。其兼容USB2.0协议,最大传输速度为USB1.1的12Mbps。对于一般的嵌入式应用来说,速度已经能满足需求。
更可贵的是,这时一片民族芯片,意味着你面对将是中文PDF和一个完善的网络技术支持氛围。使用CH375将让你学习USB协议不再枯燥,不再是纸上谈兵。下面具体阐述一下这两天自己恢复调试该芯片的“艰辛”,其实该芯片并不脆弱,我焊了又拆,拆了又焊上,还是可以用。主要是制造这个芯片南京那家公司技术支持资料太丰富了,太详细了,以至于让我在做电路时也是小心翼翼,最后反而吃了大亏。
一、CH375分为A和B两个系列,A系列支持5V供电,B系列不仅支持5V还支持3.3V。
二、B系列中,如果使用5V供电,则V3引脚通过0.01uF电容接地,如果是3.3V,则V3接3.3V,这点很重要;
三、CH375资料上说对于电源VCC引脚端应该接0.01uF的电容到地,该电容功能为退耦电容,同时,晶振必须为12MHZ,晶振引脚和电容引脚尽量*近CH375的Xi和Xo引脚。如果硬件连接正确,上电时,在Xo端应该可以检测到12MHZ的波形,在没有示波器的情况下,可以用万用表检测档拦Xi和Xo引脚是否为电源电压的一半,即如果是5V供电,此时两个引脚的电压应该接近2.5V,我在自己制作的腐蚀板中变遇到了晶振无法起振的情况,开始怀疑是引脚离得有点远,于是改变了电容的放置位置,使之更*近ch375两个引脚,也没有起振。然后怀疑是CH375坏了,前后一共换了3片还是没有起振,最后在反复检测电路后,换了一颗晶振,我把所有的怀疑都用完后,最后目光聚焦在了两个0603封装的22P电容上,当然开始我还不是怀疑电容有问题,而是ch375应用资料上给的电容是15p的,但手上又没有这个容值的电容,电容都焊下来了,因为太小,掉哪去也不知道,于是重新换了两个22p的,结果却“奇迹般”的起振了。
难道困扰了我两天的竟然是两颗坏了的晶振电容?因为那两个小东西也不知道躲哪去了,我不能再揪出来拷问,那就认为是人品问题吧,遇到了两个坏了电容,或者是自己焊接的时候不小心焊坏了,罪过。。。后来我还原了电路,一层一层验证,取下了VCC的退耦电容,可以工作;再把两个电容移回原来离CH375较远的位置,还是可以起振。仅以此调试经验警醒自己,我怀疑的逻辑,相信大多数人也是这样,越大的,越复杂的,越脆弱,呵呵,这种逻辑有问题么?调试是一个痛苦的过程,调试又是一个快乐的过程,恭喜你,嵌入式工程师,尝尽人间苦乐!
四、当上电后CH375能起振了,这时还可以测一下25和26脚的电平,26为高,25为低,说明硬件复位时成功的,否则你就要看下RST连接的一个到VCC的0.47uF电容那是否有问题了。另外就是,在晶振没有起振的情况下,往CH375写数据,那个指示灯会不停的闪,写一此,闪一次,这是不正常德。
五、当硬件能起振行如胡了,复位也完成了,请将8位数据口接到你的微控制器(单片机或DSP等),然后你还要接A0,WR,RD,INT,最后保证在软件 *** 作芯片的时候CS为低。如此,通过往CH375写命令CMD_CHECK_EXIST(0x06),接着写一个任意8位数据,稍微延时几个毫秒,CH375会返回你一个数据,这个数据是你写的数据的取反,如果你收到了这样一个取反的数据,恭喜你,你的硬件和底层软件读写 *** 作成功了,接下了便可以开始自己的USB协议解析之旅。如果你收到的数据不是正确的取反数据,那么请仔细检查在没有任何线橡腔连接的情况下,晶振是否起振,复位是否成功,如果晶振已经起振,你已经成功了一大半,至于读写的时序,网上到处都是,51的,AVR的,找一个可以用的,稍作移植便可以使用。底层 *** 作成功,是后续分析和学习USB协议的关键。
#pragma NOAREGS //禁止编译器使用绝对寄存器寻址,一定要加上#include <REG52.H> //51单片机头文件#include "CH375INC.H" //CH372/CH375头文件 ///////////////////丛衡//////////////////////////////说明: CH372总线地址// 采用别的方式,地址另外设定///////////////////////////////////////////////unsigned char volatile xdata CH375_CMD_PORT _at_ 0x03F1 unsigned char volatile xdata CH375_DAT_PORT _at_ 0x03F0/*********************延时程序********************/////////////////////////辩芹/////////////////////////函数:delay2us//说明:延时2us//入口:无//返回:无/////////////////////////////////////////////// voiddelay2us( ) { unsigned char i for ( i = 2i != 0i -- ) }/////////////////////////////////////////////////函数:delay50ms//说明:延时50ms//入口:无//返回:无///////////////////////////////////////////////voidDelay50ms( ) { unsigned char i, j for ( i="200"i!=0i-- ) for ( j="250"j!=0j-- ) }/*********************基本读写程序********************/////////////////////////////渗灶做/////////////////////函数:CH375_WR_CMD_PORT//说明:写USB命令//入口:unsigned char cmd:待写入命令//返回:无///////////////////////////////////////////////void CH375_WR_CMD_PORT( unsigned char cmd ){delay2us() CH375_CMD_PORT=cmd delay2us() }/////////////////////////////////////////////////函数:CH375_WR_DAT_PORT//说明:写一字节USB数据//入口:unsigned char dat:待写入一字节数据//返回:无///////////////////////////////////////////////void CH375_WR_DAT_PORT( unsigned char dat ){ CH375_DAT_PORT=dat } /////////////////////////////////////////////////函数:CH375_RD_DAT_PORT//说明:读一字节USB数据//入口:无//返回:从CH372/CH375读一字节数据///////////////////////////////////////////////unsigned char CH375_RD_DAT_PORT( void ){ return( CH375_DAT_PORT ) } /*********************初始化和中断服务程序********************//////////////////////////////////////////////////函数:CH375_Init//说明:CH372/CH375初始化//入口:无//返回:无///////////////////////////////////////////////voidCH375_Init( ) { /* 设置USB工作模式, 必要 *** 作 */unsigned char i CH375_WR_CMD_PORT( CMD_SET_USB_MODE ) //设置USB工作模式CH375_WR_DAT_PORT( 2 ) //设置为内置固件模式for ( i="100"i!=0i-- ){ /* 等待 *** 作成功,通常需要等待10uS-20uS */if ( CH375_RD_DAT_PORT( ) == CMD_RET_SUCCESS ) break } /* 下面启用USB中断,CH372/CH375的INT#引脚可以连接到单片机的中断引脚,中断为低电平有效或者下降沿有效,如果不使用中断,那么也可以用查询方式,由单片机程序查询CH372/CH375的INT#引脚为低电平 */IT0 = 0/* 置外部信号为低电平触发 */IE0 = 0/* 清中断标志 */EX0 = 1 /* 允许CH372中断,假定CH372的INT#引脚连接到单片机的INT0 */} /////////////////////////////////////////////////函数:mCh375Interrupt//说明:CH372/CH375中断程序//入口:无//返回:无///////////////////////////////////////////////void mCh375Interrupt( ) interrupt 0 using 1 { unsigned char i, length unsigned char data buffer[64] unsigned char InterruptStatus CH375_WR_CMD_PORT( CMD_GET_STATUS ) //获取中断状态并取消中断请求 InterruptStatus = CH375_RD_DAT_PORT( ) //获取中断状态//采用边沿触发的外部中断请求,CPU在相应中断后,自动清除中断标志switch ( InterruptStatus ){ case USB_INT_BUS_RESET1: //USB总线复位{ break}case USB_INT_BUS_RESET2: //USB总线复位{ break}case USB_INT_BUS_RESET3: //USB总线复位{ break}case USB_INT_BUS_RESET4: //USB总线复位{ break}case USB_INT_EP0_SETUP: {//端点0 的接收器接收到数据,SETUP 事务成功,内部固件模式时不需要处理break}case USB_INT_EP0_OUT:{//端点0 的接收器接收到数据,OUT 事务成功,内部固件模式时不需要处理break }case USB_INT_EP0_IN:{ //端点0 的发送器发送完数据,IN 事务成功,内部固件模式时不需要处理break }case USB_INT_EP2_OUT://批量端点/端点2接收到数据,OUT成功{ //从当前USB中断的端点缓冲区读取数据块,并释放缓冲区 CH375_WR_CMD_PORT( CMD_RD_USB_DATA ) length = CH375_RD_DAT_PORT( ) /* 首先读取后续数据长度 */ for ( i = 0i <lengthi ++ ) buffer[ i ] = CH375_RD_DAT_PORT( ) //接收数据包 /* -----------测试数据正确性,将接收到的命令包数据返回给PC机----------- */ CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ) /* 向USB端点2的发送缓冲区写入数据块 */ CH375_WR_DAT_PORT( length ) /* 首先写入后续数据长度,回传刚接收到的数据长度 */ for ( i = 0i <lengthi ++ ) CH375_WR_DAT_PORT( buffer[ i ] ) /* 数据返回,由计算机应用程序测试数据是否正确 */ /* ------------------------------------------------------------------------------------------------------ */ break } case USB_INT_EP2_IN: //批量端点/端点2发送完数据,IN成功{ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ) //释放当前USB缓冲区break } default: { CH375_WR_CMD_PORT( CMD_UNLOCK_USB ) break } } }/////////////////////////////////////////////////函数:main//说明:主程序。对CH372初始化,对USB进行读写及其他程序//入口:无//返回:无///////////////////////////////////////////////main( ) { Delay50ms( ) CH375_Init( )//对CH375/CH372初始化EA = 1 //允许中断while(1)}欢迎分享,转载请注明来源:内存溢出
评论列表(0条)