之前做毕设买了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("串口设置完毕rn");
delay_ms(100); //内部电源上电的复位时间最大为40ms,这里延时防止出现CH375初始化失败
CH375_GPIO_Init(); //
CH375_WR_CMD(CMD_GET_IC_VER); // 获取芯片及固件版本
status=CH375_RD_DAT(); //
printf("芯片版本为:%#xrn",status);
status=CH375Init(); //初始化CH375芯片,成功返回0,失败返回1
printf("CH375芯片初始化值:%#xrn",status);
CH375_WR_CMD(CMD_DISK_MAX_LUN); //获取USB存储设备的最大逻辑单元号
status=CH375_RD_DAT(); // 最大逻辑单元号
printf("USB存储设备的最大逻辑单元号为:%#xrn",status);
//status=InitDisk(); //初始化优盘,成功返回0,失败返回1
//注意:单片机要先上电,再插入优盘
status=CH375_InitDisk(); //上电后再插入优盘 金士顿8G优盘 东莞16G 3.0优盘测试通过
printf("U盘初始化值:%#xrn",status);
status=Get_CH375DiskSize();//打印磁盘容量,单位MByte
for(i=0;i<512;i++)
Write_pbuf[i]=i;//0x55;// //向数据缓冲区中写入0-255 0-255 共512个字节
printf("向缓冲区中装入完毕rn");
//CH375WriteSector(ADDR,Write_pbuf);//将数据缓冲区中的512个字节数据写入优盘的第ADDR个扇区
CH375_WriteDisk(Write_pbuf,ADDR,4); //连续写多个扇区
printf("写U盘扇区完毕rn");
for(i=0;i<2048;i++) //清空接收数据缓冲区
{
Read_pbuf[i]=0;
}
printf("清空接收缓冲区完毕rn");
//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]=%#xrn",i,Read_pbuf[i]);
}
for(i=520;i<530;i++)
{
printf("读取到的扇区数据为:i=%d Read_pbuf[i]=%#xrn",i,Read_pbuf[i]);
上一篇:STM32单片机(3) 串口中断通信
下一篇:stm32f103+znfat+ch375+vs1003实现简单mp3播放器功能
设计资源 培训 开发板 精华推荐
- PCF2129AT TCXO 的计时、CLKOUT 应用
- DC1620A-P,LTC2142-12 演示板,12 位 65 Msps 双路 ADC,DDR LVDS 输出,5-140MHz
- #第八届立创电赛#瑞萨时钟
- Ap7176B 3A 超低压差线性稳压器的典型应用
- MAXREFDES72#:适用于ARDUINO平台的PMOD适配器
- AD8054AR-EBZ,评估板采用 AD8054AR 四路高速运算放大器,采用 14 引脚 SOIC 封装
- 输出功率60W(12V-5A)的开关电源设计
- BGU7042评估板适用于带旁路功能的机顶盒低噪声放大器
- 2018电赛A题-电流信号检测装置(杭州电子科技大学)
- 使用 Analog Devices 的 LT8570EMS8E-1 的参考设计
- 【免费申请】英飞凌PSoC 62S4 先锋套件 (CY8CKIT-062S4)
- 有奖活动|TE无线连接,释放物联网无限潜能!
- TI 样片免费申请,晒样片赢好礼☞2
- 下载有礼:ADI公司生化分析仪解决方案!
- 5G来袭 TE Connectivity 助你抢占消费电子市场先机
- 有奖直播|使用 ModusToolbox® 构建系统,灵活应对物联网设计挑战
- Microchip最新SAM 以及 PIC32单片机软件开发平台-- MPLAB® Harmony V3介绍 ”
- 有奖直播:助力AI算力,下一代GPU服务器中卡缘高速互连解决方案哪里找?
- 下载有礼:2017年泰克亚太专家大讲堂第四期: 如何应对新型半导体材料表征测试挑战
- 报名赢京东卡:安路FPGA研讨会-成都站