原创 关于C8051F005DA输出抖动问题解决办法

2009-11-4 12:06 2647 4 4 分类: MCU/ 嵌入式

今天做一个AD采样DA还原程序的程序。用正选波输入DAC0输出。刚开始用  DAC0 = ADC0;直接将采样输出。结果输出波形隔一小段就有一个小跳变。开始以为是内部基准电压不稳定造成。遂换成外部基准电压,但是问题依旧。后经细致研究发现DAC0=ADC0的输出方式是先DAC0H=ADC0H,再DAC0L=ADC0L;这也问题就来了。因为C8051F在定义为sfr16 DAC0的时候就会先付高位值在付低位值。而C8051F是在付完高位值即更新DAC输出数据。所以就会造成高地位错位。但是将其改为 result = ADC0;                       //数据转存
    DAC0L=result&0x00ff;
 DAC0H=result/256;
这样子即下面代码中的红色位置即可保证16位数据正确输出,经测试输出正常。
//************************************************************
//             AD采样DA还原程序
//
// (1)使用C8051F005芯片
// (2)内部晶振16MHZ ,外部参考电压2.425
// (2)单端输入ANIO,用定时器3启动AD转换
//*************************************************************
#include <C8051F000.h>              
#include <stdio.h>
#include <intrins.h>
sfr16 TMR3RL   = 0x92;                   //定时器 3 重载寄存器
sfr16 TMR3     = 0x94;                   //定时器 3 寄存器
sfr16 ADC0     = 0xbe;                   //ADC0寄存器
sfr16 ADC0GT   = 0xc4;                   //ADC下限数据寄存器
sfr16 ADC0LT   = 0xc6;                   //ADC上限数据寄存器
sfr16 DP       = 0x82;                 // 数据指针
sfr16 RCAP2    = 0xca;                 // 定时器2捕捉寄存器
sfr16 T2       = 0xcc;                 // 定时器 2
sfr16 DAC0     = 0xd2;                 // DAC0 数据


                           
#define SYSCLK       16000000            //系统时钟 频率  
#define SAMPLE_RATE  50000            
//#define VREF         2.425                //参考电压值
 
void ADC0_Init (void);                      //AD转换初始化设置函数
void Timer3_Init (int counts);                  //定时3初始化设置函数
void ADC0_ISR (void);                      //AD转换中断函数
void delay (int t);                           //延时程序
//void SYSCLK_Init (void);                    //系统时钟函数
void WDT_CLOSE(void);                    //关闭看门狗
 
int result;               //数据存储
char  flag;             //标志
unsigned char k;
//***********************************************************
//关闭看门狗
//***********************************************************
void WDT_CLOSE(void)
{  EA="0";
   WDTCN = 0xde;                      
   WDTCN = 0xad;                    
   EA="1";
 }
//***********************************************************
//系统时钟设置
//晶振振荡方式,F>6.7MHz
//选用外部时钟
//允许时钟复位
//************************************************************
//void SYSCLK_Init (void)
//{  int i;
                             
//   OSCXCN = 0x67;                    
//   for (i=0; i < 256; i++)  ;          
//   while (!(OSCXCN & 0x80)) ;         //等待外部准备     
 //  OSCICN = 0x88;                     
                                     
// }
//***********************************************************
// 定时器3 初始化设置
// 1 系统时钟
//************************************************************
void Timer3_Init (int counts)
{
   TMR3CN  = 0x02;                  //计数器/定时器3使用系统时钟                
   TMR3RL  =-counts;                            
   TMR3    = 0xffff;                               
   EIE2   &= ~0x01;                 //T3中断允许关(扩展中断允许, 允许定时器3中断)           
   TMR3CN |= 0x04;                  //定时器3开            
}
//**********************************************************
//AD初始化设置
//AIN0 独立输入
//使用内部参考电压, PGA= 2,使用4系统时钟
//转换数据右对齐
//**********************************************************
void ADC0_Init (void)
{
   ADC0CN = 0x44;                   //右对齐          
   //REF0CN = 0x03;                   //使用内部参考电压
   REF0CN = 0x02;                   //使用外部参考电压           
                                      
   AMX0SL = 0x00;                   //AIN0 独立输入
   AMX0CF = 0x00;   
          
   ADC0CF = 0x60;                   // 8系统时钟           
   ADC0CF|= 0x00;                   // PGA 增益 1
   EIE2  |= 0x02;                     // ADC0转换结束中断开           
}
//**********************************************
//AD转换程序
//**********************************************
void ADC0_ISR (void) interrupt 15
{   
   TMR3CN &=0x20;                   //关定时器3  清除标准位
   ADCINT = 0x00;                   //清除中断标准位
   //delay (10);                           //延时等待AD转换稳定
  
    result = ADC0;                       //数据转存
    DAC0L=result&0x00ff;
 DAC0H=result/256;
  // DAC0 = ADC0;
  //  _nop_();
   TMR3CN |= 0x04;                    //定时器3开
   flag = 1;
  }
//***********************************************
//延时子程序
//***********************************************
void delay (int t)
{ int i,j;
     for (i=0;i<t;i++)
           for(j=0;j<10;j++) ;
}
//***********************************************
//端口设置
//***********************************************
//void Port_Init (void)
//{
// XBR2 = 0x40;         // 若上拉使能
// PRT0CF |= 0xff;       //P0口使能
//}
//******************************************
//MAIN
//******************************************
void main (void)      
  {
    floAT voltage="0";
    WDT_CLOSE();                       //关闭看门狗 
    OSCICN = 0x97;      //内部振荡器典型频率为16MHz
 // SYSCLK_Init ( );                      //系统时钟设置
 //Port_Init ();     //IO口输出使能设置
 Timer3_Init (15);//SYSCLK/SAMPLE_RATE);  //定时器3初始化设置  
    ADC0_Init ();                         //AD初始化
    ADCEN = 1;                          //AD转换允许打开
 DAC0CN = 0x80;                   // DAC0控制寄存器,DAC0使能;DAC0数据字的高4位在DAC0H[3:0],低字节在DAC0L中
 EA = 1;                         
    flag = 0;
    while (1)                          //循环
       {                       
         while (flag == 1)
     { flag = 0;
      
       //DAC0=result;      
       }
   }
}
本文来源于大道无极 http://www.dadwj.cn/ , 原文地址:http://www.dadwj.cn/post/492.html



 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条