Beruflich Dokumente
Kultur Dokumente
MMC is interfaced to PIC via SPI (serial peripheral interfacing). Inbuilt SPI module is available
in PIC16F877A. The SPI mode allows 8 bits of data to be synchronously transmitted and received
simultaneously. Here, PIC16F877A is SPI master and MMC is SPI slave. To accomplish
communication,
typically
three
pins
are
used:
Serial
Data
Out
(SDO)
RC5/SDO
Serial
Data
In
(SDI)
RC4/SDI/SDA
Serial Clock (SCK) RC3/SCK/SCL
MMC works at 3.6 V(max) and PIC16F877A at 5V. So, we need a voltage level convertor for
interfacing PIC to MMC. A simple resistor based voltage divider is used to connect CS, CLK and
SCK. Now, if a 4.3v (max o/p of PIC) appears across any of the above three pins, then the
voltage at corresponding MMC pins will be 2.48v (comes in range of logic high of MMC). 'Data
out' of MMC is directly connected to spi 'data in' of PIC.
MMC COMMAND & RESPONSE:
To initiate an operation on MMC, we need to send corresponding 6byte long MMC command
(structure on above figure) which is specific to each operation like single block read, multiple
block read, single block write, multiple block write, mmc initialization etc etc etc ...
Now, i think is better to explain the MMC command using command function in program.
long
)
spi_write(0xff);
spi_write(0b01000000|command);
spi_write((unsigned
char)(fourbyte_arg
>> 24));
spi_write((unsigned
char)(fourbyte_arg
>> 16));
spi_write((unsigned
char)(fourbyte_arg
>> 8));
spi_write((unsigned
char)fourbyte_arg);
spi_write(CRCbits);
spi_read();
}
The above function is the command function. If we call the command function with 6 byte
arguments then it will send the 6 bytes to MMC using spi_write function.
In MMC command, the Most significant byte is the command byte. In the command byte, the 2
'MSB' bits are always 01. The remaining 6 bits are the actual command. So, a CMD0 means this
6 bits will be 000000 and the msb 2 bits will be 01. So, the command byte for CMD0 is
0b01000000. ie in hex, it will be 0x40 and in decimal, it will be 64. Now, comes the 4 argument
bytes, which carry some information to be transferred to MMC ie the information such as sector
address, block size etc...It depends on the command whether it requires the 4 byte argument or
not. If it is not required to certain commands (like CMD0) then 0x00 is send four times ie
the fourbyte_arg is zero. Now comes the CRC byte, which is not cared in the SPI mode of MMC.
So, we send 0xff as CRC byte.
Command 0 (CMD0) is called like this :
command(0,0,0x95);
There are different types of command responses. Now, for getting a response from MMC, 0xff is
send and the received data will be the response. For some commands, we need to wait until the
correct response is received, by continuously checking for the response.
There are commands for reading, writing etc. Every data read or data write operation is
completed by reading or writing of a total of 512 bytes of data. A sector is 512 bytes.(default block
size). We cannot terminate the read or write operation in the midway with in a block.
MMC INITIALIZATION:
When an MMC is powered ON, we need to initialize the MMC and bring it to SPI mode . This
requires a series of commands (will be there in MMC spec) and need to check the response (as
per the spec) whether it is correct or not for the particular command.
Actually initialization was the main problem which i faced at the beginning. It took 3 days for
me to successfully initialize an MMC card. I used hyperterminal in PC for checking the response
of each command. I feel it is the best testing method. Later i used a 16x2 LCD. (check mmc_init()
in
my
program
below.)
DATA
TRANSFER:
-------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
command and data packet) instead of post wait can eliminate waste wait time. In addition the
internal process is initiated a byte after the data response, this means eight clocks are required to
initiate internal write operation. The state of CS signal during the eight clocks is negligible so that
it can done by bus release process described below.
Multiple Block Write:
The Multiple Block Read command writes multiple blocks in sequence from the specified
address. When number of transfer blocks has not been specified prior to this command, the
transaction will be initiated as an open-ended multiple block write, the write operation will
continue until it is terminated with a Stop Tran token(FDh). The busy flag will appear on the DO
line a byte after the Stop Tran token. As for SDC, the multiple block write transaction must be
terminated with a Stop Tran token independent of the transfer type, pre-defined or open-ended.
AUDIO
OUT:
Here, I used inbuilt PWM module of the PIC as a DAC. PWM is really a good and cheap
solution for DAC. Here, if i put an 8 bit data to CCPR2L register of PIC, it will generate PWM
signal corresponding to that data. If i stream the voice data to CCPR2L with a speed according to
the specified bitrate then a Pulse Width Modulated signal corresponding to the voice is generated
which could be easily converted to analog signal by using a low pass filter. This could be
amplified
and
introduced
to
a
speaker
to
reproduce
the
voice.
PWM
out
could
be
obtained
from RC1/CCP2 pin
of
PIC16F877A.
ADC:
ADC in PIC is used to convert the analog audio signal from a condenser mic pre-amp.
PIC16F877A have inbuilt 10 bit ADC module. I used only the 8 LS bits to store in the
MMC. RA0 of PIC16F877A is used configured as ADC input channel where the mic preamp is
connected.
CIRCUIT
DIAGRAM:
PROGRAM:
/*
----------------------------------------------------------------------------------PIC16F877A + MMC voice recored (no file system)
----------------------------------------------------------------------------------COMPILER: HI-TECH C , TARGET uC PIC16F877A
----------------------------------------------------------------------------------by Vinod.S <vinodstanur@gmail.com>
----------------------------------------------------------------------------------*/
#include<pic.h>
#define _XTAL_FREQ 20e6
__CONFIG(0x3F3A);
#define CS RC2
#define RS RB2
#define EN RB1
#define fst cmd(0x80)
#define snd cmd(0xc0)
unsigned char readdata, u;
unsigned int count;
unsigned long int arg = 0;
/*-----------------LCD BEGIN------------------------------*/
void LCD_STROBE(void)
{
EN = 1;
__delay_us(0.5);
EN = 0;
}
void data(unsigned char c)
{
RS = 1;
__delay_us(40);
PORTD = (c >> 4);
LCD_STROBE();
PORTD = (c);
LCD_STROBE();
}
void cmd(unsigned char c)
{
RS = 0;
__delay_us(40);
PORTD = (c >> 4);
LCD_STROBE();
PORTD = (c);
LCD_STROBE();
}
void clear(void)
{
cmd(0x01);
__delay_ms(2);
}
void lcd_init()
{
__delay_ms(20);
cmd(0x30);
__delay_ms(1);
cmd(0x30);
__delay_ms(1);
cmd(0x30);
cmd(0x28);
5*7Pixels)
cmd(0x28);
5*7Pixels)
cmd(0x28);
5*7Pixels)
cmd(0x0c);
clear();
clear();
cmd(0x6);
}
TRISC1 = 0;
T2CKPS1 = 0;
T2CKPS0 = 0;
PR2 = 0x50;
CCPR2L = 0x17;
TMR2ON = 1;
CCP2CON = 0b00001100;
void pwm_disable()
{
CCP2CON = 0b00000000;
}
void pwm_enable()
{
CCP2CON = 0b00001100;
}
/*--------------------PWM END-------------------------*/
/*-------------------MMC BEGIN-----------------------*/
void spi_init()
{
TRISC4 = 1;
RC2 = 1;
RC3 = 0;
RC5 = 0;
TRISC2 = TRISC3 = TRISC5 = 0;
SSPCON = 0b00100010;
SSPEN = 1;
SMP = 1;
CKE = 1;
CKP = 0;
}
void spi_write(unsigned char kk)
{
SSPBUF = kk;
while (BF == 0);
}
void spi_read()
{
SSPBUF = 0xff;
while (BF == 0);
readdata = SSPBUF;
}
void command(char command, unsigned long int fourbyte_arg, char CRCbits)
{
spi_write(0xff);
spi_write(0b01000000 | command);
spi_write((unsigned char) (fourbyte_arg >> 24));
spi_write((unsigned char) (fourbyte_arg >> 16));
spi_write((unsigned char) (fourbyte_arg >> 8));
spi_write((unsigned char) fourbyte_arg);
spi_write(CRCbits);
spi_read();
}
void mmc_init()
{
CS = 1;
for (u = 0; u < 50; u++) {
spi_write(0xff);
}
CS = 0;
__delay_ms(1);
command(0, 0, 0x95);
count = 0;
while ((readdata != 1) && (count < 1000)) {
spi_read();
count++;
}
if (count >= 1000) {
string("CARD ERROR-CMD0 ");
while (1);
}
command(1, 0, 0xff);
count = 0;
while ((readdata != 0) && (count < 1000)) {
command(1, 0, 0xff);
spi_read();
count++;
}
if (count >= 1000) {
string("CARD ERROR-CMD1 ");
while (1);
}
command(16, 512, 0xff);
count = 0;
while ((readdata != 0) && (count < 1000)) {
spi_read();
count++;
}
if (count >= 1000) {
string("CARD ERROR-CMD16");
while (1);
}
string("MMC INITIALIZED!");
__delay_ms(1000);
SSPCON = SSPCON & 0b11111101;
}
void write()
{
pwm_disable();
command(25, arg, 0xff);
while (readdata != 0) {
spi_read();
string("WRITE ERROR");
}
string("WRITING MMC");
while (1) {
spi_write(0xff);
spi_write(0xff);
spi_write(0b11111100);
for (int g = 0; g < 512; g++) {
GO = 1;
while (GO);
spi_write(ADRESL);
PORTD = ~ADRESL;
}
spi_write(0xff);
spi_write(0xff);
spi_read();
while ((readdata & 0b00011111) != 0x05) {
spi_read();
}
while (readdata != 0xff) {
spi_read();
}
if (RE0 == 1) {
spi_write(0xff);
spi_write(0xff);
spi_write(0b11111101);
//stop token
spi_read();
spi_read();
while (readdata != 0xff) {
spi_read();
}
break;
}
}
void read()
{
pwm_enable();
command(18, (arg), 0xff);
while (readdata != 0) {
spi_read();
string("READ ERROR");
}
string("READING MMC");
while (1) {
while (readdata != 0xfe) {
spi_read();
}
for (int g = 0; g < 512; g++) {
spi_read();
__delay_us(16.5);
CCPR2L = readdata;
PORTD = ~readdata;
}
spi_write(0xff);
spi_write(0xff);
if (RE0 == 1) {
command(12, arg, 0xff);
spi_read();
}
}
while (readdata != 0) {
spi_read();
}
while (readdata != 0xff) {
spi_read();
}
break;
/*--------------------mmc end----------------------*/
/*-----------------ADC functions-------------------*/
void adc_init()
{
TRISA0 = 1;
ADCON0 = 0b10000001;
ADCON1 = 0b10001110;
}
/*-------------------main function-------------------*/
main()
{
CS = 1;
PORTD = 0;
TRISC4 = 0;
TRISC5 = 0;
TRISD = 0;
TRISB2 = 0;
TRISB1 = 0;
TRISE0 = 1;
lcd_init();
adc_init();
usrt_init();
spi_init();
mmc_init();
pwm_init();
lcd_init();
count = 0;
CS = 0;
arg = 0;
while (1) {
arg = 0;
fst;
pwm_enable();
string("READ MODE");
__delay_ms(1000);
read();
arg = 0;
fst;
pwm_disable();
string("WRITE MODE");
__delay_ms(1000);
write();
}
}
:100000000A128A11C42A00308A000408840A82076E
:10001000003443344134523444342034453452346F
:1000200052344F3452342D3443344D34443430340C
:100030002034003443344134523444342034453481
:10004000523452344F3452342D3443344D344434CA
:100050003134203400344D344D3443342034493469
:100060004E3449345434493441344C3449345A348C
:10007000453444342134003443344134523444341C
:1000800020344534523452344F3452342D344334B6
:100090004D3444343134363400344234593420340D
:1000A0002D342034563449344E344F344434533490
:1000B000543441344E34553452340034523445347F
:1000C0004134443449344E34473420344D344D3473
:1000D00043340034573452344934543449344E3460
:1000E000473420344D344D34433400345734523483
:1000F00049345434453420344534523452344F3426
:100100005234003457345234493454344534203452
:100110004D344F3444344534003452344534413442
:10012000443420344534523452344F345234003441
:10013000523445344134443420344D344F34443403
:04014000453400340E
:10054E00831203139D0108000C30831203139D00C8
:10055E000800831203138614B42A83120313861021
:10056E0008008316031305148130831203139F00B2
:10057E008E30831603139F000800A001A101A20173
:10058E00A301A401A501A601A70183010A128A11E4
:10059E00902C83160313071326309800D030831245
:1005AE00031398000A308316031399000800F00015
:1005BE007008831203139300E42A83160313141C8A
:1005CE00E92AEA2AE42AEB2A080001300A128A11E3
:1005DE0060230A128A110D30F300FB30F200F20B89
:1005EE00F62AF30BF62AFB2A08008316031387104C
:1005FE0083120313921012105030831603139200BD
:10060E001730831203139B0012150C309D00080047
:10061E00FF30831203139300142B83160313141C41
:10062E00192B1A2B142B1B2B831203131308F000F8
:10063E007008A6000800831603130716831203130F
:10064E000715871187128316031387128711071157
:10065E0022308312031394009416831603139417F7
:10066E0014178312031314120800F10083120313DC
:10067E0006154230F000F00B422B64007108F000BA
:10068E0004300310F00CFF3E031D482B700883123C
:10069E00031388000A128A11B0220A128A117108F5
:1006AE008312031388000A128A11B0220A128A11C9
:1006BE000800F1008312031306114230F000F00B14
:1006CE00662B64007108F00004300310F00CFF3E3E
:1006DE00031D6C2B70088312031388000A128A11F3
:1006EE00B0220A128A1171088312031388000A12AB
:1006FE008A11B0220A128A110800F300C0300A12C1
:10070E008A1160230A128A119D2B730884000A1223
:10071E008A1103200A128A110A128A113C230A1224
:10072E008A110130F2007208F3079D2B73088400C2
:10073E000A128A1103200A128A110038031DA82BEF
:10074E00A92B8C2BAA2B0800F5000A128A11EC2279
:10075E000A128A11C32B750884000A128A1103200B
:10076E000A128A110A128A113C230A128A110130C6
:10077E00F4007408F507C32B750884000A128A1159
:10078E0003200A128A110038031DCE2BCF2BB22B59
:10079E00D02B45300A128A1184230A128A110800BE
:1007AE008230F500DD30F400F40BDB2BF50BDB2B88
:1007BE00E02B30300A128A1160230A128A11073098
:1007CE00F5007D30F400F40BEA2BF50BEA2B3030FC
:1007DE000A128A1160230A128A110730F5007D3041
:1007EE00F400F40BF82BF50BF82B30300A128A11AB
:1007FE0060230A128A1128300A128A1160230A1203
:10080E008A1128300A128A1160230A128A1128309E
:10081E000A128A1160230A128A110C300A128A11E6
:10082E0060230A128A110A128A11EC220A128A1104
:10083E000A128A11EC220A128A1106300A128A1141
:10084E0060230A128A110800FA00FF300A128A1178
:10085E00DE220A128A117A0840380A128A11DE2222
:10086E000A128A117108F6007208F7007308F80070
:10087E007408F90018300310F90CF80CF70CF60C8C
:10088E00FF3E031D422C76080A128A11DE220A123E
:10089E008A117108F6007208F7007308F8007408E0
:1008AE00F90010300310F90CF80CF70CF60CFF3EA3
:1008BE00031D592C76080A128A11DE220A128A1199
:1008CE007108F6007208F7007308F8007408F90052
:1008DE0008300310F90CF80CF70CF60CFF3E031D54
:1008EE00702C76080A128A11DE220A128A117108F9
:1008FE000A128A11DE220A128A1175080A128A1148
:10090E00DE220A128A110A128A110F230A128A1182
:10091E0008008312031307158801831603130712A9
:10092E00871288010611861009140A128A11D7231C
:10093E000A128A110A128A11B8220A128A110A128E
:10094E008A11D0220A128A110A128A1122230A123D
:10095E008A110A128A11DB260A128A110A128A11C8
:10096E00FC220A128A110A128A11D7230A128A113C
:10097E0083120313A401A50107110030A300003058
:10098E00A2000030A1000030A000CD2C0030831258
:10099E000313A3000030A2000030A1000030A0001D
:1009AE0080300A128A1160230A128A110A128A11E1
:1009BE00AB220A128A1190300A128A11AB230A1244
:1009CE008A111A3083120313AA004530A9007E3013
:1009DE00A800A80BF02CA90BF02CAA0BF02C0A12D5
:1009EE008A112E250A128A11003083120313A300D6
:1009FE000030A2000030A1000030A00080300A12AA
:100A0E008A1160230A128A110A128A11A7220A1267
:100A1E008A117A300A128A11AB230A128A111A30FD
:100A2E0083120313AA004530A9007E30A800A80B3C
:100A3E001E2DA90B1E2DAA0B1E2D0A128A11F3258F
:100A4E000A128A11CD2CCD2C0A128A1100280A12F4
:100A5E008A11AB220A128A11831203132308F4009F
:100A6E002208F3002108F2002008F100FF30FB00FD
:100A7E007B08F50012300A128A112B240A128A11F1
:100A8E00542D0A128A110F230A128A1185300A1266
:100A9E008A11AB230A128A11542D83120313A6084E
:100AAE00031D5A2D5B2D482D5C2D56300A128A11CE
:100ABE00AB230A128A116A2D6A2D0A128A110F238C
:100ACE000A128A116A2D831203132608FE3A031D99
:100ADE00712D722D642D732DFC01FD017D08803A60
:100AEE00FF0082307F02031D7E2D00307C02031C2E
:100AFE00812D822D842DA72DA72D0A128A110F2349
:100B0E000A128A111B30FB00FB0B8B2D8312031371
:100B1E0026089B00260988000130FC070318FD0AF1
:100B2E000030FD077D08803AFF0082307F02031DF2
:100B3E00A22D00307C02031CA52DA62D842DA72DE1
:100B4E00FF300A128A11DE220A128A11FF300A12AF
:100B5E008A11DE220A128A1183120313091CB82D80
:100B6E00B92D6A2D2308F4002208F3002108F200A3
:100B7E002008F100FF30FB007B08F5000C300A1254
:100B8E008A112B240A128A110A128A110F230A12B1
:100B9E008A11D72D0A128A110F230A128A11D72D04
:100BAE0083120313A608031DDD2DDE2DD12DE62D98
:100BBE00E62D0A128A110F230A128A11E62D8312CC
:100BCE0003132608FF3A031DED2DEE2DE02DF22D19
:100BDE00F22D6A2D6A2D08000A128A11A7220A1216
:100BEE008A11831203132308F4002208F30021084C
:100BFE00F2002008F100FF30FB007B08F5001930F1
:100C0E000A128A112B240A128A11192E0A128A111B
:100C1E000F230A128A116E300A128A11AB230A129E
:100C2E008A11192E83120313A608031D1F2E202EC0
:100C3E000D2E212E62300A128A11AB230A128A114E
:100C4E00282EFF300A128A11DE220A128A11FF3074
:100C5E000A128A11DE220A128A11FC300A128A1135
:100C6E00DE220A128A11FC01FD017D08803AFF0086
:100C7E0082307F02031D452E00307C02031C482E5D
:100C8E00492E4B2E762E762E831203131F154F2EC2
:100C9E001F19522E532E4F2E542E831603131E0839
:100CAE000A128A11DE220A128A11831603131E09F2
:100CBE008312031388000130FC070318FD0A00306D
:100CCE00FD077D08803AFF0082307F02031D712EE2
:100CDE0000307C02031C742E752E4B2E762EFF30A8
:100CEE000A128A11DE220A128A11FF300A128A11A2
:100CFE00DE220A128A110A128A110F230A128A118F
:100D0E008E2E0A128A110F230A128A118E2E831228
:100D1E00031326081F39053A031D962E972E882E8B
:100D2E009F2E9F2E0A128A110F230A128A119F2EAE
:100D3E00831203132608FF3A031DA62EA72E992E03
:100D4E00091CAA2EAB2E282EFF300A128A11DE2283
:100D5E000A128A11FF300A128A11DE220A128A1131
:100D6E00FD300A128A11DE220A128A110A128A1123
:100D7E000F230A128A110A128A110F230A128A11DC
:100D8E00CE2E0A128A110F230A128A11CE2E831228
:100D9E0003132608FF3A031DD52ED62EC82EDA2EA3
:100DAE00DA2E282E282E0800831203130715A7010A
:100DBE0032302702031CE42EE52EE72EF92EF92EF3
:100DCE00FF300A128A11DE220A128A110130FB004C
:100DDE007B0883120313A70732302702031CF82E59
:100DEE00F92EE72E07110730FC007D30FB00FB0BC0
:100DFE00FE2EFC0BFE2E0030F4000030F30000300F
:100E0E00F2000030F1009530FB007B08F500003059
:100E1E000A128A112B240A128A1183120313A401B7
:100E2E00A501272F0A128A110F230A128A110130E7
:100E3E0083120313A4070318A50A0030A507272F52
:100E4E002608013A03192C2F2D2F382F0330250297
:100E5E00E83003192402031C352F362F192F382F93
:100E6E00382F03302502E83003192402031C402FCB
:100E7E00412F4A2F01300A128A11AB230A128A110E
:100E8E00482F482F4A2F0030F4000030F300003076
:100E9E00F2000030F100FF30FB007B08F50001305E
:100EAE000A128A112B240A128A1183120313A40127
:100EBE00A501812F0030F4000030F3000030F20065
:100ECE000030F100FF30FB007B08F50001300A1204
:100EDE008A112B240A128A110A128A110F230A125E
:100EEE008A11013083120313A4070318A50A0030D8
:100EFE00A507812F2608031D852F902F033025026D
:100F0E00E83003192402031C8D2F8E2F612F902F92
:100F1E00902F03302502E83003192402031C982F6A
:100F2E00992FA22F12300A128A11AB230A128A119C
:100F3E00A02FA02FA22F0030F4000030F3000230BB
:100F4E00F2000030F100FF30FB007B08F50010309E
:100F5E000A128A112B240A128A1183120313A40176
:100F6E00A501C72F0A128A110F230A128A11013006
:100F7E0083120313A4070318A50A0030A507C72F71
:100F8E002608031DCB2FD62F03302502E830031978
:100F9E002402031CD32FD42FB92FD62FD62F0330D4
:100FAE002502E83003192402031CDE2FDF2FE82F61
:100FBE0034300A128A11AB230A128A11E62FE62F59
:100FCE00E82F23300A128A11AB230A128A111A3023
:100FDE00FD004530FC007E30FB00FB0BF42FFC0BBC
:100FEE00F42FFD0BF42F831203131408FD39940014
:020FFE000800E9
:02400E003A3F37
:00000001FF