The Fourth Dimension Space

枯叶北风寒,忽然年以残,念往昔,语默心酸。二十光阴无一物,韶光贱,寐难安; 不畏形影单,道途阻且慢,哪曲折,如渡飞湍。斩浪劈波酬壮志,同把酒,共言欢! -如梦令

#

求SGU 194即ZOJ 2314题AC代码

     摘要: 最近在搞网络流,刚研究完几个求最大流的基本算法,今天研究了一下有上下界的可行流问题,参考了大牛ADN.cn的图论总结,算法倒不是很难,代码也很快就写好了,只是不知道原因,就是不能AC,郁闷我一晚上。。。在SGU上 只能过9组数据,也不知道被什么BT的数据给卡住了,希望大牛们能给我点指点。 我用的方法是添加两个附加源汇,用dinic算法求最大流,如果源汇上的边满流,则说明有可行流,输出每条边的流量,...  阅读全文

posted @ 2009-07-12 01:58 abilitytao 阅读(630) | 评论 (2)编辑 收藏

欧几里德算法及其扩展算法的迭代版本(转)

整除和最大公约数。

如果m能整除n,记m|n

对于不全为0的两个整数ab,能同时整除他们俩的最大整数为它们的最大公约数,记为gcd(a,b)。如果gcd(a,b)=1,则ab互质。

gcd(a,b)可用欧几里德算法:

a = q1 * b + r1

b = q2 * r1 + r2

r1 = q3 * r2 + r3

r2 = q4 * r3 + r4

……

rn-3 = qn-1 * rn-2 + rn-1

rn-2 = qn * rn-1 + rn => rn就是gcd

rn-1 = qn+1 * rn + 0

欧几里德算法非常好写。以pascal语言为例:

function gcd(a,b:longint):longint;

begin

if b=0 then gcd:=a

else gcd:=gcd(b,a mod b);

end;

线性方程ax+by=c的解法。

对于abax+byab的线性组合。这里xy可以是任何整数。

g=gcd(a,b),则g整除所有的ax+by。特别地,所有ax+by的取值中,最小的正值为g

因此,方程ax+by=c,仅当gcd(a,b)|c时有解。因此只考虑方程ax+by=gcd(a,b)的解法。

回忆上一章中讲的欧几里德算法,在第i步,我们有

ri-2 = qi * ri-1 + ri 。若ri+1=0,ri就是gcd

假设ri可表示为ab的线性组合(xi,yi),即ri=axi+byi,则有(xi,yi)=(xi-2,yi-2)-qi* (xi-1,yi-1)

初始时, 由于a=q1*b+r1,即r1=a-b*q1,由序列{Rn}的通项公式Rn=R(n-2)-R(n-1)*q1,我们可以把a看做r(-1),

b看做,r0,那么对应于表达式ri=a*xi+b*yi,r(-1)=a=a*1+b*0=(1,0),r0=b=a*0+b*1=(0,1);

即r-1=a=(1,0)r0=b=(0,1)。这样便可一步步推出rn=(xn,yn),即为原方程的一组解。

因此有如下定理:

ab为非零整数,g=gcd(a,b),则方程

ax+by=g 总可以通过欧几里德算法找出一组可行整解,记为(x1,y1)。它的通解可以表示为:

(x,y)=(x1+k*b/g , y1-k*a/g) ,其中k为任意整数。

竞赛中常用的欧几里德扩展算法采用的是倒推的方法,相比而言,本章提供的方法需要的变量稍多,常数稍大(只大了一点点)。但由于易于用迭代实现,而且实际测试中两种算法时间差别十分微小,因此本算法仍有应用价值。

posted @ 2009-07-10 17:59 abilitytao 阅读(574) | 评论 (0)编辑 收藏

倾情奉献系列之最短路系列(POJ)

     摘要: 第一部分 Dijkstra 算法POJ 2387 ——Til the Cows Come Home最典型的最短路题目,求两点间的最短路径,一次Dij即可,代码如下: #include<iostream>#include<cmath>#include<cstdio>#include<algorithm>using namespace&nbs...  阅读全文

posted @ 2009-07-07 15:39 abilitytao 阅读(5208) | 评论 (12)编辑 收藏

POJ 1606-Jugs

     摘要: 本题的题意大致是:给你两个容器,指定它们的容量Ca,Cb,还有一个目标容量N;两个容器初始含水量都是零,问如何配制出容量为N的液体;我的做法很简单 BFS搜索,不过代码实在太长   在网上搜了一下 居然有一个500+B的代码 看得不是很明白 希望有牛人能够指点一下 //This is the source code for&n...  阅读全文

posted @ 2009-07-06 16:38 abilitytao 阅读(590) | 评论 (1)编辑 收藏

POJ 1056-IMMEDIATE DECODABILITY 解题报告

     摘要: 很久不做题目了 今天重新开始做 还颇费了一些时间 呵呵原题链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1056其实这道题 就是哈弗曼编码的问题 标准的做法是用树结构来模拟实现,与字典树的方法还有些神似。首先建立一个深度足够的满二叉树,然后按照长度由长到短的顺序,往里面添加路径(一边添加一边检查是不是前缀码),即0,往左走,1,往右走,把走过的所有...  阅读全文

posted @ 2009-07-06 13:42 abilitytao 阅读(1074) | 评论 (0)编辑 收藏

偏爱——张芸京

把昨天都作废 现在你在我眼前
我想爱 请给我机会
如果我错了也承担 认定你就是答案
我不怕谁嘲笑我极端

相信自己的直觉
顽固的人不喊累
爱上你 我不撤退

我说过 我不闪躲 我非要这麽做
讲不听 也偏要爱 更努力爱 让你明白
没有别条路能走 你决定要不要陪我
讲不听 偏爱 靠我感觉爱
等你的依赖 对你偏爱
痛也很愉快

把昨天都作废 现在你在我眼前
我想爱 请给我机会
如果我错了也承担 认定你就是答案
我不怕谁嘲笑我极端

相信自己的直觉
顽固的人不喊累
爱上你 我不撤退

我说过 我不闪躲 我非要这麽做
讲不听 也偏要爱 更努力爱 让你明白
没有别条路能走 你决定要不要陪我
讲不听 偏爱 靠我感觉爱
等你的依赖


不后悔 有把握 我不闪躲 我非要这麽做
讲不听 也偏要爱 更努力爱 让你明白
没有别条路能走 你决定要不要陪我
讲不听 偏爱 靠我感觉爱
等你的依赖 对你偏爱 爱
痛也很愉快

posted @ 2009-06-28 20:36 abilitytao 阅读(364) | 评论 (0)编辑 收藏

VC下显示位图的几种方法(转)

总结一下关于位图的几种用法。
说到这还是开头给大家介绍一下,有关位图的知识吧,以及对于我们比较有用的几个关于位图的结构体。
一.位图结构如下:
 

---- 一、BMP文件结构
---- 1. BMP文件组成
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
---- 2. BMP文件头
---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
---- 其结构定义如下: 
typedef struct tagBITMAPFILEHEADER
{
WORDbfType;   // 位图文件的类型,必须为BM
DWORD   bfSize;   // 位图文件的大小,以字节为单位
WORDbfReserved1;  // 位图文件保留字,必须为0
WORDbfReserved2;  // 位图文件保留字,必须为0
DWORD   bfOffBits; // 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
---- 3. 位图信息头 
BMP位图信息头数据用于说明位图的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
   DWORD  biSize;   // 本结构所占用字节数
   LONGbiWidth;  // 位图的宽度,以像素为单位
   LONGbiHeight; // 位图的高度,以像素为单位
   WORD   biPlanes; // 目标设备的级别,必须为1
   WORD   biBitCount// 每个像素所需的位数,必须是1(双色),
  // 4(16色),8(256色)或24(真彩色)之一
   DWORD  biCompression;   // 位图压缩类型,必须是 0(不压缩),
  // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
   DWORD  biSizeImage; // 位图的大小,以字节为单位
   LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
   LONGbiYPelsPerMeter;  // 位图垂直分辨率,每米像素数
   DWORD  biClrUsed;// 位图实际使用的颜色表中的颜色数
   DWORD  biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
---- 4. 颜色表 
    颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
typedef struct tagRGBQUAD {

BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
BYTErgbGreen;   // 绿色的亮度(值范围为0-255)
BYTErgbRed; // 红色的亮度(值范围为0-255)
BYTErgbReserved;// 保留,必须为0
} RGBQUAD;
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=24时,没有颜色表项。
   位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO {
   BITMAPINFOHEADER bmiHeader;   // 位图信息头
   RGBQUAD  bmiColors[1];  // 颜色表
} BITMAPINFO;
下面我们介绍第一种办法:
//第一种方法,使用WM__CTRLCOLOR来实现
/*******************OnCtlColor中添加的代码*****************/
HBRUSH CDemoBitmapDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
 // TODO: Change any attributes of the DC here
 //第一种实现方法
 if(nCtlColor=CTLCOLOR_DLG)
 {
  return brush;
 }
 // TODO: Return a different brush if the default is not desired
 return hbr;
}

BOOL CDemoBitmapDlg::OnInitDialog()
{
 //第一种方法,使用wm_ctlcolor来实现
 CBitmap bitmap;
 bitmap.LoadBitmap(IDB_BITMAP1);
 brush.CreatePatternBrush(&bitmap);//brush定义在头文件中CBrush burush
 bitmap.deleteobject();
}
第二种方法使用资源文件中导入的IDB_BITMAP来实现
第一步先在资源中导入一个位图:IDB_BITMAP1
void CDemoBitmapDlg::OnBtnBitmap()
{
 // TODO: Add your control notification handler code here
 /***************显示BITMAP的第二种方法**********************/
 HBITMAP hBitmap;
 CBitmap bitmap;
 CClientDC *pDC;
 pDC=new CClientDC(this);
 hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 bitmap.Attach(hBitmap);
 CDC CDCompatible;
 CDCompatible.CreateCompatibleDC(pDC);//创建兼容DC
 CDCompatible.Selectobject(&bitmap);
 /*********其它几种显示方式********/
/* pDC->BitBlt(0,0,200,200,&CDCompatible,0,0,SRCCOPY);
 CDCompatible.SetBkMode(TRANSPARENT);
 pDC->StretchBlt(0,0,352,288,&CDCompatible,0,0,352,288,SRCCOPY);
    CDCompatible.CreateCompatibleDC(this->GetDC());
    CDCompatible.Selectobject(&bitmap); */ //选择绘图对象
 BITMAP bmp;
 bitmap.GetBitmap(&bmp);
    pDC->StretchBlt(0,0,bmp.bmWidth,bmp.bmHeight,&CDCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    CDCompatible.deleteDC(); 
    ::deleteobject(&bitmap);
}
第三种方法是通过读取指定目录中的位图文件来显示(这里分别把它们显示在Picture控件和Static上面这也是大家通常要用到的):
void CDemoBitmapDlg::OnBtnPic()
{
 // TODO: Add your control notification handler code here
 /****************向PICTURE控件中动态添加位图****************************/
 HBITMAP hBitmap;
 CBitmap bitmap;
 hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 bitmap.Attach(hBitmap);
 m_Pic.SetBitmap(hBitmap);

}
/****************在STATIC中显示位图*********************/
void CDemoBitmapDlg::OnBtnStatic()
{
 // TODO: Add your control notification handler code here
 CBitmap hbmp;
 HBITMAP hbitmap;
 //将pStatic指向要显示的地方
 CStatic *pStaic;
 pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);
// pStaic=(CStatic*)GetDlgItem(IDC_BUTTON1);
 //装载资源 MM.bmp是我的一个文件名,用你的替换
 hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"NetFriend.bmp",
  IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 
 hbmp.Attach(hbitmap);
 //获取图片格式
 BITMAP bm;
 hbmp.GetBitmap(&bm);
 CDC dcMem;
 dcMem.CreateCompatibleDC(GetDC());
 CBitmap *poldBitmap=(CBitmap*)dcMem.Selectobject(hbmp);
 CRect lRect;
 pStaic->GetClientRect(&lRect);
 //显示位图
 pStaic->GetDC()->StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Height(),  &dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
 dcMem.Selectobject(&poldBitmap);
}
/*****************向BUTTON中添加ICON*****************************/
//方法和导入其它位图类似,在这里就只做一个说明一下就是了。
HICON hIco;
 hIco=AfxGetApp()->LoadIcon(IDI_ICON1);
 m_BtnBitmap.SetIcon(hIco);
第四种读取位图文件来显示位图:
void CDemoBitmapDlg::OnBtnBtmfile()
{
 // TODO: Add your control notification handler code here
 /*******************通过读取位图文件来显示位图**********************/
 CString strFileName;
 strFileName.Format("%s","NetFriend.bmp");
 //成位图信息BITMAPINFO
 BITMAPINFO *bitmapinfo=NULL;
 BYTE *BmpData=NULL;
 CFile file;//读取位图信息
 //设置文件的打开方式
 if(!file.Open(strFileName,Cfile::modeRead|Cfile::typeBinary))
 {
  return;
 }
 //BITMAP文件头结构体
 BITMAPFILEHEADER BitmapHead;
 //读取位图文件头
 if(file.Read(&BitmapHead,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER))
 {
  MessageBox("读取文件头失败!");
  return;
 }
 if(BitmapHead.bfType!=0x4d42)
 {
  MessageBox("对不起,您读取的不是位图文件!");
  return;
 }
 //位图信息
 BITMAPINFOHEADER  BitmapInfo;
 if(file.Read(&BitmapInfo,sizeof(BITMAPINFOHEADER))!=sizeof(BITMAPINFOHEADER))
 {
  MessageBox("读取位图信息失败!");
  return;
 }
 if(BitmapInfo.biBitCount!=24)
 {
  MessageBox("对不起,当前程序只支持24位位图信息!");
  return;
 }
 bitmapinfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)];
 if(!bitmapinfo)
 {
  MessageBox("内存分配失败!");
  return;
 }
 /*把BMP位图信息头中的数据读取到位图信息结构中去.*/
 memcpy(bitmapinfo,&BitmapInfo,sizeof(BITMAPINFOHEADER));
 /*用来得到位图文件的大小*/
 DWORD dataByte=BitmapHead.bfSize-BitmapHead.bfOffBits;
 BmpData=(BYTE*)new char[dataByte];
 if(!BmpData)
 {
  MessageBox("内存分配失败!");
  delete bitmapinfo;
  delete BmpData;
  return;
 }
 if(file.Read(BmpData,dataByte)!=dataByte)
 {
  MessageBox("读取位图数据失败!");
  return;
 }
 file.Close();
 CClientDC *pDC=new CClientDC(this);
 pDC->SetStretchBltMode(COLORONCOLOR);
 StretchDIBits(pDC->GetSafeHdc(),200,0,BitmapInfo.biWidth,BitmapInfo.biHeight,  0,0,BitmapInfo.biWidth,BitmapInfo.biHeight,BmpData,bitmapinfo,DIB_RGB_COLORS,SRCCOPY);
}
最后给大家介绍两个显示位图的特效的例子更多的特效显示(http://www.pconline.com.cn/pcedu/empolder/gj/vc/0504/608259.html):
1> 水平交错显示位图
void CListBmap::OnButton1()
{
 // TODO: Add your control notification handler code here
 HBITMAP hBitmap;
 CBitmap cBitmap;
 hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",  IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 cBitmap.Attach(hBitmap);
 cBitmap.GetBitmap(&bitmap);
 int i=0,j=0;
 CClientDC *pDC=new CClientDC(this);
 CDC memDC;
 memDC.CreateCompatibleDC(GetDC());
 memDC.Selectobject(&cBitmap);
 for(i=0;i<bitmap.bmHeight;i+=2)
 {
  j=i;
  while(j>0)
  {
   pDC->StretchBlt(0,j-1,bitmap.bmWidth,1,&memDC,0,bitmap.bmHeight-(i-j+1),    bitmap.bmWidth,1,SRCCOPY);
   pDC->StretchBlt(0,bitmap.bmHeight-j,bitmap.bmWidth,1,&memDC,0,i-j,    bitmap.bmWidth,1,SRCCOPY);
   j-=2;
  }
  Sleep(50);
 }

}

2>雨点显示:
void CListBmap::OnButton2()
{
 // TODO: Add your control notification handler code here

 HBITMAP hBitmap;
 CBitmap cBitmap;
 hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",  IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 cBitmap.Attach(hBitmap);
 cBitmap.GetBitmap(&bitmap);
 int i=0,j=0;
 CClientDC *pDC=new CClientDC(this);
 CDC memDC;
 memDC.CreateCompatibleDC(GetDC());
 memDC.Selectobject(&cBitmap);
 for ( i=0; i<=bitmap.bmHeight; i++ )  
 {
  for ( j=0; j<=bitmap.bmHeight-i; j++ ) 
   pDC->StretchBlt( 
   0,j, 
   //目标设备逻辑横、纵坐标 
   bitmap.bmWidth,1, 
   //显示位图的像素宽、高度
   &memDC, 
   //源位图设备情境对象
   0,bitmap.bmHeight-i, 
   //源位图的起始横、纵坐标 
   bitmap.bmWidth,1, 
   //源位图的像素宽、高度 
   SRCCOPY); 
  Sleep(20); 
 }
}

转自:http://blog.csdn.net/xyshu/archive/2008/08/20/2802162.aspx

posted @ 2009-06-14 14:37 abilitytao 阅读(553) | 评论 (0)编辑 收藏

AT89C51SND1(MP3核心器件)

主要内容:
本文介绍了以AT89C51SND1为核心的MP3播放器设计开发步骤,详细分析了MP3各个环节的功能实现,给出了多种实现其功能的方案。具体以AT公司提供的方案为例,详细作了分析,并介绍了关于AT89C51SND1在系统程序烧写的方法,以及MP3实现其功能的各种操作方法。

关键词:

功能简介 系统分析设计 外部通讯 FAT文件 程序烧写

简述:
随着科技的进步,MP3播放器已成为现代消费者首选的随身听产品,它以小巧玲珑的体积,精美的外形,低廉的价格及其强大的功能深得消费者的厚爱。这同时也引起了DIY发烧者的兴趣,他们不惜高价买进元器件,以自己组装的MP3为荣。国际上很多芯片制造商看准商机,开发出以自己生产的芯片为核心的MP3方案,并公布于众,这些核心芯片包括:ATJ-207X系列,AT9015系列,AT161系列,STMP341X系列等。其中,以ATMEL公司生产的AT89X51SND1系列芯片最为著名,这就包括AT89C51SND1.

功能强大的AT89C51SND1
AT89C51SND1单片机是ATMEL公司专门针对开发MP3而设计的,其主要特点是内部集成了MPEG2解码器和USB通讯接口,内含64k的内部程序存储器,支持在系统编辑ISP功能,通过USB或者串行口对芯片进行编程操作,内部数据存储器为2056字节。它最高支持20MHz的工作频率,工作电压为3V,内部集成的MPEG2解码功能支持48,44.1,32,24,22.05及16赫兹的采样序列,可直接与DAC音频转换芯片连接,支持USB1.1协议全速引擎,并提供相应的键盘中断、IDE/ATATPI /MMC及ISP接口。

系统分析设计:

目前MP3DIY主要有两种方案:使用DSP装配和使用专用MP3开发芯片。
DSP系统硬件设计麻烦,程序难以理解,购买DSP芯片的价格也较高,这些使MP3DIY爱好者们不约而同的选择了后一种方法。
国内流行的DIY方案很多,使用的专用芯片也是多种多样,但大部分方案整体上大致相同。以AT89C51SND1为核心的MP3系统主要实现一个MP3播放器的功能,整个系统由AT89C51SND1(MCU)、K9F1208UDF(FLASH芯片)或硬盘、音频转换部分、USB接口、外部控制、串行通讯、电源部分和录音部分组成。

MCU部分:即AT89C51SND1,控制整个系统,提供USB控制和MP3解码功能;
存储器:作为MP3播放文件的存储器;
音频转化部分:将数据流转化成声音信号;
外部控制:对MP3进行操作的外部中断按键;
通讯系统:包括USB及串口通讯。
外部显示:包括了LED发光管指示灯,液晶显示屏等。
电源部分: 为MP3提供所需要的电能;
外部音频输入部分:包括音频输入元件MIC及A/D转换芯片

下面我们具体来了解一下由ATMEL公司在网上公开提供的一款以AT89C51SND1为核心的MP3方案(以下称小板方案)。

电源部分:
整个开发板上的芯片统一采用3.3V供电,对开发板的供电采用两种形式:USB供电和电池供电

USB接口提供5V电压和200mA电流,Imax=500mA, AT89C51SND1C所需的电压为3V(偏差10%),25mA。若使用USB口供电,需将5V转化成3.3V。一般可以采用电阻分压和DC-DC芯片降压。因为MP3属于高速信息传输数码产品,能否有一个良好的电源对MP3使用的稳定性来说至关重要,因此一般采用芯片降压的供电方案,本方案选用的芯片为A1117,它输入电压为4.75-10V,最大输出电流为800mA,转换后输出电压为3.3V,是比较理想的USB电平转换芯片。

电池供电可采用两种方式:直接串接电池法和高频振荡升压法
前一种用两节1.5V的电池串联形成3V的电压直接接入MP3,这种方法不需要什么外围电路,芯片工作正常,但普通电池压降比较明显,当电池使用一段时间后,压降后的电压会导致MP3长期工作于不稳定的低压状态,对其音质和机体有很大的损害。

后一种则将1.5V的电压经高频振荡后送入电平转换芯片,将其转换成3.3V电压。这种方法是目前最常用的电源技术,它只需要一节电池供电,占用体积小,由于电压是经过高频振荡后转化而来的,所以电池的压降不会影响最终输出的电压,这也大大延长了电池的使用寿命,真正做到节能,是现代各种随身产品的首选供电方式。

 


在小板方案中,其电源转换主要是由SP6641(直流推进转换器)和SP6231(万用串列总线外围设备)构成,电路中,场效应管SI2312DS与按键SW5构成了电源开关控制电路,每触发一下SW5,SI2312DS将作导通和断开电源,电感L1和肖特基二极管BAT54S构成高频振荡电路,它将高频电流送入SP6231处理后,再由它送入SP6641进行直流电压转换,最终将3.3V电压送至整个设备。


直流电源]和数字电源的区别:在一些数字电路中,我们会发现会有DVDD(数字电源)和AVDD(模拟电源)两种电源,在小板方案中也不例外,这是因为一些芯片制造商在设计芯片时,为了让芯片工作于一个稳定的环境里,特意为其设计了专用电源DVDD。原则上,数字电源与模拟电源没有什么大的区别,但模拟电源工作的环境中,可能会出现大的压降或其他影响整个电源的情况。为保证系统的稳定性,通常在设计时,将数字电源和模拟电源分开设计,最后用一跳线将两个电源连接在一起,这样可以避免模拟电源对数字电源的影响,以保证系统的稳定性。
外部通讯系统:


外部通讯系统主要由USB通讯和串口通讯两种通讯方式,通过他们都可以进行程序烧写(51SND支持系统在线编辑功能),但通过USB接口还可进行文件的存储,即具有U盘通讯功能,所以一般直需要完成USB通讯接口就可以了。
串口通讯的实现:和其他的单片机串口通讯一样,要使用MAX232进行TTL电平转换,然后直接将信号送入51SND1的25,26脚(串行通讯接口),通过51SND1内部的程序支持和计算机上的软件来完成串口的信息通讯,串口通讯需要注意波特率问题,选用不当的波特率有可能造成通讯失败,最常用的波特率是9600和19200。


USB接口的实现则是通过51SND1自带的USB1.1协议通讯端口,它不需要使用飞利浦等公司生产的USB接口转换芯片,此方案则是通过两个27欧姆的电阻后直接接入51SND的21,22脚,这两个电阻的阻值是官方站对自己所开发的芯片提供的,最好使用精度高的电阻,否则,会因为电阻分压不当而导致计算机无法识别51SND芯片。该方案中,有一PNP三级管2N2907,它的作用是作为一个开关,在实现U盘功能时,I/O口将硬件响应信号送入三极管的基极,使其CE导通,电源VDD通过1.5K电阻拉高USB的D+端口电位,以告知计算机有新的硬件接入。我们在设计电路时,通常在三极管CE上设一跳线开管,在烧写MP3程序时,需手动拉高D+口电位。

 

外部音频输入部分:

89C51SND1芯片提供了外部录音功能,在程序的支持下,通过外部设备MIC及其模数转换芯片向其送入音频信息,51SND1将其转化成WAV文件后保存在存储器中,通过MP3放音功能可将其音频信息读出。该方案中,实现MIC到CPU转换的是MAXIM公司生产的MAX4468(增益带宽涌流器), 它的主要功能是将MIC的信号放大,并将其转化成数字信息,通过CPU将数字信息储存在存储器中,从而实现MP3的录音功能。

mp3音频转换部分:

AT89C51SND1支持PCM和I2S两种音频结构,音频数据流可以来自MP3解码的输出,也可以来自MCU直接的音频输出,和MP3解码部分类似,整个音频部分和51内核也通过5个寄存器来进行数据和控制信息的交流,这5个寄存器是:

1.音频接口控制寄存器0 AUDCON0 (AUDIO INTERFACE CONTROL REGISTER 0)
2.音频接口控制器 1 AUDCON 1 ( AUDIO INTERFACE CONTROL REGISTER 1 )
3.音频接口状态寄存器 AUDSTA (AUDIO INTERFACE STATUS REGISTER)
4.音频接口数据寄存器 AUDDAT (AUDIO INTERFACE DATA REGISTER)
5.音频时钟分频寄存器 AUDCLK (AUDIO CLOCK DIVIDER REGISTER )

当音频数据的第一位送入DA转换器的时候就会产生时钟信号。从MP3解码器送出的数据被送入MP3缓冲器,MP3的解码数据缓存和解码器通过一个握手信号进行通讯,可以通过AUDCON1寄存器中的DERQEN位来决定是否需要数据。

 

存储器:


目前市场上的MP3,其存储器是多种多样的,按照其存储器的不同,大致可分为:FLASH芯片存储,CF卡存储和硬盘存储三种。当然,不能否认还有一些使用的是碟片或者其它芯片存储。

FLASH芯片存储的MP3最常见,因为其体积小,存储速度快,耗电省等特点,已成为现在MP3存储器的首选(目前市场上的大部分MP3都使用这种存储器),本方案使用的FLASH存储器是韩国三星公司生产的K9F系列FLASH存储器,这些存储器从16M到256M不等,但价格比较高,一片64M的芯片售价是130元左右,256M的售价300多元,用户可根据需要来选择,但选用不同的FLASH芯片时,应注意程序兼容的问题,比如设定存储器的大小,FLASH存储器读出和写入的入口地址等等。

CF卡存储器最早应该是应用在数码相机上,它的特点是支持插拔,更换碟片容易,市场上很容易买到,其价格也比较便宜。这类MP3在市场上不常见,因为其体极大,存储量又不如硬盘,常用于数码摄像机机带MP3功能的存储器。但因为CF卡价格便宜,多为DIY者选用。

上边介绍的两种存储器存储量远远满足不了需要,于是人们便把目光投向了硬盘。一些公司看准商机,生产出专门用于MP3的微型硬盘,它的容量大小从几个G到几十个G,但此类MP3 目前售价较高,使很多MP3爱好者望尘莫及。在MP3DIY一族里,已经有不少高手使用普通硬盘完成了硬盘MP3,使用的CPU正是51SND1。51SND1与硬盘通讯的方法多种多样,最常用的方法是利用锁存器74373和38译码器74138作为接口扩展,32KRAM62256作为缓冲器与硬盘的IDE接口连接,由于硬盘需使用12V和5V两种电源,其耗电量也非常大,不适合随身携带,所以大部分DIY的硬盘MP3多是以台式的方式出现,并配上了液晶显示及功放电路。

用硬盘作为MP3的存储器要比使用FLASH芯片和CF卡复杂的多,不仅仅要了解硬盘接口的定义,在编写驱动程序时,还要完全读懂FAT文件,这个文件包括软盘数据的逻辑存储、硬盘中的数据组织、硬盘主引导记录(DBR)及其结构、引导记录及其结构、文件分配表FAT、文件目录表、分区表等等。要想完全看懂这些东西,必须要对计算机原理作充分的了解,理清程序算法,这些不亚于学好几门高等数学。在国内的DIY人群中,能看懂FAT文件,写出硬盘驱动的人也寥寥无几,大部分DIY者是使用别人写好的HEX文件。正因为这个原因,51SND1控制硬盘的源程序到目前还没有公开。若读者对此感兴趣,可到21IC网去下载硬盘FAT文件作具体分析,在此不多作介绍。

 


工作指示部分:

市场上的MP3都有一个漂亮的液晶屏来显示工作状态,如果自己DIY,所要使用的液晶屏都必须含驱动电路,其体积过大不易携带,所以大部分DIY者将这一部分省下了,取而代之的是4个LED发光管。通过程序控制,4个发光管分别表示不同的状态,由4个按键来控制整个MP3的工作过程。

程序部分:
MP3的强大功能与其程序是分不开的,没有合适的程序任何一个硬件都无法工作,关于MP3的程序设计在网上和一些相关的书籍上都有介绍,如果对其感兴趣,可到网上下在源程序研究,也可下在编译过的HEX程序直接进行烧写。


程序烧写:
前面已经介绍过,89C51SND1具有在系统编译功能,可用ISP端口控制,通过USB口或串口进行烧写,下面就一些程序烧写问题进行介绍:

1. 安装89C51SND1的在系统烧写软件flip2.2。

2. 通过开始菜单运行InstUsb.exe(建议在开始菜单中运行,否则会出现路径找不到,系统建议用2000,xp兼容性太差。)

 

3.将PCB板上的ISP接地,USB的D+电位拉高(即短接三极管CE两脚),注意一定要过1.5K电阻,否则硬件不能被识别。


4.连接USB线(或串口线),出现硬件响应后选择自动安装程序。

5.打开flip2.2,选择芯片为AT89C51SND1,连接方式为USB(或串口)。

6.将SBV中的F0改为FC,调入所要烧写的HEX文件(文件所在路径中不能含有中文)。


7.进行烧写后,即可完成自己的MP3。

Mp3功能操作:
本方案中共有4个按键:
S1: 播放/停止/确定键
S2: NEXT键
S3: BACK键
S4: 功能选择键

其指示灯也表示4种状态:
L1: 播放指示灯/音量大小
L2: 录音指示灯/高音
L3: U盘联机指示灯/中音
L4: 格式化指示灯/低音

用选择键选取相应功能的指示灯按确定键即可实现其功能,在播放过程中,可用S2和S3来选择上一首和下一首歌曲。若在播放中按选择键,播放指示灯便会高速闪烁,此时可按S2和S3控制音量大小,若继续按选择键,可依次调节高、中、低音效控制。

U盘功能:停止播放歌曲,选择U盘联机功能,按确定即可作为U盘使用,在此可为MP3增加歌曲和存储其它文件。

注:U盘功能在2000以上系统免驱,其它系统必须到ATMEL公司的网站下载相应的驱动程序。


总结:
本文系统的介绍了关于ATMEL公司生产的89C51SND1芯片开发MP3功能的方法,但对于89C51SND1来说,实现MP3只是它强大功能的一部分,还需要广大DIY爱好者深入开发,但51SND还有很多不足之处。有不少使用者反映,89C51SND1的数据传输速度跟不上,用其开发硬盘MP3易出现声音 断断续续的。除此以外,51SND1的稳定性也不好,长期的上电掉电会导致51SND1内部程序混乱,更有甚者成为“老年痴呆症患者”。但51SND1强大的功能早已弥补了这一点的不足,在当今MP3DIY爱好者中,89C51SND1仍然是装备MP3的首选芯片。

 

参考资料:
《51系列单片机高级实例开发指南》 作者:李军 北京航空航天大学出版社
AT89C51SND1芯片说明 ATMEL www. ATMEL .com
AT89C51SND1硬件电路设计 ATMEL www. ATMEL .com
AT89C51SND1控制硬盘硬件电路 蓝牙 www. mp3DIY .com
EMU控制硬盘方案 未知 www. 21IC .com
硬盘FAT资料 未知 www.21IC.com
MP3程序烧写资料 未知 安然技术论坛

posted @ 2009-06-06 23:54 abilitytao 阅读(1378) | 评论 (0)编辑 收藏

Setimer和Ontimer的使用(转)

关于OnTimer()函数的填写,对于CDialog,可以Ctrl+W中添加;

对于SetTimer可以在初始化当中添加!

OnTimer()函数是响应用SetTimer()函数设定的时钟发送的时钟消息的,你没设定时钟,就不会有时钟消息,OnTimer()里的语句当然也不会被调用。

为类添加VM_TIMER消息响应,会看到类中多了个OnTimer(UINT nIDEvent)。
然后用SetTimer(1,10,NULL)就行了。第一个参数是ID,第二个是间隔时间,单位是毫秒,第3个是响应函数,因为要在OnTimer(UINT nIDEvent)里面做响应操作,所以此处给个NULL就行了

Timer事件,即定时器事件,是在游戏编程中,经常使用的一个事件。借助它可以产生定时执行动作的效果。这篇文章,就和大家一起探讨一下如何使用SetTimer()函数。
1、SetTimer定义在那里?

SetTimer表示的是定义个定时器。根据定义指定的窗口,在指定的窗口(CWnd)中实现OnTimer事件,这样,就可以相应事件了。

SetTimer有两个函数。一个是全局的函数::SetTimer()

UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);

其中hWnd 是指向CWnd的指针,即处理Timer事件的窗口类。说道窗口类(CWnd),我们有必要来看一下CWnd的继承情况:CWnd有以下子类:CFrameWnd,CDialog,CView,CControlBar等类。这也意味这些类中都可以定义SetTimer事件。

同时,SetTimer()在CWnd中也有定义,即SetTimer()是CWnd的一个成员函数。CWnd的子类可以调用该函数,来设置触发器。

UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );

参数含义:

nIDEvent:是指设置这个定时器的iD,即身份标志,这样在OnTimer()事件中,才能根据不同的定时器,来做不同的事件响应。这个ID是一个无符号的整型。

nElapse

是指时间延迟。单位是毫秒。这意味着,每隔nElapse毫秒系统调用一次Ontimer()。

void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD)

Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application’s message queue and handled by the CWnd object。

意思是,指定应用程序提供的TimerProc回调函数的地址,来处里这个Timer事件。如果是NULL,处理这个Timer事件的定义这个Timer的CWnd对象。他将WM_TIMER消息传递给这个对象,通过实现这个对象的OnTimer()事件来处理这个Timer事件。

所以,一般情况下,我们将这个值设为NULL,有设置该定时器的对象中的OnTimer()函数来处理这个事件。

同样的,我们再看看KillTimer()和OnTimer()的定义:

KillTimer同SetTimer()一样,他也有两个,一个是全局的::KillTimer(),另一个是CWnd的一个函数。他的声明如下:


//全局函数

BOOL KillTimer(
HWND hWnd, // handle of window that installed timer
UINT uIDEvent // timer identifier
);

//CWnd函数

BOOL KillTimer( int nIDEvent );

这两个函数表示的意思是将iD为nIDEVENT的定时器移走。使其不再作用。其用法如同SetTimer()一样。

再看看OnTimer()

CWnd::OnTimer
afx_msg void OnTimer( UINT nIDEvent );

ontimer()是响应CWnd对象产生的WM_Timer消息。nIDEvent表示要响应TIMER事件的ID。

2、Timer事件的使用:

由以上的分析,我们应该很清楚,如何来使用Timer事件。假定我们在视图上画一个渐变的动画。我们首先在菜单栏上添加一个菜单项,给这个菜单添加命令响应:

pView->SetTimer(1,1000,NULL);//pView是视图类的指针,这里是在视图类当中设置一个定时器。

添加完毕,再给视图类添加一个WM_Timer事件的相应。在OnTimer()函数中编写汉书,进行相应。

如此,就能做出动画。

posted @ 2009-06-02 00:09 abilitytao 阅读(10472) | 评论 (0)编辑 收藏

坦克究竟该怎么写嘛?

这学期学了MFC,期末老师布置我们写个游戏。我选了坦克大战,上课的时候觉得老师讲的挺简单的,都能听懂,但是真正写起来却发现自己无从下手了,我个人的设计思路是这样的:
首先写个坦克类,里面有坦克的坐标,速度,还有装载的位图。再写个子弹类,每个坦克里面包含一颗子弹。
写消息映射,上下左右,分别控制坦克移动,空格键发射子弹;任何一个消息事件,均触发重绘,将屏幕刷新;

可是,之后该怎么办,我就无从下手了,因为,还有敌方的坦克,我的子弹打出去,地方坦克难道就不动了吗?这显然不可能啊~更何况,敌方坦克的AI要怎么写呢?我想,可能是由于上课的时候很多消息都没有学到造成的吧,不知道有没有牛人可以指点我一下呢。
感激不尽~

posted @ 2009-06-01 12:59 abilitytao 阅读(492) | 评论 (2)编辑 收藏

仅列出标题
共42页: First 28 29 30 31 32 33 34 35 36 Last