/**********************************************************************************
作者: 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
=====================================================================================================*/