|
本帖最后由 tomzbj 于 2013-5-21 11:39 编辑
马老师在我blog上的原文:
“用m16加一片lm324,设计一个读取sd卡上wave文件,并播放的wave播放器,看谁做的好
尝试过就知道了,关键还是要做的好。参考一下我编写教程第2版的第19章,有什么心得可以到我的讨论组交流。”
我用mega8,16.9344M, 14位r-2r实现了流畅播放16位 44.1kbps单声道wav。 双声道没试,估计超点频应该差不多了。
这次用了两晚上焊电路,周末两天加今天晚上调试。如果再加上3月份用8位pwm做的一次实验,那就是一共用了五个晚上和四个全天时间,hehe
电路图见附件
主程序如下,其他初始化、uart、sd卡操作、petit fs之类就不贴了#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "init.h"
#include "uart.h"
#include "sd.h"
//#include "fifo.h"
#include "pttfs/pff.h"
#include "pttfs/diskio.h"
#define FIFOSIZE 384
volatile static enum { NOTREADY, READY } play_ready;
volatile uint16_t *rear, *front;
uint16_t fifo_buf[FIFOSIZE];
FATFS fs;
/* 全部fifo操作改用宏实现 */
#define fifo_init() do { front = rear = fifo_buf; } while(0)
#define fifo_is_empty() ( front == rear )
#define fifo_is_full() ( rear+1 == front || rear+1 == front+FIFOSIZE )
#define fifo_del(e) do { e = *front; front++; if( front == fifo_buf + FIFOSIZE ) front = fifo_buf; } while(0)
/*inline int8_t fifo_del( uint16_t *e ) {
if( fifo_is_empty() )
return -1;
*e = *front;
front++;
if( front == fifo_buf + FIFOSIZE )
front = fifo_buf;
return 0;
}*/
/*
int8_t fifo_insert( uint16_t e ) {
if( fifo_is_full() )
return -1;
*rear = e;
rear++;
if ( rear == fifo_buf + FIFOSIZE )
rear = fifo_buf;
return 0;
}*/
ISR( TIMER0_OVF_vect ) {
uint16_t data;
TCNT0 += (256-48); // 16934400 / 8 / 48 = 44100
if( play_ready == NOTREADY )
return;
if( !fifo_is_empty() )
fifo_del( data );
else
data = 0x0;
data += 0x8000;
/* PORTD = ( PORTD & 0x3 ) | ( (data >> 8 ) & 0xfc );
*/
/* 用14个io拼r-2r, 比用pwm da的方式灵活些。如果用m16就容易多了 */
PORTB = ( PORTB & 0xfc ) | ( data >> 14 );
PORTD = ( PORTD & 0x3 ) | ( (data >> 6 ) & 0xfc );
PORTC = ( data >> 2 ) & 0xff;
}
uint16_t get_avail_mem(void) {
uint8_t *p;
uint16_t i;
for( i = 1; i < 65534; i++ ) {
p = malloc(i);
if( !p )
break;
free(p);
}
return i-1; /* 最后一次分配成功的栈内存大小 */
}
void init() {
play_ready = NOTREADY;
init_devices();
fifo_init();
disk_initialize();
pf_mount(&fs);
}
void listfile( char *path ) {
DIR dir;
FILINFO finfo;
int n = 256;
pf_opendir( &dir, path );
while ( pf_readdir( &dir, &finfo ) == FR_OK && n > 0 ) {
n--;
if( finfo.fname[0] == '\0' )
continue;
if( strstr( finfo.fname, ".WAV" ) ) {
uart_puts( finfo.fname );
uart_puts( "\r\n" );
play_back( finfo.fname );
}
}
}
void skip_wav_header() {
WORD n;
uint8_t i,ret;
do {
ret = pf_read( (void *)fifo_buf, 4, &n );
} while( strncasecmp( (char *)fifo_buf, "fmt ", 4 ) );
{
DWORD size;
struct WAVE_FORMAT {
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
} fmt_chunk;
ret = pf_read( &size, 4, &n );
ret = pf_read( &fmt_chunk, sizeof(fmt_chunk), &n );
/* sprintf( (char *)fifo_buf, "%u channel, %lubps, %ubits",
fmt_chunk.wChannels,
fmt_chunk.dwSamplesPerSec,
fmt_chunk.wBitsPerSample );
uart_puts( (char *)fifo_buf );*/ /* 显示wave文件头信息 */
i = size - sizeof(fmt_chunk);
while( i>0 ) {
pf_read( fifo_buf, 1, &n );
i--;
}
}
pf_read( fifo_buf, 4, &n );
// uart_write( (char *)fifo_buf, 4 );
/* 实际可能还需要跳过fact等trunk,不过无所谓了,不影响播放 */
}
void play_back( char *path ) {
register uint16_t i;
register uint16_t *ptr;
int8_t ret;
WORD n;
register WORD nn = 0;
ret = pf_open( path );
skip_wav_header();
do {
/* pf_read( buf, sizeof(buf), &n );
for( i = 0; i < n; i+=2 ) {
do {
ret = fifo_insert( *(uint16_t *)(&buf) );
} while( ret == -1 );
}
continue;*/ /* 以上实现逐个数据插入fifo,22.05kbps时可以,44.1kbps就不行了 */
if( fifo_is_full() )
continue;
cli();
ptr = rear;
if( front <= rear ) {
if ( front == fifo_buf ) {
nn = fifo_buf + FIFOSIZE - rear - 1;
nn *= sizeof( fifo_buf[0]);
rear = fifo_buf + FIFOSIZE - 1;
}
else {
nn = fifo_buf + FIFOSIZE - rear;
nn *= sizeof( fifo_buf[0]);
rear = fifo_buf;
}
}
else if (front > rear ) {
nn = front - rear - 1;
nn *= sizeof( fifo_buf[0]);
rear = front - 1;
}
sei();
pf_read( ptr, nn, &n );
play_ready = READY;
if( ! ( PIND & _BV(0) ) ) {
while( ! (PIND & _BV(0) ) );
break;
}
} while( nn == n );
}
int main() {
init();
{ sprintf( fifo_buf, "free mem: %d\r\n", get_avail_mem() ); uart_puts(fifo_buf); }
listfile( "/" );
while(1);
return 0;
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|