STM32F103RC驱动CH375B模块读写优盘扇区数据

之前做毕设买了CH375B模块,一直没好好用过。现在想把这个模块用起来。程序参考的振南的51例程《U盘扇区读写[IO方式]》 和正点原子的例程模板,只要把最底层的扇区读写测试通过,znFAT文件系统就可以用了。程序用的并口通信控制。先说端口配置:8位数据端口用的GPIOC的低8位,写选通WR、读选通RD、片选 CS、命令口和数据口地址选择A0和中断INT用的GPIOB端口。端口定义如下:

#define  GPIO_CH375_Data    GPIOC     //数据端口
#define  DATA_MODE_IN           GPIO_CH375_Data->CRL=0x44444444;   //  Floating IN
#define  DATA_MODE_OUT          GPIO_CH375_Data->CRL=0x33333333;   //  PP_OUT  50MHZ

#define  GPIO_CH375_CTL         GPIOB   //CH375控制端口
#define  WR                 PBout(11)
#define  RD                 PBout(10)
#define  CS                 PBout(9)
#define  A0                 PBout(8)
#define  INT                PBin(12)

          端口初始化代码如下:


void CH375_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);	 //
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11  ;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);  //
 
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;      //   INT中断
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// GPIO_Mode_IPU;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |GPIO_Pin_3|
	GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7  ; //GPIOC数据端口
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);  //
}
//写命令
void CH375_WR_CMD( u8 cmd )
{
   u16 TempData=0;
   DATA_MODE_OUT;  //设置成数据输出
   TempData=GPIO_ReadOutputData(GPIO_CH375_Data);  //读取数据口数据,保护高8位
   TempData &= 0xFF00;     //低8位清0,保留高8位状态
   TempData |= (u16)cmd;   //写命令
 
	 delay_us(10);    //延时
	 CS=0;           //打开片选
	// delay_us(10);
	 A0=1;           //命令模式
	// delay_us(10);
	 GPIO_Write(GPIO_CH375_Data, TempData); //向CH375写命令码
	 //delay_us(10);
	 WR=0;           //打开写使能
	 delay_us(10);   //
	 WR=1;           //关闭写使能
	 //delay_us(10);
	 CS=1;           //关闭片选
	// delay_us(10);
	 A0=1;           //恢复A0为高电平
	 delay_us(200);  //延时
}
//写数据
void CH375_WR_DAT( u8 dat )
{
   u16 TempData=0;
   DATA_MODE_OUT;   //数据端口设置成输出,发送数据给CH375
   TempData=GPIO_ReadOutputData(GPIO_CH375_Data);//读数据端口数据,保护高8位
   TempData &= 0xFF00;  //低8位清0
   TempData |= (u16)dat;  //写数据

	delay_us(10);    //
	CS=0;            //
	//delay_us(10);
	A0=0;            //
	//delay_us(10);
	GPIO_Write(GPIO_CH375_Data, TempData); //
	//delay_us(10);
	WR=0;            //
	delay_us(10);
	WR=1;            //
//	delay_us(10);
	CS=1;            //
	//delay_us(10); 
	A0=1;            //
	delay_us(200);   //
}
//读取数据
u8  CH375_RD_DAT( void )
{
   u8 PortData;   
   DATA_MODE_IN;  //

	delay_us(10);   //
	CS=0;           //
//	delay_us(10);
	A0=0;           //
	//delay_us(10);
	RD=0;           //
//	delay_us(10);
	PortData = (u8)( GPIO_ReadInputData(GPIO_CH375_Data) );  //
	delay_us(10);
	RD=1;           //
	//delay_us(10);
	CS=1;           //
	//delay_us(10);
	A0=1;           //
	//delay_us(10);
   return PortData; //
}
//等待中断
u8  WaitInterrupt( void )
{   
		delay_us(10);
		INT=1;      //IO口作输入先置高
		while(INT);   //等待中断,低电平有效
		delay_us(10);
    CH375_WR_CMD( CMD_GET_STATUS );  //产生操作完成中断,获取中断状态,收到GET_STATUS命令到INT#引脚撤消中断最大延时3us
    delay_us(10);
		return( CH375_RD_DAT( ) );
}

写好读写数据命令函数后就是CH375初始化和磁盘初始化:

//CH375芯片初始化,设置CH375为USB主机模式,成功返回0,失败返回1
u8  CH375Init( void )
{
		u8 i;
	  u8	Read_Data=0;
    CH375_WR_CMD( CMD_CHECK_EXIST );  //测试工作状态  
		CH375_WR_DAT( 0x55 );  // 测试数据
    Read_Data = CH375_RD_DAT( );  // 返回的数据应是测试数据取反,如发送0x55,返回0xAA
   if ( Read_Data != 0xaa ) //CH375出错
   {  
     for ( i = 100; i != 0; i -- )
     {  
	    CH375_WR_CMD( CMD_RESET_ALL );  
			 delay_ms(50); //RESET_ALL命令的执行时间最大为40ms
        CH375_WR_CMD( CMD_CHECK_EXIST );  // 测试工作状态
        CH375_WR_DAT( 0x55 );           // 测试数据
        Read_Data = CH375_RD_DAT( );  
        if ( Read_Data == 0xaa )    //读取到的数据是输入数据按位取反
           break;
      }      
    }

     CH375_WR_CMD( CMD_SET_USB_MODE );  // 设置USB工作模式
		 delay_us(30);//设置USB工作模式为等待20us
     CH375_WR_DAT( 6 );  //模式代码,自动检测USB设备连接
     for ( i = 0xff; i != 0; i -- )  // 等待操作成功,通常要等待10uS-20uS //
     {	
			 delay_us(20);
       if ( CH375_RD_DAT( ) == CMD_RET_SUCCESS )   break;  //操作成功,退出循环
     }
     if ( i != 0 ) return( 0 );  // 操作成功,返回0
     else return( 1 );  // CH375初始化出错,如芯片型号出错或处于串口方式或不支持,返回1
}
//磁盘初始化,成功返回0,失败返回1
unsigned char CH375_InitDisk(void)
{ 
 unsigned char status,i,j=0;
//delay_us(100);
 status=WaitInterrupt();
	delay_us(100);
 if(status==USB_INT_DISCONNECT) return 1;  //USB设备断开 

 while(1)
 {
  CH375_WR_CMD(CMD_DISK_INIT);  //初始化USB存储器
	 delay_us(100);
  status=WaitInterrupt();        //等待中断并获取中断状态
	 delay_us(100);
  if(status==USB_INT_SUCCESS) 
   break;
 }

 while(1)	 //以下代码均源自于沁恒的官方优盘初始化函数,借用它可提高对优盘的兼容性
 {   
  j++;
  CH375_WR_CMD(CMD_DISK_SIZE);  //获取优盘容量
	 delay_us(100);
  status=WaitInterrupt();       //等待中断并获取中断状态
	 delay_us(100);
  if(status==USB_INT_SUCCESS) 
   break;
  else 
  {
   //Delay(1000);
		delay_us(100);
   CH375_WR_CMD(CMD_DISK_R_SENSE); //主机方式:检查USB存储器错误
		delay_us(100);
   status=WaitInterrupt();         //等待中断并获取中断状态
		delay_us(100);
   if(status==USB_INT_SUCCESS)            
	continue;                  //初始化成功跳出while(1)
   else 
    return 1;          //初始化失败,返回1
  }
  if(j==5) 
   return 1;     			 //初始化失败,返回1
 }

	
 for(i=0;i!=5;i++)
 {
	 //delay_us(100);
  CH375_WR_CMD( CMD_DISK_READY );     //检查USB存储设备的错误
	 delay_us(100);
  status=WaitInterrupt();             //等待中断并获取中断状态
	 delay_us(100);
  if(status==USB_INT_SUCCESS) 
   return 0;                          //优盘已经成功初始化,返回0
 }	
 return 1;     //优盘初始化失败,返回1
}

后面就是main函数了,测试扇区读写功能:

#define ADDR 100//6600000//100	 //要操作的优盘物理扇区地址 用winhex打开物理磁盘可查看扇区地址数据 

u8 flag1=0;
u8 Write_pbuf[512];   //发送数据缓冲区
u8 Read_pbuf[2048];   //接收数据缓冲区
u8 status=0xff; //初始化状态标志


//注意:单片机要先上电,再插入优盘
 int main(void)
 {
	u16 i=0;	 
	delay_init();	    	 //延时函数初始化	  
	LED_Init();
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 //串口初始化波特率9600	
	printf("串口设置完毕\r\n");
	delay_ms(100); //内部电源上电的复位时间最大为40ms,这里延时防止出现CH375初始化失败
	CH375_GPIO_Init(); //
	CH375_WR_CMD(CMD_GET_IC_VER);  // 获取芯片及固件版本
	status=CH375_RD_DAT();  //  
	printf("芯片版本为:%#x\r\n",status);
	status=CH375Init(); //初始化CH375芯片,成功返回0,失败返回1
	printf("CH375芯片初始化值:%#x\r\n",status);
	CH375_WR_CMD(CMD_DISK_MAX_LUN);  //获取USB存储设备的最大逻辑单元号
	status=CH375_RD_DAT();  // 最大逻辑单元号
	 printf("USB存储设备的最大逻辑单元号为:%#x\r\n",status);
	//status=InitDisk();	 //初始化优盘,成功返回0,失败返回1
//注意:单片机要先上电,再插入优盘
	 status=CH375_InitDisk(); //上电后再插入优盘 金士顿8G优盘 东莞16G 3.0优盘测试通过
	 printf("U盘初始化值:%#x\r\n",status);
	 status=Get_CH375DiskSize();//打印磁盘容量,单位MByte
	for(i=0;i<512;i++)
		Write_pbuf[i]=i;//0x55;//	   //向数据缓冲区中写入0-255 0-255 共512个字节
	printf("向缓冲区中装入完毕\r\n");
	//CH375WriteSector(ADDR,Write_pbuf);//将数据缓冲区中的512个字节数据写入优盘的第ADDR个扇区
	CH375_WriteDisk(Write_pbuf,ADDR,4); //连续写多个扇区
	printf("写U盘扇区完毕\r\n");

	for(i=0;i<2048;i++) //清空接收数据缓冲区
	{
		Read_pbuf[i]=0;
	}
	printf("清空接收缓冲区完毕\r\n");
	//CH375ReadSector(ADDR+1,Read_pbuf);//从优盘的第ADDR个扇区中读取512个字节数据到数据缓冲区
	CH375_ReadDisk(Read_pbuf,ADDR,4);  //连续读取多个扇区数据
	//查看读取到的几个扇区数据,只取一小部分
		for(i=0;i<10;i++)
	{
		printf("读取到的扇区数据为:i=%d   Read_pbuf[i]=%#x\r\n",i,Read_pbuf[i]);
	}
	for(i=520;i<530;i++)
	{
		printf("读取到的扇区数据为:i=%d   Read_pbuf[i]=%#x\r\n",i,Read_pbuf[i]);
	}
		for(i=1030;i<1040;i++)
	{
		printf("读取到的扇区数据为:i=%d   Read_pbuf[i]=%#x\r\n",i,Read_pbuf[i]);
	}
			for(i=1600;i<1610;i++)
	{
		printf("读取到的扇区数据为:i=%d   Read_pbuf[i]=%#x\r\n",i,Read_pbuf[i]);
	}
	printf("读取优盘扇区完毕\r\n");

	for(i=0;i<512;i++) 
	{ 
		if(Write_pbuf[i]!=Read_pbuf[i])  //对读取的数据进行匹配
		{
			flag1=1;   //匹配失败,flag1=1
				break;
		}
	}
	printf("匹配完毕\r\n");

	for(i=0;i<512;i++) //清空发送数据缓冲区
	{
		Write_pbuf[i]=0;
//printf("扇区数据为:%#x\n",Write_pbuf[i]);	 
	}
	
	if(flag1)
	{
		LED=1; //发光LED灭
		printf("优盘扇区读写测试失败\r\n"); //数据不吻合
	}
	else 
	{	 
		LED=0; //发光LED点亮
		printf("优盘扇区读写测试成功\r\n"); //数据吻合
	}
	printf("------------------------------------\r\n");
 while(1){
	}
 }

测试结果如下:

金士顿8G优盘串口内容:

使用winhex打开金士顿8G优盘查看数据和容量如下:

总容量=总扇区数*每扇区字节数=15131636*512=7747397632字节=7388.494140625MByte

之前用程序计算总容量的时候没注意到变量位数,导致计算后的总字节数超过定义的32位变量,输出的结果有误,修改计算过程后计算结果正常了。

到此,用STM32F103RC和CH375模块读写优盘扇区基本实现了,后面就可以用znFAT或FATFS在优盘上读写文件了。

详细例程代码见我的下载https://download.csdn.net/download/u013072995/11223269

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值