STM32和CH375B芯片连接,采用并行方式。
初始化并从第10240扇区开始读取,每次读取1个扇区,前9个扇区都能正常读出。 第十次发出CMD_DISK_READ命令后,再也不进入中断了。
并且芯片ACT#脚所连接的LED也灭了。。。
如果一次读取5个扇区,那么读取第二次的时候也会死掉。
STM32和CH375B芯片连接,采用并行方式。
初始化并从第10240扇区开始读取,每次读取1个扇区,前9个扇区都能正常读出。 第十次发出CMD_DISK_READ命令后,再也不进入中断了。
并且芯片ACT#脚所连接的LED也灭了。。。
如果一次读取5个扇区,那么读取第二次的时候也会死掉。
又有新发现了。如果从10240扇区开始读,那么只能读出9个扇区。
如果从0扇区开始读,只能读出5个扇区。
从128扇区开始读,能读出50个扇区都不死掉。。。。。
U盘用紫光1G和SanDisk 128M分别测试,表现也完全一样。。
(1)LED灭的时候,测一下D+上是否还有3V以上的电压 (2)估计与你的程序有关把程序贴出来看看
您好,(1),LED灭时,D+是高电平
2,相关代码如下,请指教:
//主函数
/////////////////以下代码中的所有Usart1_SendByte()都是为了调试,通过串口监控程序运行
int main(void) { for(;;) {
if(g_UsbInsertFlag) { Usb_ReadAllFiles(); g_UsbInsertFlag = FALSE; } }
////这里省略了其它正常代码 }
//=========================================================== ///读取函数 void Usb_ReadAllFiles(void) { UI32 msgIndex = 0; //读取计数器 UI32 errCount = 0; UI8 state ; UI32 msgID; //信息ID //延时,等待稳定 for(state=0; state<10; state++) { Usart1_SendByte(Ch375GetDiskStatus()); delay_ms(10); } if(Ch375GetDiskStatus() != STATUS_READY) { Usart1_SendByte(0x46); Led_Flash(E_DISK_ERROR); return; }
for(msgIndex = 0; msgIndex < 50; msgIndex++) { state = ReadPage(msgIndex); //读取一个扇区 Usart1_SendByte(msgIndex); Usart1_SendByte(state); Usart1_SendByte(g_Buff0[0]); //目前遇到的问题:如果USB_BASE_SEC=0,则msgIndex跑到4就不动了 //如果USB_BASE_SEC=10240, msgIndex跑到9就不动了 //如果USB_BASE_SEC=128, msgIndex可以一直跑到49
delay_ms(100); } }
=========================================================================== //读扇区函数,以及相关宏定义
#define USB_BASE_SEC 0 //10240 //信息存储的开始扇区数(一扇区512字节) #define USB_SEC_SIZE 512 #define MSG_SEC_NUM 1 //每条信息所占?个USB扇区
UI8 ReadPage(UI32 index) { UI8 ret; //读出一个扇区 g_Buff0[0] = 0x55;
ret = Ch375ReadSector(USB_BASE_SEC + index, 1, g_Buff0]); if(!ret) { Usart_SendByte(0x50); return S_ERR; }
delay_ms(10);
return S_OK; }
//============================================================ //ch375相关函数,该文件中代码核心部分来自于网络,删掉了一些写入相关代码 //============================================================
// 基本操作 // 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 void Ch375WriteCmd( CPU_INT08U mCmd ) { //Ch375Nop(); delay_us(1); //Ch375Delay1uS( ); // 至少延时1uS CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_DATA_OUTPUT(); CH375_DATA_OUT(mCmd); // 向CH375的并口输出数据 CH375_SET_A0(); // 输出A0=1 CH375_CLR_WR(); //WR=0 CH375_SET_RD(); //RD=1 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); CH375_SET_WR(); //WR=1 CH375_CLR_A0(); // 输出A0=0 CH375_SET_CS(); //Ch375Nop(); CH375_DATA_INPUT(); delay_us(2); //Ch375Nop(); //Ch375Delay1uS( ); // Ch375Delay1uS( ); // 至少延时2uS }
// 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 void Ch375WriteData( CPU_INT08U mData ) { //Ch375Nop( ); //Ch375Delay1uS( ); // 至少延时1uS delay_us(1); CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_DATA_OUTPUT(); CH375_DATA_OUT(mData); // 向CH375的并口输出数据 CH375_CLR_A0(); // 输出A0=0 CH375_CLR_WR(); //WR=0 CH375_SET_RD(); //RD=1 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); CH375_SET_A0(); // 输出A0=1 CH375_SET_WR(); //WR=1 CH375_SET_CS(); //Ch375Nop(); CH375_DATA_INPUT(); //Ch375Nop(); //Ch375Delay1uS( ); //Ch375Delay1uS( ); // 至少延时1.2uS delay_us(2); }
// 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 CPU_INT08U Ch375ReadData(void) { CPU_INT08U mData;
//Ch375Delay1uS( ); // 至少延时1.2uS //Ch375Nop(); delay_us(1); CH375_DATA_INPUT(); CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_CLR_A0(); // 输出A0=0 CH375_SET_WR(); //WR=1 CH375_CLR_RD(); //RD=0 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); mData = CH375_DATA_GET() & CH375_DAT_MASK; // 从CH375的并口PA输入数据 CH375_SET_A0(); // 输出A0=0 CH375_SET_RD(); //RD=1 CH375_SET_CS(); //Ch375Delay1uS( ); //Ch375Delay1uS( ); // 至少延时1.2uS //Ch375Nop(); delay_us(2); return( mData );
}
UI8 Ch375SetMode(UI8 mode) { UI8 i, d; Ch375WriteCmd( CMD_SET_USB_MODE ); // 设置USB工作模式 //delay_us(30); Ch375WriteData(mode ); // 模式代码 for ( i = 0xff; i != 0; i -- ) { // 等待操作成功,通常需要等待10uS-20uS delay_us(1); d=Ch375ReadData( ); if ( d == CMD_RET_SUCCESS ) { break; // 操作成功 } } return i; }
// 设置CH375为USB主机方式 CPU_INT08U Ch375Init(void ) { CPU_INT08U i; CPU_INT08U d; GPIO_InitTypeDef GPIO_InitStructure; //EXTI_InitTypeDef EXTI_InitStructure; //NVIC_InitTypeDef NVIC_InitStructure; //enable PORT clock //RCC_APB2PeriphClockCmd(RCC_APB2Periph_CH375_CTRPORT | RCC_APB2Periph_AFIO, ENABLE); //RCC_APB2PeriphClockCmd(RCC_APB2Periph_CH375_DATPORT , ENABLE); //ctr prot to push-pull GPIO_InitStructure.GPIO_Pin = CH375_WR_MASK | CH375_RD_MASK | CH375_A0_MASK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(CH375_A0_PORT, &GPIO_InitStructure); //data port to Input pull-up GPIO_InitStructure.GPIO_Pin = CH375_DAT_MASK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(CH375_DATA_PORT, &GPIO_InitStructure);
mDiskStatus = STATUS_DISCONNECT; Ch375WriteCmd( CMD_CHECK_EXIST); Ch375WriteData(0xa5); d=Ch375ReadData(); //Usart1_SendByte(0x60); /////// if(d!=0x5a) { //Usart1_SendByte(0x61); //////// Ch375WriteCmd(CMD_RESET_ALL); //Ch375Delay100mS(); delay_ms(100); } i = Ch375SetMode(6); /* //Usart1_SendByte(0x62);//////// Ch375WriteCmd( CMD_SET_USB_MODE ); // 设置USB工作模式 //delay_us(30); Ch375WriteData( 6 ); // 模式代码,自动检测USB设备连接 //delay_us(30); for ( i = 0xff; i != 0; i -- ) { // 等待操作成功,通常需要等待10uS-20uS d=Ch375ReadData( ); if ( d == CMD_RET_SUCCESS ) { break; // 操作成功 } } //Usart1_SendByte(0x63);//////// */ return i; }
CPU_INT08U Ch375GetDiskStatus(void) { CPU_INT08U r = mDiskStatus; return r; }
// CH375中断服务程序,使用寄存器组1 void Ch375Isr(void) { CPU_INT08U s; CPU_INT08U len; Ch375WriteCmd( CMD_GET_STATUS ); // 获取中断状态并取消中断请求 delay_us(2); // 至少延时2uS s = Ch375ReadData( ); // 获取中断状态 switch(s) { case USB_INT_SUCCESS://0x14 switch(mDiskStatus) { case STATUS_CONNECT: mDiskStatus = STATUS_WAIT_INIT; Ch375WriteCmd(CMD_DISK_READY);// 产生中断 //Usart1_SendByte(0x44); /////////////////////////////////////////////////// //注:这个变量是我加的,目的是在主循环中,得到U盘已经插入的事件 g_UsbInsertFlag = TRUE; /////////////////////////////////////////////////// break; case STATUS_READ_DISK_SIZE: Ch375WriteCmd( CMD_RD_USB_DATA ); // 从CH375缓冲区读取数据块 delay_us(2); // 至少延时2uS len = Ch375ReadData( ); // 后续数据的长度 //delay_us(4); while ( len-- ) { // 根据长度读取数据 *pBufferPoint++ = Ch375ReadData( ); // 读出数据并保存 } mDiskStatus = STATUS_READY; // 操作成功 break; case STATUS_WAIT_INIT: default: mDiskStatus = STATUS_READY; // 操作成功 break; } break; case USB_INT_CONNECT://0x15 mDiskStatus = STATUS_CONNECT; // 检测到USB设备连接事件 //Ch375GenSwi(200);// 如果U盘刚插入那么最好稍等一下再操作 //Ch375Delay100mS(); delay_ms(100); delay_ms(100); Ch375WriteCmd( CMD_DISK_INIT ); // 初始化USB存储器 break; case USB_INT_DISCONNECT://0x16 mDiskStatus = STATUS_DISCONNECT; // 检测到USB设备断开事件 break; case USB_INT_DISK_READ: // USB存储器读数据块,请求数据读出 Ch375WriteCmd( CMD_RD_USB_DATA ); // 从CH375缓冲区读取数据块 //Delay1us(2); // 至少延时2uS
刚刚排版较乱,请看这个:
//主函数
/////////////////以下代码中的所有Usart1_SendByte()都是为了调试,通过串口监控程序运行
int main(void) { for(;;) {
if(g_UsbInsertFlag) { Usb_ReadAllFiles(); g_UsbInsertFlag = FALSE; } }
////这里省略了其它正常代码 }
//=========================================================== ///以下为读取函数 void Usb_ReadAllFiles(void) { UI32 msgIndex = 0; //读取计数器 UI32 errCount = 0; UI8 state ; UI32 msgID; //信息ID //延时,等待稳定 for(state=0; state<10; state++) { Usart1_SendByte(Ch375GetDiskStatus()); delay_ms(10); } if(Ch375GetDiskStatus() != STATUS_READY) { Usart1_SendByte(0x46); Led_Flash(E_DISK_ERROR); return; }
for(msgIndex = 0; msgIndex < 50; msgIndex++) { state = ReadPage(msgIndex); //读取一个扇区 Usart1_SendByte(msgIndex); Usart1_SendByte(state); Usart1_SendByte(g_Buff0[0]); //目前遇到的问题:如果USB_BASE_SEC=0,则msgIndex跑到4就不动了 //如果USB_BASE_SEC=10240, msgIndex跑到9就不动了 //如果USB_BASE_SEC=128, msgIndex可以一直跑到49
delay_ms(100); } }
=========================================================================== //以下为读扇区函数,以及相关宏定义
#define USB_BASE_SEC 0 //10240 //信息存储的开始扇区数(一扇区512字节) #define USB_SEC_SIZE 512 #define MSG_SEC_NUM 1 //每条信息所占?个USB扇区
UI8 ReadPage(UI32 index) { UI8 ret; //读出一个扇区 g_Buff0[0] = 0x55;
ret = Ch375ReadSector(USB_BASE_SEC + index, 1, g_Buff0]); if(!ret) { Usart_SendByte(0x50); return S_ERR; }
delay_ms(10);
return S_OK; }
//============================================================ //以下为ch375相关函数,该文件中代码核心部分来自于网络,删掉了一些写入相关代码 //============================================================
// 基本操作 // 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 void Ch375WriteCmd( CPU_INT08U mCmd ) { //Ch375Nop(); delay_us(1); //Ch375Delay1uS( ); // 至少延时1uS CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_DATA_OUTPUT(); CH375_DATA_OUT(mCmd); // 向CH375的并口输出数据 CH375_SET_A0(); // 输出A0=1 CH375_CLR_WR(); //WR=0 CH375_SET_RD(); //RD=1 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); CH375_SET_WR(); //WR=1 CH375_CLR_A0(); // 输出A0=0 CH375_SET_CS(); //Ch375Nop(); CH375_DATA_INPUT(); delay_us(2); //Ch375Nop(); //Ch375Delay1uS( ); // Ch375Delay1uS( ); // 至少延时2uS }
// 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 void Ch375WriteData( CPU_INT08U mData ) { //Ch375Nop( ); //Ch375Delay1uS( ); // 至少延时1uS delay_us(1); CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_DATA_OUTPUT(); CH375_DATA_OUT(mData); // 向CH375的并口输出数据 CH375_CLR_A0(); // 输出A0=0 CH375_CLR_WR(); //WR=0 CH375_SET_RD(); //RD=1 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); CH375_SET_A0(); // 输出A0=1 CH375_SET_WR(); //WR=1 CH375_SET_CS(); //Ch375Nop(); CH375_DATA_INPUT(); //Ch375Nop(); //Ch375Delay1uS( ); //Ch375Delay1uS( ); // 至少延时1.2uS delay_us(2); }
// 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 CPU_INT08U Ch375ReadData(void) { CPU_INT08U mData;
//Ch375Delay1uS( ); // 至少延时1.2uS //Ch375Nop(); delay_us(1); CH375_DATA_INPUT(); CH375_CLR_CS(); //CS = 0,可以一直接地 CH375_CLR_A0(); // 输出A0=0 CH375_SET_WR(); //WR=1 CH375_CLR_RD(); //RD=0 //Ch375Nop(); // 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于100nS delay_us(1); mData = CH375_DATA_GET() & CH375_DAT_MASK; // 从CH375的并口PA输入数据 CH375_SET_A0(); // 输出A0=0 CH375_SET_RD(); //RD=1 CH375_SET_CS(); //Ch375Delay1uS( ); //Ch375Delay1uS( ); // 至少延时1.2uS //Ch375Nop(); delay_us(2); return( mData );
}
UI8 Ch375SetMode(UI8 mode) { UI8 i, d; Ch375WriteCmd( CMD_SET_USB_MODE ); // 设置USB工作模式 //delay_us(30); Ch375WriteData(mode ); // 模式代码 for ( i = 0xff; i != 0; i -- ) { // 等待操作成功,通常需要等待10uS-20uS delay_us(1); d=Ch375ReadData( ); if ( d == CMD_RET_SUCCESS ) { break; // 操作成功 } } return i; }
// 设置CH375为USB主机方式 CPU_INT08U Ch375Init(void ) { CPU_INT08U i; CPU_INT08U d; GPIO_InitTypeDef GPIO_InitStructure; //EXTI_InitTypeDef EXTI_InitStructure; //NVIC_InitTypeDef NVIC_InitStructure; //enable PORT clock //RCC_APB2PeriphClockCmd(RCC_APB2Periph_CH375_CTRPORT | RCC_APB2Periph_AFIO, ENABLE); //RCC_APB2PeriphClockCmd(RCC_APB2Periph_CH375_DATPORT , ENABLE); //ctr prot to push-pull GPIO_InitStructure.GPIO_Pin = CH375_WR_MASK | CH375_RD_MASK | CH375_A0_MASK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(CH375_A0_PORT, &GPIO_InitStructure); //data port to Input pull-up GPIO_InitStructure.GPIO_Pin = CH375_DAT_MASK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(CH375_DATA_PORT, &GPIO_InitStructure);
mDiskStatus = STATUS_DISCONNECT; Ch375WriteCmd( CMD_CHECK_EXIST); Ch375WriteData(0xa5); d=Ch375ReadData(); //Usart1_SendByte(0x60); /////// if(d!=0x5a) { //Usart1_SendByte(0x61); //////// Ch375WriteCmd(CMD_RESET_ALL); //Ch375Delay100mS(); delay_ms(100); } i = Ch375SetMode(6); /* //Usart1_SendByte(0x62);//////// Ch375WriteCmd( CMD_SET_USB_MODE ); // 设置USB工作模式 //delay_us(30); Ch375WriteData( 6 ); // 模式代码,自动检测USB设备连接 //delay_us(30); for ( i = 0xff; i != 0; i -- ) { // 等待操作成功,通常需要等待10uS-20uS d=Ch375ReadData( ); if ( d == CMD_RET_SUCCESS ) { break; // 操作成功 } } //Usart1_SendByte(0x63);//////// */ return i; }
CPU_INT08U Ch375GetDiskStatus(void) { CPU_INT08U r = mDiskStatus; return r; }
// CH375中断服务程序,使用寄存器组1 void Ch375Isr(void) { CPU_INT08U s; CPU_INT08U len; Ch375WriteCmd( CMD_GET_STATUS ); // 获取中断状态并取消中断请求 delay_us(2); // 至少延时2uS s = Ch375ReadData( ); // 获取中断状态 switch(s) { case USB_INT_SUCCESS://0x14 switch(mDiskStatus) { case STATUS_CONNECT: mDiskStatus = STATUS_WAIT_INIT; Ch375WriteCmd(CMD_DISK_READY);// 产生中断 //Usart1_SendByte(0x44); /////////////////////////////////////////////////// //注:这个变量是我加的,目的是在主循环中,得到U盘已经插入的事件 g_UsbInsertFlag = TRUE; /////////////////////////////////////////////////// break; case STATUS_READ_DISK_SIZE: Ch375WriteCmd( CMD_RD_USB_DATA ); // 从CH375缓冲区读取数据块 delay_us(2); // 至少延时2uS len = Ch375ReadData( ); // 后续数据的长度 //delay_us(4); while ( len-- ) { // 根据长度读取数据 *pBufferPoint++ = Ch375ReadData( ); // 读出数据并保存 } mDiskStatus = STATUS_READY; // 操作成功 break; case STATUS_WAIT_INIT: default: mDiskStatus = STATUS_READY; // 操作成功 break; } break; case USB_INT_CONNECT://0x15 mDiskSt
曾经做过的尝试: 1,在检测到u盘插入时,先切换到模式7再切换到模式6,效果未变化 2,在代码中多处增加延时,或加大原有延时,效果未变化
(1)确保写命令、写数据、读数据函数中的延时务必精确一些,命令后延时1.5uS,数据后延时0.6uS;CH375的RD、WR信号宽度最小60nS就够了,参考下面的读写时序 void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定义的被CH375程序库调用的子程序,向CH375写命令 */ { P0 = mCmd; /* 向CH375的并口输出数据 */ CH375_A0 = 1; CH375_CS = 0; CH375_WR = 0; /* 输出有效写控制信号, 写CH375芯片的命令端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于60nS */ CH375_WR = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; CH375_A0 = 0; P0 = 0xFF; /* 禁止数据输出 */ mDelay1_2uS( );/* 至少延时1.5uS */ }
void xWriteCH375Data( UINT8 mData ) /* 外部定义的被CH375程序库调用的子程序,向CH375写数据 */ { P0 = mData; /* 向CH375的并口输出数据 */ CH375_A0 = 0; CH375_CS = 0; CH375_WR = 0; /* 输出有效写控制信号, 写CH375芯片的数据端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于60nS */ CH375_WR = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; P0 = 0xFF; /* 禁止数据输出 */ mDelay1uS( ); /* 至少延时0.6uS */ }
UINT8 xReadCH375Data( void ) /* 外部定义的被CH375程序库调用的子程序,从CH375读数据 */ { UINT8 mData;
P0 = 0xFF; /* 输入 */ CH375_A0 = 0; CH375_CS = 0; CH375_RD = 0; /* 输出有效写控制信号, 读CH375芯片的数据端口 */ CH375_CS = 0; /* 该操作无意义,仅作延时,CH375要求读写脉冲宽度大于60nS */ mData = P0; /* 从CH375的并口输入数据 */ CH375_RD = 1; /* 输出无效的控制信号, 完成操作CH375芯片 */ CH375_CS = 1; mDelay1uS( ); /* 至少延时0.6uS */ return( mData ); } (2)对于模式的设置应该是先设为模式5,U盘连接后设置模式7总线复位,重新等待U盘连接后再设为模式6 (3)这个程序改动比较大,下载CH375EVT.ZIP,移植MISCELL下的例程试试,注意仅修改375的接口程序,用查询方式
请教: (1) ----------------------------------------------- 确保写命令、写数据、读数据函数中的延时务必精确一些 ----------------------------------------------- 延时太短肯定有问题,长了是否也会有问题?比如本应1uS,但实际延时2uS。
(2) ---------------------------------- 对于模式的设置应该是先设为模式5 ---------------------------------- MISCELL下的例程,好像都是直接设为6的,请问是否6也能用,只是兼容性不好?
(1)这样的延时也是可以的,误差不要太大就行 (2)可以用,只是兼容性要差一些
我觉得这很有可能是你的操作流程有问题,Ch375WriteCmd( CMD_DISK_INIT ); 是不是每次都能成功?然后获取容量呢?设置块大小呢? CH375EVT.ZIP,里面有MISCELL.先按照这个去修改,流程正确后在去修改.磁盘容量一定要去获取,并且正确的获取到否则可能会有很多U盘不兼容.
请问各位有没哪个文档会对库函数所包含的子函数有详细描述?我在例程里好像没有看到相关文档。
我现在设计的硬件电路是把CH375挂在数据总线上当RAM用,在写命令跟写数据时用不同的RAM地址选中,请问这样可以直接使用CH375HF4的库函数吗?
CH375EVT.ZIP中有CH375HF.PDF,里面哟程序库的详细说明.
另部分函数的定义在头文件中,还可以参考库的头文件
总线就是这样用的,完全可以的.只要A0,CS,DATA,WR,RD按照总线连接就可以了.
不好意思,发错地方了,我以为跟着我自己的贴发了。谢谢回复。我想请问库函数是不是直接支持总线方式?