Step 1: Build the circuit
I bought a small honeycomb board and an SD slot, and soldered them according to the standard circuit. Since the SPI mode is used, you must be careful when choosing the circuit diagram. Don't make a mistake in the pin order on the SD card, 912345678. The last two are very close together, so don't connect them when soldering. The relevant pins must be connected to a 47K pull-up resistor as required. Although the circuit is simple, you must ensure that it is correct. Another point is that there are different types of SD card holders. A senior bought a spring-type one. After soldering, the initialization was successful at the beginning, but it suddenly stopped working after a few days. After checking the pins, there was no problem. Finally, it was found that it was a problem with the card holder. Such hardware problems are difficult to find and waste time, so it is better to buy a simple card holder.
Step 2: Set up the hardware SPI
I use sililab's C8051F020, which comes with hardware SPI. If it doesn't come with hardware SPI, you can use software to simulate it. There are many ready-made programs on the Internet for software simulation of SPI. In this step, I first wrote a program according to the 020 manual. Of course, it is set to master mode. At this time, CONFIG (this software can operate most registers of C8051F in a windowed manner and automatically generate code) will allocate 4 pins, CLK clock bit, MISO and MOSI two data transmission bits, and an NSS bit. This pin is not used. Don't use it as a CS chip select bit. Just select a normal IO for the CS bit. All pins output from the microcontroller are set to push-pull output. After the setting is completed, it is best to get an oscilloscope to see if the output waveform is the same as you imagined, so that you can ensure that your SPI is working properly. This step is also critical. SPI is the basis of underlying communication.
Step 3: Initialize the SD card
This step officially enters the MCU debugging SD part. After understanding the timing of the SD card (I will upload this part of the information later), there are many different opinions on the Internet, and some people say that you need to read the 178-page English PDF. I am dizzy. I guess I am an expert after reading this. There are many opinions about the initialization command. I sent CMD0 and CMD1 to successfully initialize.
Explain the meaning of this command format: This is a one-byte command format of 01xx xxxx. The last six digits are the binary value of the number following CMD, such as CMD1=0100 0001=0x41. It is written as CMD | 0x40 in the program. CMD represents the number following it.
It should be noted that the SPI rate cannot exceed 400K during initialization. I set it to 100K and there was no problem with initialization. Also, at least 74 clock cycles must be sent to the SD card before sending CMD0. Only CMD0 needs to be special.
The following is the program segment for sending CMD0:
retry=0;
CSH;
do{
for(i=0;i<10;i++) SPI_WriteByte(0xFF); // Send at least 74 clock cycles Note that the chip select line is high at this time
r1=mmcSendCommand(MMC_GO_IDLE_STATE, 0); // Send CMD0, note that the chip select line is low at this time
retry++;
if(retry>0xfe) return -1; // The number of attempts to send can be appropriately more
} while(r1 != MMC_R1_IDLE_STATE); // The correct response is 1
Try to send at least 200 times. Some people suggest 2000. It doesn't matter. If it is unstable, such as sometimes it can be received and sometimes it can't, you can increase the number of sending times appropriately.
This is the CMD1 program segment sent immediately afterwards:
retry=0;
do{
r1=mmcSendCommand(MMC_SEND_OP_COND, 0); //Send CMD1
retry++;
if(retry>100) return -1;
} while(r1!=0); //Correct response is 0
Initialization can be completed with these two, and some programs will also add
mmcSendCommand(MMC_CRC_ON_OFF, 0); // Turn off CRC check
mmcSendCommand(MMC_SET_BLOCKLEN, 512); //Set the block length to 512 bytes
This is irrelevant. There is no CRC check by default in SPI mode, and the number of bytes per block is 512. Don't change the block size. If you set it to another size, there will be trouble when adding FAT later.
The following explains the uint8_t mmcCommand(uint8_t cmd, uint32_t arg) function in the above program
uint8_t mmcCommand(uint8_t cmd, uint32_t arg)
{
uint8_t r1,retry=0;
SPI_WriteByte(cmd|0x40); // send command
SPI_WriteByte(arg>>24);
SPI_WriteByte(arg>>16);
SPI_WriteByte(arg>>8);
SPI_WriteByte(arg);
SPI_WriteByte( 0x95); //Explanation mark (1)
SPI_WriteByte(0xFF);//Explanation mark (2)
while((r1=SPI_WriteByte(0xFF))==0xFF)if(retry++>8)break;
return r1;
}
The arg parameter is a command attribute, usually 0.
Explanation Marking (1)
The CRC bit 0x95 is only meaningful for CMD0. This bit can be any value when sending other commands, so it does not need to be modified.
Explanation Marking (2)
This is easy to ignore. If you don't ignore the first byte, you may not receive the correct response. In many programs, this is called dummy values. Pay special attention to the timing diagram. In the program that writes the command later, two bytes are sent. Don't confuse this.
Write command program segment:
uint8_t mmcWrite(uint32_t sector, uint8_t* buffer){
uint8_t r1;
uint16_t i;
CSL; // assert chip select
r1 = mmcCommand(MMC_WRITE_BLOCK,sector<<9); // issue command
if(r1 != 0)return r1;
SPI_WriteByte(0xFF); // send dummy
SPI_WriteByte(MMC_STARTBLOCK_WRITE); // send da
for(i=0; i<512; i++){
SPI_WriteByte(*buffer++); // write da
}
SPI_WriteByte(0xFF); // write 16-bit CRC (dummy values) See clearly! Two bytes!
SPI_WriteByte(0xFF);
r1 = SPI_WriteByte(0xFF); // read da
if((r1&MMC_DR_MASK)!=MMC_DR_ACCEPT)return r1; //Explain token (1)
while(!SPI_WriteByte(0xFF)); // wait until card not busy
CSH; // release chip select
return 0;
}
Explanation Marking (1)
This is so important!!! I wasted a week on this!!!
Many programs including most of the information on the Internet say that the response is 0x05, but I never receive this response. What I receive is 0xE5. I thought there was something wrong with the program, but it was not. I checked the information and found the meaning of the 8 bits of this response token. I found that the upper three bits are reserved bits, and the lower five bits of 0xE5 and 0x05 are the same, which means the response is correct. The upper three bits may have different values due to different manufacturers.
This program is relatively complete. In response to r1 and the previous MMC_DR_MASK (the macro definition value is 0x0001 1111), the upper three bits are ANDed to 0. Some programs on the Internet do not have this process.
If you want to verify whether the card can be read and written normally, you can assign the value to the array and write it to a sector of the SD card (the sector here refers to the physical sector, which will be discussed in the FAT file). Then read it out with the array and see if it is the same in the emulator. This process may not use the winhex software, because the sector you write to may be the boot area, which will cause you to be prompted to format the card when you insert it into the computer.
Below is the waveform of CMD0
I originally thought that there was something wrong with the waveform, because the chip select line in the timing diagram was always low during the data transmission process. I asked about it online for a while, but unfortunately no one paid attention to me. In fact, it was correct. The level jump in the middle was due to the chip select being pulled low and high at the beginning and end of the SPI sending function. Once the chip select line is pulled high, the data line will become high as well, so the jump occurred. I tried to remove the chip select at the beginning and end of the SPI sending function, and found that this also worked.
Step 4: Add FAT
If the above tests are all OK, then there is no problem with the underlying communication. So far, we have been operating the SD as a large FLASH, but if you want to read the program written by the microcontroller on the computer, you must write it in accordance with certain rules, and this rule is FAT. I use a 2G Kingston SD card, which can use FAT16, and FAT16 supports up to 2G.
For more information about this section, please refer to http://www.sjhf.net/document/fat/ #index
The explanation inside is very detailed and will help you understand the file system
The idea that needs to be grasped is: first use a computer to format the SD card into FAT16 (i.e. FAT), and then the reading and writing rules are: find the MBR (master boot area) and read the relevant bytes to get the address of the logical boot area, read the BPB data in the logical sector, and then perform corresponding operations on the FAT table, root directory and data area.
You can use winhex to view the physical and logical sectors of the SD card for comparison.
Here I will talk about some problems I encountered.
1>>If it is VISTA operating system, you need to enter as an administrator, otherwise you will not be able to see the physical sectors, that is, stop the mouse on the winhex icon, right-click and select Run as administrator (don't laugh, I didn't know how to do this at the beginning, haha)
2>>Some SD cards do not have a master boot area, or MBR. This is better, and the logical sector is the same as the physical sector. So how do you determine whether there is an MBR? The simplest way is to use winhex to look at the physical and logical sectors. If the data is the same, there is no MBR. Another more rigorous method is to pay attention to the explanation of the logical boot area in the PDF. The logical boot area basically starts with E9 and EB. This alone can be easily determined using a function. So before writing a file, find out whether your SD card has an MBR. For more information, please refer to http://hi.baidu.com/bg4uvr/blog/item/b59f2fde196efd5fcdbf1aee.html
Is there any MBR that can be converted? For details, please see: http://hi.baidu.com/bg4uvr/blog/item/9489a6295f7bcff998250a48.html
3>>Here are some questions about compilation. After adding the FAT part of the program, there will be more program files in the project. Here we should pay attention to the problem of repeated inclusion. There are many such problems on the Internet, so I will not repeat them here. Sometimes the error is not in the line indicated by the pointer.
For example, sometimes the line you are referring to contains only a statement like int a;. In this case, you should look up to see if the semicolon at the end was omitted when defining the function, causing the compiler to treat a as its parameter. This error is sometimes very subtle, such as int a; contains only #include "bh". In this case, you should look in b to see if the semicolon was forgotten after the function defined at the end of the file.
If the compiler reports "segment too large", you need to set the Variable in the Memory Model in the compiler options to XDATA. This is for the sililab IDE development environment, or you can put it in the xdata array. Project -> Tool Chain Intergration -> Compiler -> Custmize -> Memory Model -> Variable -> Large: XDATA
The official download of this IDE will limit the code size because the compiler used in it is a limited version. At this time, if you install the genuine KEIL, you can use the KEIL compiler without code restrictions. Specific steps: Project——>Tool Chain Intergration, modify the paths in Compiler and Linker to the corresponding paths of KEIL.
Also, some programs do not support nested folders.
Now I will talk about the most important problem, which is also the last problem I encountered, the byte order problem. Please refer to http://blog.csdn.net/sunshine1314/archive/2008/04/20/2309655.aspx
Now that you know the byte order, you don't need to worry about the bit order. If you are using an AVR microcontroller, congratulations, the word order is the same as that of the SD card and the computer, so you don't need to convert the word order. You can use most programs on the Internet. The C8051F020 I use needs to do a conversion every time I exchange data larger than one byte with the card. Since only data such as 8 16 32 is used in the program, I only add two-byte conversion functions and four-byte conversion functions. The function body is as follows:
uint16_t two_byte_exchange(uint16_t h)
{
if(!Big_Small_ending_Switch) //If byte conversion is not enabled, return the original value
return h;
return (h >> 8) + (h << 8);
}
uint32_t four_byte_exchange(uint32_t h)
{
if(!Big_Small_ending_Switch) //If byte conversion is not enabled, return the original value
return h;
return (h >> 24) + ((h >> 16) << 8)+ ((h >> 8) << 16)+ (h << 24);
}
The above are most of the problems I encountered. I hope it will be helpful to everyone. Due to my limited level, I would like to ask seniors to give me advice if there are any shortcomings!
Previous article:If you use the sprintf() function in 51, you must be more careful!
Next article:Design of intelligent fast charger for electric vehicle battery based on single chip microcomputer
Recommended ReadingLatest update time:2024-11-17 00:43
- Popular Resources
- Popular amplifiers
- 100 Examples of Microcontroller C Language Applications (with CD-ROM, 3rd Edition) (Wang Huiliang, Wang Dongfeng, Dong Guanqiang)
- Digilent Vivado library
- Teach you to learn 51 single chip microcomputer-C language version (Second Edition) (Song Xuefeng)
- Raspberry Pi Development in Action (2nd Edition) ([UK] Simon Monk)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- An article explains the relationship between the stability of fully differential voltage feedback amplifiers and the feedback resistor value
- Six points to note when selecting resistors
- Planar spiral inductor design
- Add OpenOCD Flash driver for domestic chips --- take AIC8800 as an example
- [Erha Image Recognition Artificial Intelligence Vision Sensor] The final report is based on Erha Image Recognition Vision Sensor and STM32 Smart Car
- Which TI model is the chip with silkscreen AO34?
- [Shanghai Hangxin ACM32F070 development board + touch function evaluation board review] Touch button
- Maintaining Common Equipment - Power Meters and Power Sensors
- [Open Source] Introduction to the whole board resources - FengShell ARM dual processor development board series
- Does the reverse gate-source voltage of an enhanced NMOS have an effect on the drain-source leakage current?