原创 单片机的正弦信号产生中改变正弦信号频率时仍旧保持采样频率的算法

2006-9-26 21:32 4569 12 13 分类: 工程师职场

单片机的正弦信号产生中改变正弦信号频率时仍旧保持采样频率的算法



//*********************************************************************************//
//正弦信号发生;


//实现单片机:SPCE061A;


//用61板即可直接下载使用;
//可按固定频率步进(在程序中步进值为f0,改变f0可改变步进值);
//可按固定电压进行幅度步进(在程序中值为A0,改变A0可改变幅度步进值);
//取点的采样频率fs为固定值32kHz,这样可以使输出端接的模拟滤波器的设计变得简单;
//61板,P_DAC1输出,KEY1:调整锁(按一次KEY1,可以调整频率,再按一次,可以调整幅度,再按一次,不能调整);KEY2:上调;KEY3:下调;
//由有限字长效应,频率不会很准确,但误差很小;
//!!!!注意:工作在最高频率下,并且要求时钟一直这么工作,所以要把系统时钟设置为强振模式(*osc = 0x98)
//!!!!BUG1:由于计算级数很少(只算了两级),低频(50Hz以下)时相对误差大;
//!!!!BUG2:由于按键调频率时要关中断,所以,在每次频率改变时信号输出会有一段时间的中止(计算x2,k和对x赋0的时间);
//实现算法:递归法;
//差分方程:y(n)=k*y(n-1)-y(n-2);
//k=2*cos(omiga)-------omiga:数字频率,omiga=2*pi*f0/fs;
//初始y(n-2):y(n-2)=-A*sin(omiga);
//**********************************************************************************//


#define pi 3.14
#define f0 5
unsigned int *p0=(unsigned int *)(0x7000);
unsigned int *p0d=(unsigned int *)(0x7002);
unsigned int *p0a=(unsigned int *)(0x7003);
unsigned int *oscu=(unsigned int *)(0x7013);
unsigned int *t0=(unsigned int *)(0x700a);
unsigned int *t0u=(unsigned int *)(0x700b);
unsigned int *intu=(unsigned int *)(0x7010);
unsigned int *intc=(unsigned int *)(0x7011);
unsigned int *dau=(unsigned int *)(0x702a);
unsigned int *da0=(unsigned int *)(0x7017);
unsigned int *da1=(unsigned int *)(0x7016);
unsigned int *wdogc=(unsigned int *)(0x7012);



unsigned int key_num,key_mode,key_have,key_plus,fast;
unsigned int f=400;
unsigned int fs=42000;
unsigned int Fs;
int Am=20000;
unsigned int A0=200;
double omiga;
long x;
long x1;
unsigned int k;
long x2;


unsigned int Init_MCU()
{
 *p0d=0;
 *p0a=0;
 *p0=0;
 key_num=0;
 key_mode=0;
 key_have=0;
 key_plus=0;
 fast=0;
 __asm("int off");
 *oscu=0x98;    //设置采样频率的中断
 *t0u=0x30;
 Fs=fs/1000;
 *t0=65535-24576/Fs;
 *intu=0x1000;
 //初始输出频率定为f;
 fs=Fs*1000;
 omiga=2*pi*f/fs;
 x2=(int)(-Am*omiga);   //这里本来是调用正弦函数的,但函数运算的级数太多,这里因为omiga很小,所以sin(omiga)几乎等于omiga,利用这个,把正弦值直接用omiga值代替;
 k=(int)(32768-omiga*omiga*16384); //这里本来是调用余弦函数,同上面,级数不用太多,用cos(omiga)约等于1-omiga*omiga/2;
 x1=0;
 __asm("irq on");
}


//定时器中断,实现递推过程;
void IRQ1(void) __attribute__ ((ISR));
void IRQ1(void)
{
  x=((k*x1)>>14)-x2;
  x2=x1;
  x1=x;
  *da0=x1+32000;
  *da1=*da0;
  *intc=0x1000;
}  
//扫描键盘;
void Scan_key()

 if(*p0==0)
 {
  key_plus=0;
  key_num=0;
  key_have=0;
 }
 if(*p0==1)
 {
  if(key_have==0)
  {
   if(key_num<1000)
    key_num++;
   else
   {
    key_num=0;
    key_have=1;
    if(key_mode<2)
     key_mode+=1;
    else
     key_mode=0;
   }
  }
 
 }
 if(*p0==2)
 {
  if(key_num<1000)
   key_num++;
  else
  {
   key_num=0;
   if(key_mode==1)
   {
    key_have=1;
    
   // 频率增加f0Hz
    __asm("int off");
    if(f<(fs/8-f0))
    {
     f+=f0;
     omiga=2*pi*f/fs;
  x2=(int)(-Am*omiga);   //这里本来是调用正弦函数的,但函数运算的级数太多,这里因为omiga很小,所以sin(omiga)几乎等于omiga,利用这个,把正弦值直接用omiga值代替;
  k=(int)(32768-omiga*omiga*16384); //这里本来是调用余弦函数,同上面,级数不用太多,用cos(omiga)约等于1-omiga*omiga/2;
     x1=0;
     __asm("irq on");
    }
    else 
     __asm("irq on");
   }
   if(key_mode==2)
   {
    key_have=1;
    
   // 幅度增加A0
    __asm("int off");
    if(Am<31000-A0)
    {
     Am+=A0;
  x2=(int)(-Am*omiga);
     x1=0;
     __asm("irq on");
    }
    else 
     __asm("irq on");
   }
   
  }
 }
 
 if(*p0==4)
 {
  if(key_num<1000)
   key_num++;
  else
  {
   key_num=0;
   if(key_mode==1)
   {
    key_have=1;
    
   // 频率减小f0Hz
    __asm("int off");
    if(f>f0)
    {
     f-=f0;
     omiga=2*pi*f/fs;
  x2=(int)(-Am*omiga);
  k=(int)(32768-omiga*omiga*16384);
     x1=0;
     __asm("irq on");
    }
    else 
     __asm("irq on");
   }
   if(key_mode==2)
   {
    key_have=1;
    
   // 幅度减小A0
    __asm("int off");
    if(Am>A0)
    {
     Am-=A0;
  x2=(int)(-Am*omiga);
     x1=0;
     __asm("irq on");
    }
    else
     __asm("irq on");
   }
  }
 }
}


int main()
{
 Init_MCU();
 while(1)
 {
  *wdogc=1;
  Scan_key();
 }
}


 




系统分类:单片机
用户分类:无分类
标签:采样频率 单片机 正弦 频率 算法

发表评论 阅读全文(110) | 回复(1)
PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1547295 2007-3-14 22:44

好啊不错啊
相关推荐阅读
用户1099365 2007-08-16 21:08
当前电池现状专题
最近因项目需要,查找了一些关于电池的信息,总结如下,也希望对大家有些用处。目前市面上的几种电池性能比较:技术参数<?xml:namespace prefix = o ns = "urn:sche...
用户1099365 2007-06-07 20:42
『ZZ』千千万万的IT开发工程师路在何方
  恭喜,你选择开发工程师作为自已的职业!  悲哀,你选择开发工程师作为自已的职业!    本文所指的开发工程师,仅指程序开发人员和以数字电路开发为主的电子工程师。当你选择计算机或者电子、自控等专业进...
用户1099365 2006-11-27 22:02
给中国高校的一封信
给中国高校的一封信——请培养21世纪企业需要的人才李开复引言自从1998年回到中国以来,我几乎走遍了中国所有知名大学的校园,和千百位工作在教学、科研第一线的院系领导、教授、讲师晤谈,通过演讲、座谈、网...
用户1099365 2006-11-15 19:56
FPGA设计的四种常用思想与技巧
本文讨论的四种常用FPGA/CPLD设计思想与技巧:乒乓操作、串并转换、流水线操作、数据接口同步化,都是FPGA/CPLD逻辑设计的内在规律的体现,合理地采用这些设计思想能在FPGA/CPLD设计工作...
用户1099365 2006-10-26 20:12
[转贴]自制电脑红外线接口电路
最近想做这么个东西来着,刚好看到这么一篇文章,觉的很有参考价值,转过来研究研究!红外线通讯是一种廉价、近距离、无连线、低功耗和保密性较强的通讯方案,在PC 机中主要应用在无线数据传输方面,但目前已经逐...
用户1099365 2006-10-26 20:07
OpenOCDasflash-programmingSoftware
看到的一片国外牛人写的如何用OpenOCD对ARM的flash编程。网址:http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/ope...
EE直播间
更多
我要评论
1
12
关闭 站长推荐上一条 /3 下一条