本帖最后由 xlhtracy 于 2013-8-27 13:58 编辑
最近在做一个用C8051F352采集数据,通过AD0转换通过串口和pc通信的任务。遇到了问题,还望论坛中的大侠帮助。下面是原理图
下面是我写的AD0转换的代码,在ANI0.2输入,然后通过串口助手通信。
#include <C8051F350.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
//16位寄存器定义
sfr16 TMR2RL = 0xCA; // 定时器2重装值
sfr16 TMR2 = 0xCC; // 定时器2值
sfr16 ADC0DEC = 0x9A; // ADC0 抽取比寄存器
typedef union LONGDATA{ //共同体用于存放返回的ad值
uint result ;
uchar Byte[2] ;
}LONGDATA;
uchar flag=1;
#define SYSCLK 24500000 // 系统时钟频率 Hz
#define MDCLK 2457600 // 调制时钟分频数
// (2.4576 MHz)
#define OWR 20 // 输出字率 Hz
#define BAUDRATE 9600 // 波特率
void Oscillator_Init (void);
void Port_Init (void);
void UART0_Init (void);
void ADC0_Init(void);
void ADC0_Sigle_Channel_ISR(uchar Channel);
void main(void)
{
static LONGDATA rawValue;
uint mV;
PCA0MD &= ~0x40;
Oscillator_Init();
Port_Init(); // 端口初始化
UART0_Init(); // 串口通信初始化
ADC0_Init(); // ADC0初始化
while(1)
{
if(flag)
{
ADC0_Sigle_Channel_ISR(0x28);
rawValue.Byte[0]=(uchar)ADC0H;
rawValue.Byte[1]=(uchar)ADC0M;
mV = rawValue.result / 26;
printf("AIN0.2 voltage: %4d mV\n",mV);
}
}
}
void Oscillator_Init (void)
{
OSCICN = 0x83; // 内部晶振使能,SYSCLK不分频
CLKSEL = 0x00; // 选择内部振荡器
RSTSRC = 0x04; // 时钟丢失检验使能
}
void Port_Init (void)
{
XBR0 = 0x01; // UART0 TX0,RX0连接到引脚
XBR1 = 0x40; // 交叉开关使能,弱上拉使能
P0MDOUT |= 0x10; // TX 免推方式
}
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8位波特率可编程uart,
// 停止位的逻辑电平被忽略
// RX 使能
// 第9位清零
// RI0 ,TI0标志位清零
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = 256-(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B;
CKCON |= 0x08; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = 256-(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = 256-(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else if (SYSCLK/BAUDRATE/2/256 < 48) {
TH1 = 256-(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
} else {
while (1); // Error. Unsupported baud rate
}
TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer1 8位自动重装
TMOD |= 0x20;
TR1 = 1; // 启动 Timer1
TI0 = 1; // 表面 TX0 准备好了
}
void ADC0_Init (void)
{
ADC0MD = 0x80; //ADC0使能,工作在空闲模式
REF0CN |= 0x03; // 使能内部 Vref
ADC0CN = 0x00; // PGA增益为1,单极性工作方式
ADC0CF = 0x00; // SINC3 滤波器输出,使用内部2.5V Vref
ADC0CLK = (SYSCLK/MDCLK)-1; // 产生调制时钟分频系数
// MDCLK = 2.4576MHz
// 根据输出字率确定抽取比
ADC0DEC = ((unsigned long) MDCLK / (unsigned long) OWR /(unsigned long) 128) - 1;
ADC0BUF = 0x00; // 关闭输入缓冲器
ADC0MUX = 0x28; // 选择 AIN0.2
ADC0MD = 0x81; // 开始内部校准
while(!AD0CALC); // 直到校准完成
EIE1 &= ~0x08; // 关闭中断
ADC0MD &= ~0x07; // 使ADC0处于空闲模式
}
void ADC0_Sigle_Channel_ISR(uchar Channel)
{
ADC0MUX = Channel; // 转换通道
AD0INT = 0; // 清ADC0中断标志
ADC0MD |= 0x02; // ADC0单次转换
// AD0INT = 0; // 清ADC0中断标志
while (!AD0INT);
flag=0;
}
但是很奇怪,运行时候,无论我输入怎么变,输出都是302mv
下面是我仿真时候的,ADC0寄存器的值。
我对照datasheet看了下,好像是ADC0STA寄存器中的AD0SC3置位了,表明ADC0 SINC3 滤波器发生了限幅。但是我不知道什么意思。也不知道怎么修改。还玩哪位大侠用过这个芯片的,帮我看看。或者发个正确的代码给我,小弟感激不尽。
原理图和ADC0寄存器在附近中。谢谢大家 |