zgh98765
2015-07-31 09:44
浏览 3.4k

c8051f020的12位AD采样

/*******************************************************************************
程序测量电压在外部ADC输入和打印  
/ /结果通过UART终端窗口。 
/ /系统时钟使用内部24.5 mhz振荡器成倍增加  
/ / 49 mhz的芯片上的锁相环。结果输出到UART的循环 
/ /设定的速度基于定时器2的延迟。这个循环定期读取 
/ / ADC值从一个全局变量,结果。
/ / ADC使重复测量速度取决于SAMPLE_RATE使用  
/ /定时器3。每个ADC转换启动一个中断运行一个  
/ /平均函数。< INT_DEC >样品平均然后结果值更新。
/ /每4的< INT_DEC >,你获得1点有效的决议。  
/ /例如,< INT_DEC > = 256获得你4位分辨率:4 ^ 4 = 256。
/ / ADC输入多路复用器将是单端输入
************************************************************************************/

#include // SFR declarations
#include
#include
/*******16位寄存器定义**********/
sfr16 ADC0 = 0xbe; //ADC0数据
sfr16 RCAP2 = 0xca; //定时器2自动重装
sfr16 RCAP3 = 0x92; //定时器3自动重装
sfr16 TMR2 = 0xcc; //定时器2
sfr16 TMR3 = 0x94; //定时器3

/**********全局常量***************/

#define BAUDRATE 115200 //串口通信的波特率
#define SYSCLK 22118400//外部晶振频率
#define SAMPLE_RATE 100000 //采样频率
#define INT_DEC 256 //积分抽取比采样并取平均值;由过采样并取平均值来提高ADC分辨率的相关
#define SAR_CLK 2500000 //ADC0转换时钟周期的计算
#define SAMPLE_DELAY 50 //采样之前的毫秒延时

sbit led = P1^6; //led = 1是否定
sbit sw1 = P3^7; //sw1 = 0转换开关

void PORT_INIT (void);
void OSCILLATOR_INIT (void);
void UART0_INIT();
void TIMER3_INIT(int counts);
void ADC0_INIT();
void delay_ms(unsigned int ms);
void delay4j();

/***********全局变量***********/

long result; // 减小的值

/*********主函数************/

void main()
{
long measurement; // 测量电压(mv)

WDTCN = 0xde;           //关闭看门狗
WDTCN = 0xad;

OSCILLATOR_INIT();      //初始化晶振
PORT_INIT();            //交叉使能开关
UART0_INIT();           //初始化串口通信0;
TIMER3_INIT(SYSCLK/SAMPLE_RATE);//初始化定时器3的溢出采样率
ADC0_INIT();

AD0EN  = 1;             //ADC0控制寄存器,使能ADC
EA     = 1;             //打开所有中断(总体,但如果子中断关闭,那该中断依旧关闭)
while(1)
{
    EA = 0;            //关闭中断
 /*********12ADC的值是通过积分平均值的测量,数据存储在result中,为右对齐
  AIN0.1的实测值为:  Vref(mv)
        measure(mv) =----------------*result(bits)
                      (2^12)-1(bits)
 ****************************/
 measurement = result * 2430 / 4095;

// measurement = result;
EA = 1; //使能中断
printf("AIN0.1 voltage:%ld mv\n",measurement);
// led = ~sw1; //LED反应状态的转换
// delay_ms(SAMPLE_DELAY);//延时50ms
delay_ms(1);
// delay4j();

}

}

/************交叉使能开关配置****************/
void PORT_INIT (void)
{
XBR0 = 0x04; // UART0 线路配置
XBR2 = 0x40; // 交叉使能,设置为弱上拉
P0MDOUT = 0x01; // enable TX0 as a push-pull output
P1MDOUT = 0x40; // enable LED as push-pull output

}
/*************使用外部晶振作为系统时钟***********/
void OSCILLATOR_INIT (void)
{
int i; // delay counter

OSCXCN = 0x67; // start external oscillator with
// 22.1184MHz crystal

for (i=0; i < 256; i++) ; // wait for oscillator to start

while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settle

OSCICN = 0x88; // select external oscillator as SYSCLK
// source and enable missing clock
// detector

}

/************串口初始化****************/
void UART0_INIT()
{
SCON0 = 0x50; //UART0控制寄存器设置
TMOD = 0x20; //定时器1的方式寄存器
TH1 = -(SYSCLK/BAUDRATE/16); //定时器1波特率的重装值
CKCON = 0x10; //时钟控制寄存器设置,定时器1使用系统时钟
PCON = 0x80; //电源控制寄存器设置
TR1 = 1; //打开定时器1
TI0 = 1; //发送中断标志
}

/*************定时器3的初始化*************/
void TIMER3_INIT(int counts)
{
TMR3CN = 0x02; //定时器3控制寄存器,停止定时器3,清除TF3,定时器3使用系统时钟
RCAP3 = -counts;//初始化定时器3重装
TMR3 = RCAP3; // 立即重新加载
EIE2 &= ~0x01; //扩展中断允许2寄存器 关闭所有中断
TMR3CN |= 0x04; //打开定时器3,且使用系统时钟
}

/**************ADC0的初始化**********/
void ADC0_INIT()
{
ADC0CN = 0x04; //ADC0控制寄存器,禁止ADC0,一直跟踪方式,
//ADC0没完成一次数据转换,当前没有进行数据转换
//定时器3溢出启动ADC0转换数据,ADC0H,ADC0L寄存器数据右对齐
REF0CN = 0x03; //关闭温度传感器,VREF输出缓冲区
AMX0CF = 0x00; //AIN为单端输入
AMX0SL = 0x03; //选择AIC0.1位模拟输入引脚
ADC0CF = (SYSCLK/SAR_CLK)<<3;//ADC转换时钟为2500000
ADC0CF |= 0x00; //设置转换时钟2500000,放大倍数为1

EIE2  |= 0x02; //允许ADC0数据转换结束产生中断请求

}

/****************延时ms************/
void delay_ms(unsigned int ms)
{

CKCON &= ~0x20; // use SYSCLK/12 as timebase

RCAP2 = -(SYSCLK/1000/12); // Timer 2 overflows at 1 kHz
TMR2 = RCAP2;

ET2 = 0; // Disable Timer 2 interrupts

TR2 = 1; // Start Timer 2

while(ms)
{
TF2 = 0; // Clear flag to initialize
while(!TF2); // Wait until timer overflows
ms--; // Decrement ms
}

TR2 = 0; // Stop Timer 2

}

/***************ADC0的中断*****************/
void ADC0_ISR (void) interrupt 15
{
static unsigned int_dec=INT_DEC; // 集成计数器,当int_dec = 0时,置入一个新的结果
static long accumulator=0L; // 整合ADC采样,“0L”为将0转换成long型的

AD0INT = 0; // 清除AD数据转换成功标识符,重新开始下次采样

accumulator += ADC0; //读取ADC的值,并逐次累加
int_dec--; // 更新衰减计数器

if (int_dec == 0) // If zero, then post result
{
int_dec = INT_DEC; // Reset counter
result = accumulator >> 8;
accumulator = 0L; // Reset accumulator
}
}

void delay4j()
{
nop();
nop();
nop();
nop();

}

c8051f020的12位AD采样频率最高是100ksps,低频的时候可以,但是为什么转换频率为1kHZ的正弦波时数据会混乱呢,

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

相关推荐 更多相似问题