历史上的今天
今天是:2024年11月06日(星期三)
2019年11月06日 | PIC单片机USB MSC的应用:用 MMC/SD 卡作为储存设备进行读写
2019-11-06 来源:51hei
单片机的USB接口,通常用法,
1)HID 是Human Interface Device的缩写,由其名称可以了解HID设备是直接与人交互的设备,例如键盘、鼠标与游戏杆等。不过HID设备并不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。
2)CDC 虚拟串口,可与PC机直接联机通讯,如同RS232。
3)USB MSC (Mass Storage class) MSC是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输。设备包括:移动硬盘,移动光驱,U盘,SD、TF等储存卡读卡器,数码相机,手机等等。
..........
注意:
每一个USB设备,都需要一个独立的身份编码 (ID),它由 2 组数字组成,一个是开发商代码(Vender ID),另一个是产品代码(Product ID)。如果是PIC使用者,可以向Microchip公司申请获得免费的身份编码。
USB MSC 的应用与前面介绍的USB CDC 和 USB HID 相比较,USB MSC 的内容比较多,需要多花一些时间。
以下介绍一个简单的从USB接口对 MMC/SD 卡进行读/写数据的简单测试程序。希望大家能够喜欢。
让PC认为 MMC/SD 卡作为储存设备 (Storage) 进行运作
主程序:
/*
* Project name:
MassStorageDevice.vtft
* Generated by:
Visual TFT
* Description:
Example using EasyPIC Fusion v7 board as mass storage device. Before using it, insert microSD card
in the card slot on EasyPIC Fusion v7 board and plug usb cable to connect with PC.
After connection with PC, mikromedia is detected as mass storage device wich size is
size of microSD card inserted.
* Test configuration:
MCU: P18F87J50
Dev.Board: MikroMMB_for_PIC18FJ_hw_rev_1.10_9A
http://www.mikroe.com/mikromedia/pic18fj/
Oscillator: HS-PLL, 48.000MHz
SW: mikroC PRO for PIC
http://www.mikroe.com/mikroc/pic/
*/
#include "__Lib_USB_Device.h"
// MMC module connections
sbit Mmc_Chip_Select at LATD0_bit; // for writing to output pin always use latch
sbit Mmc_Chip_Select_Direction at TRISD0_bit;
// eof MMC module connections
void interrupt(){
USBDev_IntHandler();
}
void main() {
PLLEN_bit = 1;
Delay_ms(150);
WDTCON.B4 = 1;
ANCON0 = 0xF0; // All pins to digital
ANCON1 = 0xFF;
WDTCON.B4 = 0;
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
USBDev_MSCInit();
USBDev_Init();
IPEN_bit = 1;
USBIP_bit = 1;
USBIE_bit = 1;
GIEH_bit = 1;
while(1){
USBDev_MSCMain();
}
}
复制代码
MMC/SD卡驱动程序:
#include // Mode sense data static const uint8_t MODE_SENSE_6_DATA[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Standard Inquiry Data static const uint8_t STD_INQUIRY_DATA[36] = { 0x00, // Direct access block device 0x80, // RMB bit set to one indicates that the medium is removable 0x00, // ISO(7..6) ECMA(5..3) ANSI(2..0) Version 0x02, // Response Data Format 0x1F, // Additional length (31) 0x00, // Reserved 0x00, // Reserved 0x00, // Reserved 'M', 'I', 'K', 'R', 'O', 'E', ' ', ' ', // Vendor Information 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product identification 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', '1', '.', '0', '0' // Product Revision Level n.nn }; // USB Mass storage Page 0 Inquiry Data static const uint8_t UNIT_SERIAL_NUMBER[7] = { 0x00, // Peripheral qualifier[7..5] device type[4..0] 0x80, // Page Code 80h 0x00, // Reserved 0x03, // Page Length 0x00, // Product Serial Nnumber 0x00, 0x00 }; static uint8_t tmpStorageBuff[36]; // Storage callbacks static uint8_t StorageInit(); static uint8_t StorageIsReady(); static uint8_t StorageIsWriteProtected(); static uint8_t StorageGetCapacity(uint32_t* blockNum, uint32_t *blockSize); static uint8_t StorageRead(uint8_t *buffer, uint32_t lba, uint16_t blockNum); static uint8_t StorageWrite(uint8_t *buffer, uint32_t lba, uint16_t blockNum); static uint8_t* StorageGetInquiryData(uint8_t vpd); static uint8_t* StorageGetStdInquiryData(); static uint8_t* StorageGetModeSenseData(); typedef struct { uint8_t(*StorageInit)(); uint8_t(*StorageIsReady)(); uint8_t(*StorageIsWriteProtected)(); uint8_t(*StorageGetCapacity)(uint32_t *blockNum, uint32_t * blockSize); uint8_t(*StorageRead) (uint8_t *buffer, uint32_t lba, uint16_t blockNum); uint8_t(*StorageWrite)(uint8_t *buffer, uint32_t lba, uint16_t blockNum); uint8_t * (*StorageGetInquiryData)(uint8_t vpd); uint8_t * (*StorageGetStdInquiryData)(); uint8_t * (*StorageGetModeSenseData)(); } TMSCStorageCB; TMSCStorageCB USBDev_MSCStorageCB = { StorageInit, StorageIsReady, StorageIsWriteProtected, StorageGetCapacity, StorageRead, StorageWrite, StorageGetInquiryData, StorageGetStdInquiryData, StorageGetModeSenseData }; // STORAGE IMPLEMENTATION static void StorageConstToRam(const uint8_t* fromBuffer, uint8_t* toBuffer, uint16_t len){ uint16_t i; for(i = 0; i < len; i++){ toBuffer[i] = fromBuffer[i]; } } //////////////////////////////////////////////////////////////////////////////// // This is a wrapper for retrieving number of sector device implements. // It is used to get sector count of the device (for fat formatting purpose, // assumed sector size is 512 bytes). // MMC GetMmcSectorCount return codes static const uint8_t MMC_OK = 0, MMC_ERROR = 255; static uint8_t GetMmcSectorCount(uint32_t *scCnt) { uint8_t csdbuf[16]; uint16_t c_size, c_size_mult, mult, read_bl_len, block_len; uint32_t size, blocknr; // determine MMC/SD card size in MB if (Mmc_Read_Csd(csdbuf) != MMC_OK) { return MMC_ERROR; } // is it version 2.0? if (1 == ((csdbuf[0] & 0xC0) >> 6)) { size = 0; size <<= 8; size += csdbuf[7] & 0x3F; size <<= 8; size += csdbuf[8]; size <<= 8; size += csdbuf[9]; size <<= 0; // size is in 0.5MB, get size in sectors (assumed 512 bytes sector size) size *= 1024; } // if not, it's version 1.xx else { c_size = ((csdbuf[8] & 0xC0) >> 6) + ((unsigned) csdbuf[7] << 2) + (((unsigned) csdbuf[6] & 0x03) << 10); c_size_mult = (csdbuf[10] & 0x80) + (((unsigned) csdbuf[9] & 0x03) << 8); c_size_mult = c_size_mult >> 7; read_bl_len = csdbuf[5] & 0x0f; mult = 1; mult = mult << (c_size_mult + 2); blocknr = (c_size + 1) * (long) mult; block_len = 1; block_len = block_len << read_bl_len; size = block_len * blocknr; // size is in 1B, get size in sectors (assumed 512 bytes sector size) size /= 512; } *scCnt = size; return MMC_OK; } static uint8_t storageInitStatus; // storage initializtion status // Initializing storage static uint8_t StorageInit() { // initialize a MMC card storageInitStatus = Mmc_Init(); return storageInitStatus; } // Get storage capacity, number of blocks and block size static uint8_t StorageGetCapacity(uint32_t* blockNum, uint32_t *blockSize) { GetMmcSectorCount(blockNum); *blockSize = 512; return 0; } // Read storage to buffer static uint8_t StorageRead(uint8_t *buffer, uint32_t lba, uint16_t blockNum) { uint8_t status; status = 0; Mmc_Multi_Read_Start(lba); while (blockNum) { Mmc_Multi_Read_Sector(buffer); buffer += 512; blockNum--; } Mmc_Multi_Read_Stop(); return status; } // Return storage status static uint8_t StorageIsReady() { if(storageInitStatus) return 0; // storage is not ready else return 1; // storage is ready } // Write to storage static uint8_t StorageWrite(uint8_t *buffer, uint32_t lba, uint16_t blockNum) { uint8_t status; status = 0; while (blockNum) { status |= Mmc_Write_Sector(lba, buffer); lba++; buffer += 512; blockNum--; } return status; } // Get storage protection status static uint8_t StorageIsWriteProtected() { return 0; } // Return storage inquiry data static uint8_t* StorageGetInquiryData(uint8_t vpd) { StorageConstToRam(UNIT_SERIAL_NUMBER, tmpStorageBuff, 7); return tmpStorageBuff; } // Get standard inquiry data static uint8_t* StorageGetStdInquiryData() { StorageConstToRam(STD_INQUIRY_DATA, tmpStorageBuff, 36); return tmpStorageBuff;
史海拾趣
|
一、 闭路监视电视系统简介: CCTV系统结构: 电视监控系统(Closed Circuit Television,简称CCTV),一般由以下三部分组成: 前端部分: 主要由黑白(彩色)摄像机、镜头、云台、防 ...… 查看全部问答> |
|
高人可以帮我看下我的这个拨码开关程序老有点小我问题,,十万火急 process(clk_a) VARIABLE cnt_a : std_logic_vector(7 downto 0):=\"11111111\"; begin if (clk_a\'event and clk_a=\'1\') then if cnt_a=\"11111111\" then cnt_a:=d; full_a… 查看全部问答> |
|
Altium Designer 使用 —— 快速制作原理图封装当制作引脚数比较多的器件的原理图封装时,可以使用AD提供的“smart grid insert”功能快速制作原理图封装库。本文以制作K9F1G08为例,进行简单说明。K9F1G08的引脚分布如图1所示:1. 打开 excel ,按 ...… 查看全部问答> |
|
新建一个wince 的mfc exe,怎么在对话框中添加一个ie控件,浏览一个url(本地页面),thanks 新建的时候,选择,WCE MFC appWizard[exe] ,然后再选择Dialog base, 怎么样在该Dialog上添加一个ie控件,然后去浏览一个本地url? thanks… 查看全部问答> |
|
本人从朋友那里得到一份cadence(allegro)视频教程15.5板本,是一个培训班的内部视频讲义,清晰度很高,很具体详细,是自学的好资料。如果您没时间看书或者想很快学会allegro的话就请联系:13783696474 或者QQ:20247125 ...… 查看全部问答> |
|
1.最近我用sci调试RS485的时候遇到一个怪现象: 有时候(不是全部,重新加载程序的时候一般都是)cpu明明有数据发出来,SCIRX,SCITX波形正常,可是485驱动芯片出来的两线信号发不出来,示波器只能看到负半波.只要我把与其通信的人机界面的通讯口拔出来 ...… 查看全部问答> |
|
最近在学习FPGA方面知识,对时钟触发有了了解,但有好多问题有些不明白。希望大虾解释 如: always(posedge CLK) begin //执行任务块 end 假如时钟的周期为50nS,占空比50%;所执行的任务块比较耗时间,超过50nS,而此时任务块尚未完全执行完 ...… 查看全部问答> |




