基于SPI2M采样速率ADC信号处理经验分享--滤波算法、精度补偿技术(源程序,调试通过!

chenky   2010-9-17 11:08 楼主
/**********************************************************************************
 作者: keyong chen  
 时间: May. 2009
 文件: prg.c
 硬件: ADuC7021,ADS1675、DAC9881、RS485
开发环境:Keil C for ARM
 描述: 软件部分设计重点而且难点有以下几点:
     1、采用软件Σ-Δ技术提高现有DAC的分辨率;
     2、双通道DAC实现高精度直流电压源与电流源;
     3、实现复杂的数字信号处理算法(如二阶吧特沃斯滤波等);
     4、输出信号精度补偿(如温度补偿和常规误差补偿)算法。
*********************************************************************************/
#include<ADuC7021.h>
#include <stdio.h>  
#include <math.h>
#define k1   0.99              // 调节启动信号的幅频
#define k2   0.01     
/*====================================================================================================
    变量定义 
=====================================================================================================*/
unsigned char txDat2=0x00;       // The Tx high byte
unsigned char txDat1=0x00;       // The Tx mid byte
unsigned char txDat0=0x00;       // The Tx low byte
unsigned char rxDat2=0x00;       // The Rx high byte
unsigned char rxDat1=0x00;       // The Rx mid byte
unsigned char rxDat0=0x00;       // The Rx low byte
long rxDat=0x00;                 // The Rx full byte
unsigned int txDat=0x00;         // The Tx full byte
long sum1=0x00;
long val=0x00,sum3=0x00;
double val1=0.0;sum2=0.0; 
long value_buf1[2]={0x00};
unsigned char value_buf2[3]={0x00};
int i=0,j=0,num=1,empty=1,count; 
/*====================================================================================================
    Main Program 
=====================================================================================================*/         
int main (void) {
 SysClkInit();                       // CPU时钟初始化
 REFCON=0x01;              // 内部参考电源2.5V连接到VREF引脚输出
 GP1CON=0x02220011;        // 定义P1.6 ,P1.5and P1.4 工作在 SPI 模式,设置P1.0 和 P1.1分别为 tx & rx,P1.2为RS-485切换控制信号
 GP1DAT=0x84840000;         // 定义P1.7(DACS)和P1.2为输出
 GP2DAT=0x01010000;         // 定义P2.0(DACS)为输出,控制ADCNV
 GP0DAT=0xA0A00000;         // 定义P0.5和P0.7(ADCS)为输出,分别控制DAC复位和ADC的/CS
// GP0SET=0x00200000;        // P0.5置高,上电复位DAC9881
// Delay(20);          
// GP0CLR=0x00200000;
// Delay(20);
// GP0SET=0x00200000;
// Delay(20);
 GP1SET=0x00040000;         // P1.2置高,使能RS-485 通讯,切换为发送状态
// SPICON=0x1047;          // 定义SPI为主机模式          
 SPIDIV=0x01;            // 设置 SPI 时钟,分频公式:40960000/(2x(1+SPIDIV))
 // Setting up UART at 115200bps (CD=0,DL=1)
 COMCON0=0x80;                     // 设置分频系数寄存器访问设置位(DLAB),使能访问COMDIV0和COMDIV1
 COMDIV0=0x0B;         // 设置DIV0和DIV1,计算分频数DL值=1
  COMDIV1=0x00;
  COMCON0=0x07;         // 使能访问COMRX和COMTX,数据长度为8位,使用2位停止位
 COMDIV2=0x883E;         // 41.78MHz/(16*2*2^CD*DL*(M+N/2048))
             // CD=0 DL=0B=11
             // 115.2Kbps M+N/2048 =1.0303 M=1, N=62=0x3EH=000 0011 1110
             // comdiv2=0x883E
  // DAC configuration         
 DAC1CON=0x13;                        // 配置DAC
                            // 范围在0~AVdd/AGND
                            // 时钟下降沿时更新DAC1
 DAC1DAT=0x08000000;                       // start from midscale 
 SysInit();                        // 系统初始化
 while(1)
 {
 SPICON=0x00;
 SPICON=0x47;         // 使能 SPI
 GP2SET=0x00010000;        // P2.0置高(ADCNV)
// Delay(0);          // 延时时间必须大于62.5ns
 GP2CLR=0x00010000;        // ADCNV 置低,开始转换数据
    delay(21);              // 延时时间必须大于5.55us
/* __asm
 {
  nop;
  nop;
  nop;
 }
*/   
 GP0CLR=0x00800000;        // 将/CS(P0.7)置低,开始发送数据
 SPITX=0x00;          // 写入SPI寄存器以启动一次数据发送
  while(!(SPISTA & 0x08)) ;
// while((SPISTA & 0x10) != 0x10);           // wait for data in the RX MMR
// Delay(1);
 rxDat2=SPIRX;
 SPITX=0x00;          // 写入SPI寄存器以启动一次数据发送
  while(!(SPISTA & 0x08)) ;
// while((SPISTA & 0x10) != 0x10);           // wait for data in the RX MMR
// Delay(1);
 rxDat1=SPIRX;
 SPITX=0x00;          // 写入SPI寄存器以启动一次数据发送
  while(!(SPISTA & 0x08)) ;
// while((SPISTA & 0x10) != 0x10);           // wait for data in the RX MMR
// Delay(1);
 rxDat0=SPIRX; 
 GP0SET=0x00800000;
  
 rxDat=(((rxDat2 & 0xFF)<<16)+((rxDat1 & 0xFF)<<8)+(rxDat0 & 0xFF));
// rxDat = 0x7FFFFF;
 if(rxDat>0x7FFFFF)           // 计算公式为:txDat = rxDat/2+2.5
 {
  rxDat=-(0xFFFFFF-rxDat+1);
//  txDat=0x20000-val*0.015625;
//  txDat=0x20000-val*0.009375;
//  txDat=0x20000-val*0.013375;
 }
 
 value_buf1 = rxDat;       // 控制系统稳定时间和超调量,延时1.2us
    if (i == 1)
  {sum1 = (k1*value_buf1[1]+k2*sum1);i = 0;}
   else
   {sum1 = (k1*value_buf1[0]+k2*sum1);i = 1;}
 val=sum1>>6;
 txDat=0x20000+val;        // 发送数据给18位DA
// val1=sum1*0.015625-val;
// txDat12=0x800+val1*1638.4;      // 发送数据给12位DA,延迟9.8us
/* val1=rxDat*0.015625;
 val1=modf(val1,&val);
 txDat=0x20000+val;        // 发送数据给18位DA
 txDat12=0x800+val1*1638.4;      // 发送数据给12位DA,延迟9.8us
*/
 SPICON=0x00;
 SPICON=0x1043;           // Configure SPI as Master, clock idles high
 //configure the high byte to be sent   
 txDat2=(txDat>>16);        // Copy the first 4 bits of data into the last 4 bits of txDat2
 txDat-=(txDat2<<16);
 //configure the mid byte to be sent        
 txDat1=(txDat>>8);         // Copy the first 4 bits of data into the last 4 bits of txDat1
 txDat-=(txDat1<<8);
 //configure the low byte to be sent
 txDat0=(txDat);            // Copy the last 4 bits of data into the first 4 bits of txDat0
// txDat0&=0xf0;           // Insure the first 4 bits of data in txDat0 are empty
 //send the data         // Delay 50ns,one clock is 0.28us
 GP1CLR=0x00800000;        // Pull DACS Low
 SPITX=txDat2;
// while((SPISTA & 0x02)!=0x02);
// while(SPISTA & 0x01);
 __asm
 {
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
 }
 SPITX=txDat1;
// while((SPISTA & 0x02)!=0x02);
// while(SPISTA & 0x01);
 __asm
 {
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
  nop;
 }
 
  SPITX=txDat0;
// while((SPISTA & 0x02)!=0x02);
// while(SPISTA & 0x01);
 delay(1);
 GP1SET=0x00800000;        // Pull DACS High
  
// DAC1DAT=(txDat12<<16);        // 内部DAC输出,9.8us
 if(empty==1)
 {
   if(j==0)
   {
    value_buf2[0]=rxDat2;
    value_buf2[1]=rxDat1;
    value_buf2[2]=rxDat0;
   }
   else
   {
    sum3=sum2/(j-1);
    value_buf2[0]=(sum3>>16);sum3-=(value_buf2[0]<<16);
    value_buf2[1]=(sum3>>8 );sum3-=(value_buf2[1]<<8 );
    value_buf2[2]=(sum3);
    j=0;
    sum2=0.0;
   }
  
   empty=0;  
 }
 
 switch(num)             // 二阶博特沃斯滤波,延时24us,输出频率为80Hz
 {   
  case  75:COMTX=0x0D;break;
  case 150:COMTX=value_buf2[0];break;
  case 225:COMTX=value_buf2[1];break;     
  case 300:COMTX=value_buf2[2];empty=1;num=0;break;
 
  default :sum2+=sum1;j++;
  }
 num++;
    }
           
 return 0;
}
/*====================================================================================================
    ADCpoweron
=====================================================================================================*/
void ADCpoweron(int time)
{
 ADCCON=0x20;                   // 启动ADC
 while(time>=0)                     // 等待ADC完全启动
    time--;
}
void SysClkInit(void)
{
 PLLKEY1=0xAA;
 PLLCON=0x01;            //PLL配置 
 PLLKEY2=0x55;
 POWKEY1=0x01;
 POWCON=0x00;           //CPU时钟配置为41.78MHz
 POWKEY2=0xF4;
}
void SysInit(void)
{
 SPICON=0x1043;           // Configure SPI as Master, clock idles high
 //send the data         // Delay 50ns,one clock is 0.28us
 GP1CLR=0x00800000;        // Pull DACS Low
}
void delay (int length)
{
while(length>=0)
    length--;
}
/*====================================================================================================
     End Of File
=====================================================================================================*/

回复评论 (2)

来看看
点赞  2010-9-17 11:33
必须留下足迹
生命不息奋斗不止
点赞  2011-8-10 16:58
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复