---
+ Post New Thread
Results 1 to 7 of 7
  1. #1
    Member level 3
    Points: 684, Level: 5

    Join Date
    May 2011
    Posts
    57
    Helped
    1 / 1
    Points
    684
    Level
    5

    How to play audio files from SD card using PIC microcontroller

    Hello,

    For my project, I want to play some audio files from the SD card. I want to control these audio files using a PIC micro controller (I have a PIC 16F877A uc).
    I need a great help to do this.

    I am a beginner in PIC programming field and I don't know how much complex the task is? But anyway hope for the best.

    Another way to do this using a voice controller IC like APR9600, but a second person may not know how to add new audio files to IC. This is why I want to try using a SD card with an interface to PC so that it is easy to change the file if necessary :)

    Thanks in advance,
    Akhil

    •   Alt9th June 2011, 07:40

      advertising

        
       

  2. #2
    Advanced Member level 5
    Points: 35,361, Level: 45
    ckshivaram's Avatar
    Join Date
    Apr 2008
    Location
    villingen (Germany) / Bangalore
    Posts
    5,070
    Helped
    2128 / 2128
    Points
    35,361
    Level
    45
    Blog Entries
    1

    Re: How to play audio files from SD card using PIC microcontroller

    A good search int he forum would give you enough results...
    pic audio voice record and play porject required urjent !!!!
    " It is so simple to be happy,
    but it is so difficult to be simple"



    •   Alt9th June 2011, 07:46

      advertising

        
       

  3. #3
    Advanced Member level 3
    Points: 5,652, Level: 17
    vinodstanur's Avatar
    Join Date
    Oct 2009
    Location
    Kerala (INDIA)
    Posts
    722
    Helped
    108 / 108
    Points
    5,652
    Level
    17
    Blog Entries
    3

    Re: How to play audio files from SD card using PIC microcontroller

    The main problem is RAM in PIC16F877A. Generally, u need RAM of above 512 bytes for efficient FAT file system access. Better solution is go for PIC18F series.
    -----------------------------------
    I had done a digital voice recorder and play back system with MMC and PIC16F877A but it doesn't have any file system. It just write and read from a particular sector to its last sector.(i think u had seen that video).I didn't used RAM buffer but continuously read bytes and send each byte to PWM just after reading the byte. I am posting the code at the bottom.
    -----------------------------------
    And i also wrote code to access FAT filesystem using PIC16F877A. But i doubt that the code is less efficient and may not be good for audio streaming. I can display ASCII-text files(copied to FAT16 mmc) in an LCD using PIC16F877A. The difficult part is reading the FAT(file allocation table) in the MMC (to get next sector address of the playing file) after streaming each cluster. If u could do it in most efficient manner, then i think u can play an audio using PIC16F877A. Any way, i stopped my activities since its our exam time, and i will continue after exam. My aim is to play wav files in FAT16 mmc using this PIC.
    ----------------------------------
    Code:
    ///////////////////////////////////////////////////////////////////////
    // my first digital voice recorder using PIC16F877A and MMC//
    //   push button at RE0 to select play or record mode           //
    // http://www.youtube.com/watch?v=Mn1VsM-i8QI             //
    ///////////////////////////////////////////////////////////////////////
    #include<pic.h>
    #define _XTAL_FREQ 20e6
    #define CS RC2
    #define RS RB2
    #define EN RB1
    #define fst cmd(0x80)
    #define snd cmd(0xc0)
    unsigned int i;
    unsigned char j,k,rec,dat,tempbuf,readdata,u;
    unsigned int count;unsigned long int wcount;
    unsigned long int mul=1,arg=0;
    	const char *q="VINOD ";
    /*-----------------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 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x28 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x28 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x0c); // Make cursorinvisible
    	clear();
    	clear(); // Clear screen 
    	cmd(0x6); // Set entry Mode
    	}
    void string(const char *q)
    	{
    	clear();
    	while(*q) {data(*q++);}
    	}
    
    
    void istring(unsigned int q)
    	{
    	cmd(0x81);
    	data(48+(q/100));q%=100;
    	data(48+(q/10));q%=10;
    	data(48+(q));
    	__delay_ms(500);
    	}
    /*-----------------------LCD END--------------------*/
    
    /*-----------------------USRT BEGIN--------------------*/
    void usrt_init()
    	{
    
    	TRISC6=0;
    	TXSTA=0b00100110;
    	RCSTA=0b11010000;
    	SPBRG=10;
    	}
    void printf(const char *p)
    	{
    	while(*p)
    		{
    		TXREG=*p;
    		while(TRMT==0);
    		p++;
    		}
    	}
    void txd(unsigned char vv)
            {
            TXREG=vv;
            while(TRMT==0);
            }
      /*-----------------------USRT END-------------------*/
      
    /*----------------------PWM BEGINS--------------------*/
    void pwm_init()
    {
    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();	
    	/*write*/
    	command(25,arg,0xff);
    	while(readdata!=0){spi_read();string("WRITE ERROR");}
    	string("WRITING MMC");
    h:	spi_write(0xff);
    	spi_write(0xff);
    	spi_write(0b11111100);
    	for(int g=0;g<512;g++)
    		{
    		ADGO=1;
    		while(ADGO);
    		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();}
    	goto exit1;
    	}
    	goto h;
    exit1:;
    	}
    void read()
    	{
    	pwm_enable();
    
    	command(18,(arg),0xff);
    	while(readdata!=0){spi_read();	string("READ ERROR");}
    	string("READING MMC");
    g:	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();}
    		goto exit2;
    		}
    	goto g;
    exit2:pwm_disable();
    	}
    /*--------------------mmc end----------------------*/
    
    /*-----------------ADC functions-------------------*/
    void adc_init()
    {
    TRISA0=1;
    ADCON0=0b10000001;
    ADCON1=0b10001110;
    }
    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;
    mul=1;arg=0;
    while(1)
    	{
    arg=0;
    fst;
    string("READ MODE");
    __delay_ms(1000);
    read();
    arg=0;
    fst;
    string("WRITE MODE");
    __delay_ms(1000);
    write();
    	}
    }
    I am not telling that this is an efficient code, now i think i can modify it much more. In above program, i am waiting for ADC to complete, without doing any job. I think its better to send converted Digital value to MMC while ADC starts next conversion. Similarly, much modifications could be done to make it more efficient.
    Last edited by vinodstanur; 9th June 2011 at 10:35.


    1 members found this post helpful.

    •   Alt9th June 2011, 10:26

      advertising

        
       

  4. #4
    Newbie level 3
    Points: 561, Level: 5

    Join Date
    May 2010
    Posts
    3
    Helped
    0 / 0
    Points
    561
    Level
    5

    Re: How to play audio files from SD card using PIC microcontroller

    Quote Originally Posted by vinodstanur View Post
    The main problem is RAM in PIC16F877A. Generally, u need RAM of above 512 bytes for efficient FAT file system access. Better solution is go for PIC18F series.
    -----------------------------------
    I had done a digital voice recorder and play back system with MMC and PIC16F877A but it doesn't have any file system. It just write and read from a particular sector to its last sector.(i think u had seen that video).I didn't used RAM buffer but continuously read bytes and send each byte to PWM just after reading the byte. I am posting the code at the bottom.
    -----------------------------------
    And i also wrote code to access FAT filesystem using PIC16F877A. But i doubt that the code is less efficient and may not be good for audio streaming. I can display ASCII-text files(copied to FAT16 mmc) in an LCD using PIC16F877A. The difficult part is reading the FAT(file allocation table) in the MMC (to get next sector address of the playing file) after streaming each cluster. If u could do it in most efficient manner, then i think u can play an audio using PIC16F877A. Any way, i stopped my activities since its our exam time, and i will continue after exam. My aim is to play wav files in FAT16 mmc using this PIC.
    ----------------------------------
    Code:
    ///////////////////////////////////////////////////////////////////////
    // my first digital voice recorder using PIC16F877A and MMC//
    //   push button at RE0 to select play or record mode           //
    // http://www.youtube.com/watch?v=Mn1VsM-i8QI             //
    ///////////////////////////////////////////////////////////////////////
    #include<pic.h>
    #define _XTAL_FREQ 20e6
    #define CS RC2
    #define RS RB2
    #define EN RB1
    #define fst cmd(0x80)
    #define snd cmd(0xc0)
    unsigned int i;
    unsigned char j,k,rec,dat,tempbuf,readdata,u;
    unsigned int count;unsigned long int wcount;
    unsigned long int mul=1,arg=0;
    	const char *q="VINOD ";
    /*-----------------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 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x28 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x28 ); // Function set (4-bit interface, 2 lines, 5*7Pixels)
    	cmd(0x0c); // Make cursorinvisible
    	clear();
    	clear(); // Clear screen 
    	cmd(0x6); // Set entry Mode
    	}
    void string(const char *q)
    	{
    	clear();
    	while(*q) {data(*q++);}
    	}
    
    
    void istring(unsigned int q)
    	{
    	cmd(0x81);
    	data(48+(q/100));q%=100;
    	data(48+(q/10));q%=10;
    	data(48+(q));
    	__delay_ms(500);
    	}
    /*-----------------------LCD END--------------------*/
    
    /*-----------------------USRT BEGIN--------------------*/
    void usrt_init()
    	{
    
    	TRISC6=0;
    	TXSTA=0b00100110;
    	RCSTA=0b11010000;
    	SPBRG=10;
    	}
    void printf(const char *p)
    	{
    	while(*p)
    		{
    		TXREG=*p;
    		while(TRMT==0);
    		p++;
    		}
    	}
    void txd(unsigned char vv)
            {
            TXREG=vv;
            while(TRMT==0);
            }
      /*-----------------------USRT END-------------------*/
      
    /*----------------------PWM BEGINS--------------------*/
    void pwm_init()
    {
    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();	
    	/*write*/
    	command(25,arg,0xff);
    	while(readdata!=0){spi_read();string("WRITE ERROR");}
    	string("WRITING MMC");
    h:	spi_write(0xff);
    	spi_write(0xff);
    	spi_write(0b11111100);
    	for(int g=0;g<512;g++)
    		{
    		ADGO=1;
    		while(ADGO);
    		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();}
    	goto exit1;
    	}
    	goto h;
    exit1:;
    	}
    void read()
    	{
    	pwm_enable();
    
    	command(18,(arg),0xff);
    	while(readdata!=0){spi_read();	string("READ ERROR");}
    	string("READING MMC");
    g:	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();}
    		goto exit2;
    		}
    	goto g;
    exit2:pwm_disable();
    	}
    /*--------------------mmc end----------------------*/
    
    /*-----------------ADC functions-------------------*/
    void adc_init()
    {
    TRISA0=1;
    ADCON0=0b10000001;
    ADCON1=0b10001110;
    }
    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;
    mul=1;arg=0;
    while(1)
    	{
    arg=0;
    fst;
    string("READ MODE");
    __delay_ms(1000);
    read();
    arg=0;
    fst;
    string("WRITE MODE");
    __delay_ms(1000);
    write();
    	}
    }
    I am not telling that this is an efficient code, now i think i can modify it much more. In above program, i am waiting for ADC to complete, without doing any job. I think its better to send converted Digital value to MMC while ADC starts next conversion. Similarly, much modifications could be done to make it more efficient.


    Hi Vinodstanur, I was wondering if you figured out your problem.. I too have problems reading the next cluster from the FAT table... it kind of slows down audio playback since it takes a while to read 512 bytes from the FAT. For this reason, I cannot hear fluid, constant audio streaming each time the pic looks for the next cluster.

    Did you find a way or another method to overcome this problem? Or could you provide me with any suggestion?

    Thank you!



  5. #5
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,307
    Helped
    806 / 806
    Points
    23,048
    Level
    36

    Re: How to play audio files from SD card using PIC microcontroller



    3 members found this post helpful.

  6. #6
    Newbie level 3
    Points: 561, Level: 5

    Join Date
    May 2010
    Posts
    3
    Helped
    0 / 0
    Points
    561
    Level
    5

    Re: How to play audio files from SD card using PIC microcontroller

    Thanks, this helped me figure it out!



  7. #7
    Newbie level 1
    Points: 492, Level: 4

    Join Date
    Jul 2012
    Posts
    1
    Helped
    0 / 0
    Points
    492
    Level
    4

    Re: How to play audio files from SD card using PIC microcontroller

    hi i want to ask if i have counting .wav files upto 999 in sd card is it possible to access these files with some switch and trigger means there would be thre switches so one is up second is down and third is reset so up goes to next counting voice down goes to previous counting voice and reset goes to start of couting voice but it all happen on switch strike please tll me is it possible in this way



+ Post New Thread
Please login