استفاده از پورت USB کاربرد فراوانای در مدارات امبدد دارد . در میکروکنترلر های جدید به طور معمول از ارتیاط USB پشتیبانی می شود . یک ارتباط USB شامل یک لایه سخت افزاری که همان کانکتور USB و سطح منطقی صفر و یک های انتقالی و… است ، ویک لایه نرم افزاری که شامل چندین مد کاری است می باشد . به طور مثال در مد CDC پورت USB دستگاه همانند یک مبدل USB-TTL عمل خواهد کرد یا در مد HID می توانید فرمان های HID را جهت کنترل کامپیوتر ارسال کنید فرمان هایی مانند کنترل موس و کیبورد . در پیاده سازی یک ارتباط USB به صورت نرم افزاری علاوه بر پیکر بندی های پیچیده ممکن است به فرکانس های خاصی نیاز داشته باشید . از این رو در استفاده از USB در میکروکنترلر هایی که قابلیت USB را ندارند می توان از چیپ های واسط استفاده کرد . ماژول USB-Host یکی از این واسط های USB می باشد که بر پایه چیپCH376S است . با استفاده از این ماژول به راحتی می توانید فلش های USB یا موس و کیبورد را به آردوینو متصل کنید . این ماژول قابلت ارتباط SPI و UART را دارد .
مشخصات ماژول CH376S :
- پشتیبانی از USB 2.0
- پشتیبانی از پروتکل UART تا سرعت 3Mpbs
- پشتیبانی از ارتباط پارالل تا 2Mpbs
- پشتیبانی از پروتکل SPI تا 2Mpbs
- عملکرد در دو مد USB Host و USB Device
- تامین جریان خروجی تا 800 میلی آمپر
- تغییر مد کاری به صورت اتومات
- پشتیبانی از FAT16 و FAT32 و FAT12
راه اندازی ماژول CH376S :
می توان از طریق رابط های SPI ، UART و یا ارتباط 8 بیتی موازی با این ماژول ارتباط برقرار کرد . در اینجا تنها به شرح ارتباط سریال می پردازیم . در ارتباط UART با ارسال کاراکتر های دستوری که در داخل دیتاشیت ماژول هستند ، می توان ماژول را کنترل کرد.جدول زیر شامل برخی از دستورات کنترلی است :
راه اندازی ماژول CH376S با آردوینو :
برنامه زیر شامل کلیه توابع کار با این ماژول می باشد .
#include <SoftwareSerial.h> byte computerByte; //used to store data coming from the computer byte USB_Byte; //used to store data coming from the USB stick int LED = 13; //the LED is connected to digital pin 13 int timeOut = 2000; //TimeOut is 2 seconds. This is the amount of time you wish to wait for a response from the CH376S module. String wrData = "What is the meaning of life ?"; //We will write this data to a newly created file. String wrData2 = "42"; //We will append this data to an already existing file. SoftwareSerial USB(10, 11); // Digital pin 10 on Arduino (RX) connects to TXD on the CH376S module // Digital pin 11 on Arduino (TX) connects to RXD on the CH376S module // GND on Arduino to GND on CH376S module // 5V on Arduino to 5V on CH376S module //============================================================================================================================================== void setup() { Serial.begin(9600); // Setup serial communication with the computer (using a baud rate of 9600 on serial monitor) USB.begin(9600); // Setup serial communication with the CH376S module (using the default baud rate of 9600) pinMode(LED,OUTPUT); // Define digital pin 13 as an OUTPUT pin - so that we can use it with an LED digitalWrite(LED,LOW); // Turn off the LED } void loop() { if(Serial.available()){ computerByte = Serial.read(); //read any incoming bytes from the Serial monitor, and store this byte in the variable called computerByte if(computerByte==49){ //1 //If you send the number 1 from the serial monitor, the arduino will read it as digital number 49. Google "ascii table" for more info. printCommandHeader("COMMAND1: CHECK CONNECTION"); checkConnection(0x01); // Check for successful connection and communication with the CH376S module. } if(computerByte==50){ //2 printCommandHeader("COMMAND2: set_USB_Mode"); set_USB_Mode(0x06); // Code used to enable read/write communication and monitoring of the USB stick } if(computerByte==51){ //3 printCommandHeader("COMMAND3: resetALL"); resetALL(); // Reset the USB device } if(computerByte==52){ //4 printCommandHeader("COMMAND4: Create and Write to File : TEST4.TXT"); writeFile("TEST4.TXT", wrData); // Create a file called TEST4.TXT and then Write the contents of wrData to this file } if(computerByte==53){ //5 printCommandHeader("COMMAND5: Read File: TEST4.TXT"); readFile("TEST4.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor } if(computerByte==54){ //6 printCommandHeader("COMMAND6: Append data to file: TEST4.TXT"); appendFile("TEST4.TXT", wrData2); // Append data to the end of the file. } if(computerByte==55){ //7 printCommandHeader("COMMAND7: Delete File: TEST4.TXT"); fileDelete("TEST4.TXT"); // Delete the file named TEST4.TXT } if(computerByte==56){ //8 printCommandHeader("COMMAND8: Read File: TEST2.TXT"); readFile("TEST2.TXT"); // Read the contents of the TEST2.TXT file on the USB disk, and display contents in the Serial Monitor } if(computerByte==57){ //9 printCommandHeader("COMMAND9: Read File: TEST3.TXT"); readFile("TEST3.TXT"); // Read the contents of the TEST3.TXT file on the USB disk, and display contents in the Serial Monitor } } if(USB.available()){ // This is here to capture any unexpected data transmitted by the CH376S module Serial.print("CH376S has just sent this code:"); Serial.println(USB.read(), HEX); } } //END OF LOOP FUNCTION ======================================================================================================================================== //print Command header void printCommandHeader(String header){ Serial.println("======================"); Serial.println(""); Serial.println(header); Serial.println("----------------------"); } //checkConnection================================================================================== //This function is used to check for successful communication with the CH376S module. This is not dependant of the presence of a USB stick. //Send any value between 0 to 255, and the CH376S module will return a number = 255 - value. void checkConnection(byte value){ USB.write(0x57); USB.write(0xAB); USB.write(0x06); USB.write(value); if(waitForResponse("checking connection")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==(255-value)){ Serial.println(">Connection to CH376S was successful."); blinkLED(); //blink the LED for 1 second if the connection was successful } else { Serial.print(">Connection to CH376S - FAILED."); } } } //set_USB_Mode===================================================================================== //Make sure that the USB is inserted when using 0x06 as the value in this specific code sequence void set_USB_Mode (byte value){ USB.write(0x57); USB.write(0xAB); USB.write(0x15); USB.write(value); delay(20); if(USB.available()){ USB_Byte=USB.read(); //Check to see if the command has been successfully transmitted and acknowledged. if(USB_Byte==0x51){ // If true - the CH376S has acknowledged the command. Serial.println("set_USB_Mode command acknowledged"); //The CH376S will now check and monitor the USB port USB_Byte = USB.read(); //Check to see if the USB stick is connected or not. if(USB_Byte==0x15){ // If true - there is a USB stick connected Serial.println("USB is present"); blinkLED(); // If the process was successful, then turn the LED on for 1 second } else { Serial.print("USB Not present. Error code:"); // If the USB is not connected - it should return an Error code = FFH Serial.print(USB_Byte, HEX); Serial.println("H"); } } else { Serial.print("CH3765 error! Error code:"); Serial.print(USB_Byte, HEX); Serial.println("H"); } } delay(20); } //resetALL========================================================================================= //This will perform a hardware reset of the CH376S module - which usually takes about 35 msecs ===== void resetALL(){ USB.write(0x57); USB.write(0xAB); USB.write(0x05); Serial.println("The CH376S module has been reset !"); delay(200); } //readFile===================================================================================== //This will send a series of commands to read data from a specific file (defined by fileName) void readFile(String fileName){ resetALL(); //Reset the module set_USB_Mode(0x06); //Set to USB Mode diskConnectionStatus(); //Check that communication with the USB device is possible USBdiskMount(); //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations. setFileName(fileName); //Set File name fileOpen(); //Open the file for reading int fs = getFileSize(); //Get the size of the file fileRead(); //***** Send the command to read the file *** fileClose(0x00); //Close the file } //writeFile======================================================================================== //is used to create a new file and then write data to that file. "fileName" is a variable used to hold the name of the file (e.g TEST.TXT). "data" should not be greater than 255 bytes long. void writeFile(String fileName, String data){ resetALL(); //Reset the module set_USB_Mode(0x06); //Set to USB Mode diskConnectionStatus(); //Check that communication with the USB device is possible USBdiskMount(); //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations. setFileName(fileName); //Set File name if(fileCreate()){ //Try to create a new file. If file creation is successful fileWrite(data); //write data to the file. } else { Serial.println("File could not be created, or it already exists"); } fileClose(0x01); } //appendFile()==================================================================================== //is used to write data to the end of the file, without erasing the contents of the file. void appendFile(String fileName, String data){ resetALL(); //Reset the module set_USB_Mode(0x06); //Set to USB Mode diskConnectionStatus(); //Check that communication with the USB device is possible USBdiskMount(); //Prepare the USB for reading/writing - you need to mount the USB disk for proper read/write operations. setFileName(fileName); //Set File name fileOpen(); //Open the file filePointer(false); //filePointer(false) is to set the pointer at the end of the file. filePointer(true) will set the pointer to the beginning. fileWrite(data); //Write data to the end of the file fileClose(0x01); //Close the file using 0x01 - which means to update the size of the file on close. } //setFileName====================================================================================== //This sets the name of the file to work with void setFileName(String fileName){ Serial.print("Setting filename to:"); Serial.println(fileName); USB.write(0x57); USB.write(0xAB); USB.write(0x2F); USB.write(0x2F); // Every filename must have this byte to indicate the start of the file name. USB.print(fileName); // "fileName" is a variable that holds the name of the file. eg. TEST.TXT USB.write((byte)0x00); // you need to cast as a byte - otherwise it will not compile. The null byte indicates the end of the file name. delay(20); } //diskConnectionStatus================================================================================ //Check the disk connection status void diskConnectionStatus(){ Serial.println("Checking USB disk connection status"); USB.write(0x57); USB.write(0xAB); USB.write(0x30); if(waitForResponse("Connecting to USB disk")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful Serial.println(">Connection to USB OK"); } else { Serial.print(">Connection to USB - FAILED."); } } } //USBdiskMount======================================================================================== //initialise the USB disk and check that it is ready - this process is required if you want to find the manufacturing information of the USB disk void USBdiskMount(){ Serial.println("Mounting USB disk"); USB.write(0x57); USB.write(0xAB); USB.write(0x31); if(waitForResponse("mounting USB disk")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful Serial.println(">USB Mounted - OK"); } else { Serial.print(">Failed to Mount USB disk."); } } } //fileOpen======================================================================================== //opens the file for reading or writing void fileOpen(){ Serial.println("Opening file."); USB.write(0x57); USB.write(0xAB); USB.write(0x32); if(waitForResponse("file Open")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful Serial.println(">File opened successfully."); } else { Serial.print(">Failed to open file."); } } } //setByteRead===================================================================================== //This function is required if you want to read data from the file. boolean setByteRead(byte numBytes){ boolean bytesToRead=false; int timeCounter = 0; USB.write(0x57); USB.write(0xAB); USB.write(0x3A); USB.write((byte)numBytes); //tells the CH376S how many bytes to read at a time USB.write((byte)0x00); if(waitForResponse("setByteRead")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==0x1D){ //read the CH376S message. If equal to 0x1D, data is present, so return true. Will return 0x14 if no data is present. bytesToRead=true; } } return(bytesToRead); } //getFileSize()=================================================================================== //writes the file size to the serial Monitor. int getFileSize(){ int fileSize=0; Serial.println("Getting File Size"); USB.write(0x57); USB.write(0xAB); USB.write(0x0C); USB.write(0x68); delay(100); Serial.print("FileSize ="); if(USB.available()){ fileSize = fileSize + USB.read(); } if(USB.available()){ fileSize = fileSize + (USB.read()*255); } if(USB.available()){ fileSize = fileSize + (USB.read()*255*255); } if(USB.available()){ fileSize = fileSize + (USB.read()*255*255*255); } Serial.println(fileSize); delay(10); return(fileSize); } //fileRead======================================================================================== //read the contents of the file void fileRead(){ Serial.println("Reading file:"); byte firstByte = 0x00; //Variable to hold the firstByte from every transmission. Can be used as a checkSum if required. byte numBytes = 0x40; //The maximum value is 0x40 = 64 bytes while(setByteRead(numBytes)){ //This tells the CH376S module how many bytes to read on the next reading step. In this example, we will read 0x10 bytes at a time. Returns true if there are bytes to read, false if there are no more bytes to read. USB.write(0x57); USB.write(0xAB); USB.write(0x27); //Command to read ALL of the bytes (allocated by setByteRead(x)) if(waitForResponse("reading data")){ //Wait for the CH376S module to return data. TimeOut will return false. If data is being transmitted, it will return true. firstByte=USB.read(); //Read the first byte while(USB.available()){ Serial.write(USB.read()); //Send the data from the USB disk to the Serial monitor delay(1); //This delay is necessary for successful Serial transmission } } if(!continueRead()){ //prepares the module for further reading. If false, stop reading. break; //You need the continueRead() method if the data to be read from the USB device is greater than numBytes. } } Serial.println(); Serial.println("NO MORE DATA"); } //fileWrite======================================================================================= //are the commands used to write to the file void fileWrite(String data){ Serial.println("Writing to file:"); byte dataLength = (byte) data.length(); // This variable holds the length of the data to be written (in bytes) Serial.println(data); Serial.print("Data Length:"); Serial.println(dataLength); delay(100); // This set of commands tells the CH376S module how many bytes to expect from the Arduino. (defined by the "dataLength" variable) USB.write(0x57); USB.write(0xAB); USB.write(0x3C); USB.write((byte) dataLength); USB.write((byte) 0x00); if(waitForResponse("setting data Length")){ // Wait for an acknowledgement from the CH376S module before trying to send data to it if(getResponseFromUSB()==0x1E){ // 0x1E indicates that the USB device is in write mode. USB.write(0x57); USB.write(0xAB); USB.write(0x2D); USB.print(data); // write the data to the file if(waitForResponse("writing data to file")){ // wait for an acknowledgement from the CH376S module } Serial.print("Write code (normally FF and 14): "); Serial.print(USB.read(),HEX); // code is normally 0xFF Serial.print(","); USB.write(0x57); USB.write(0xAB); USB.write(0x3D); // This is used to update the file size. Not sure if this is necessary for successful writing. if(waitForResponse("updating file size")){ // wait for an acknowledgement from the CH376S module } Serial.println(USB.read(),HEX); //code is normally 0x14 } } } //continueRead()================================================================================== //continue to read the file : I could not get this function to work as intended. boolean continueRead(){ boolean readAgain = false; USB.write(0x57); USB.write(0xAB); USB.write(0x3B); if(waitForResponse("continueRead")){ //wait for a response from the CH376S. If CH376S responds, it will be true. If it times out, it will be false. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful readAgain=true; } } return(readAgain); } //fileCreate()======================================================================================== //the command sequence to create a file boolean fileCreate(){ boolean createdFile = false; USB.write(0x57); USB.write(0xAB); USB.write(0x34); if(waitForResponse("creating file")){ //wait for a response from the CH376S. If file has been created successfully, it will return true. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful createdFile=true; } } return(createdFile); } //fileDelete()======================================================================================== //the command sequence to delete a file void fileDelete(String fileName){ setFileName(fileName); delay(20); USB.write(0x57); USB.write(0xAB); USB.write(0x35); if(waitForResponse("deleting file")){ //wait for a response from the CH376S. If file has been created successfully, it will return true. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful Serial.println("Successfully deleted file"); } } } //filePointer======================================================================================== //is used to set the file pointer position. true for beginning of file, false for the end of the file. void filePointer(boolean fileBeginning){ USB.write(0x57); USB.write(0xAB); USB.write(0x39); if(fileBeginning){ USB.write((byte)0x00); //beginning of file USB.write((byte)0x00); USB.write((byte)0x00); USB.write((byte)0x00); } else { USB.write((byte)0xFF); //end of file USB.write((byte)0xFF); USB.write((byte)0xFF); USB.write((byte)0xFF); } if(waitForResponse("setting file pointer")){ //wait for a response from the CH376S. if(getResponseFromUSB()==0x14){ //CH376S will send 0x14 if this command was successful Serial.println("Pointer successfully applied"); } } } //fileClose======================================================================================= //closes the file void fileClose(byte closeCmd){ Serial.println("Closing file:"); USB.write(0x57); USB.write(0xAB); USB.write(0x36); USB.write((byte)closeCmd); // closeCmd = 0x00 = close without updating file Size, 0x01 = close and update file Size if(waitForResponse("closing file")){ // wait for a response from the CH376S. byte resp = getResponseFromUSB(); if(resp==0x14){ // CH376S will send 0x14 if this command was successful Serial.println(">File closed successfully."); } else { Serial.print(">Failed to close file. Error code:"); Serial.println(resp, HEX); } } } //waitForResponse=================================================================================== //is used to wait for a response from USB. Returns true when bytes become available, false if it times out. boolean waitForResponse(String errorMsg){ boolean bytesAvailable = true; int counter=0; while(!USB.available()){ //wait for CH376S to verify command delay(1); counter++; if(counter>timeOut){ Serial.print("TimeOut waiting for response: Error while: "); Serial.println(errorMsg); bytesAvailable = false; break; } } delay(1); return(bytesAvailable); } //getResponseFromUSB================================================================================ //is used to get any error codes or messages from the CH376S module (in response to certain commands) byte getResponseFromUSB(){ byte response = byte(0x00); if (USB.available()){ response = USB.read(); } return(response); } //blinkLED========================================================================================== //Turn an LED on for 1 second void blinkLED(){ digitalWrite(LED, HIGH); delay(1000); digitalWrite(LED,LOW); }