本帖最后由 gzh4510 于 2015-2-6 18:53 编辑
信号源是工频220V交流 LMV932MA 7脚输出,直接进入单片机AD。单片机为STC12C5A60S2 AD采样交流电压2个周期,时间间隔为312微妙,采样点数为128点。VCC为+5V。
+
单片机采集到的数据通过串口发送到PC端,在EXCEL里通过采集到的数据绘制的波形,基本等于正弦波,可以断定采集到的数据基本正确。
以下是程序
#include<STC12C5A60S2.h>
#include <intrins.h>
#include <math.h>
#include <string.h>
#include "LCD1602_1.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 22118400L //System frequency
#define BAUD 9600 //UART baudrate
/********************************************************************
ADC数据转换函数
*********************************************************************/
#define ADC_POWER 0x80 //ADC 电源控制位
#define ADC_FLAG 0x10 //ADC转换结束标志位
#define ADC_START 0x08 //ADC 开始转换控制位
#define ADC_SPEEDLL 0x00 //540 个时钟周期转换一次
#define ADC_SPEEDL 0x20 //360 个时钟周期转换一次
#define ADC_SPEEDH 0x40 //180 个时钟周期转换一次
#define ADC_SPEEDHH 0x60 //90 个时钟周期转换一次
/********************************************************************
ADC转换数据数组
*********************************************************************/
double xdata ADC_DH_Temp[128]; //AD采样高8位缓冲区
unsigned int xdata ADC_DL_Temp[128]; //AD采样低2位缓冲区
unsigned int xdata ADC_Data[128];
unsigned char ADC_Count; //采样计数
unsigned char Disp_Tab[]={'0','1','2','3','4','5','6','7','8','9'};
bit ADC_Flag; //采样完成标志位
/****************************************************************/
/****************************************************************/
unsigned char code mcustudio[] //={" A D C "}; //Photosensitive box
={"STC12C5A60S2 AD"};
/******************************************
均方根值函数
******************************************/
double Calc (double *pData,int nNum)
{
double fsum=0;
unsigned char i;
//求平方和
for( i=0;i<nNum;++i)
{
fsum+=pData*pData;
}
//平均 开方
return sqrt(fsum/nNum);
}
/******************************************
AD初始化函数
******************************************/
void InitADC()
{
P1ASF=0XFF; //P1所有I/O口作为模拟功能A/D使用
ADC_RES=0; //AD数据高8位清空
ADC_RESL=0; //AD数据低2位清空
ADC_CONTR=ADC_POWER|ADC_SPEEDHH; //打开AD电源 转换周期90微妙
_nop_();
_nop_();
_nop_(); //保证电源打开
_nop_();
EADC=1; //开AD中断
IPH=0X20;
IP=0X20; //AD中断优先级最高
}
void InitTimer0(void) //定时器0 312微妙定时
{
AUXR |= 0x80; //定时器时钟1T 模式
TMOD = 0xA1; //设置定时器模式
TL0 = 0x0B; //初值
TH0 = 0xE5;
TF0 = 0; //清中断标志位
ET0=1; //开定时器0中思
EA=1; //开总中断
TR0 = 1; //启动定时器0
}
//******************************************//
// 测式用程序
// 串口发送
//******************************************//
/*----------------------------
Initial UART
----------------------------*/
void InitUart()
{
PCON |= 0x80; //
SCON = 0x50; //
AUXR |= 0x40; //定时器时钟选为Fosc,即1T
AUXR &= 0xFE; //串口1选为定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式
TMOD |= 0x20; //为8位自动装载
TL1 = 0x70; //初值
TH1 = 0x70; //
ET1 = 0; //关定时器1中断
TR1 = 1; //启动定时器1中断
}
/*----------------------------
Send a string to UART
Input: s (address of string)
Output:None
----------------------------*/
void SendString(unsigned int *pData,int nNum) //发送字符串函数
{
unsigned char i;
for(i=0;i<nNum;i++)
{
SBUF=pData;
while(TI==0);
TI=0;
}
}
//******************************************//
// 测式用函数结束
//******************************************//
/******************************************
主函数
******************************************/
void main(void)
{
// double ADC_1;
unsigned int ADC_2;
unsigned char LedOut[4];
InitADC(); //AD初始化
LCMInit(); //1602初始化
InitTimer0(); //定时器0初始化
InitUart(); //串口初始化
DisplayListChar(0, 0, mcustudio); //LCD1602显示
//SendString(1,16);
while(1)
{
if(ADC_Flag==1) //AD转换完成置位
{
ADC_Flag=0;
ADC_2=(int)(Calc(ADC_DH_Temp,128)*130); //计算有效值
//ADC_Merge(ADC_DH_Temp,ADC_DL_Temp);
//SendString(ADC_Data,64);
//SendString(ADC_DH_Temp,128); //发送高8位数据
// SendString(ADC_DL_Temp,64); //发送低2位数据
// 1602显示
LedOut[0]=Disp_Tab[ADC_2%100000/10000];
LedOut[1]=Disp_Tab[ADC_2%10000/1000];
LedOut[2]=Disp_Tab[ADC_2%1000/100];
LedOut[3]=Disp_Tab[ADC_2%100/10];
LedOut[4]=Disp_Tab[ADC_2%10];
DisplayOneChar(1, 1, LedOut[0]);
DisplayOneChar(2, 1, LedOut[1]);
DisplayOneChar(3, 1, LedOut[2]);
DisplayOneChar(4, 1, '.');
DisplayOneChar(5, 1, LedOut[3]);
DisplayOneChar(6, 1, LedOut[4]);
DisplayOneChar(7, 1,'V');
ET0 = 1; //开定时器0中断
EADC=1; //开AD中断
}
}
}
void Timer0Interrupt(void) interrupt 1 //定时器0中断函数 312微秒时间
{
TL0 = 0x0B; //初值
TH0 = 0xE5;
ET0=0; //关定时器0中断
ADC_CONTR=ADC_POWER|ADC_SPEEDHH|ADC_START|0x20; //开始转换 P1.0输入 90个周期
_nop_();
_nop_();
_nop_(); //保证电源打开
_nop_();
P20=~P20; //测式用LED灯
}
void ADC_ISR() interrupt 5 using 1
{
EADC=0; //关AD中断
ADC_CONTR&=~ADC_FLAG; //关闭AD转换
ADC_DH_Temp[ADC_Count]=(ADC_RES)*10*49.999/255; //取高8位数据存入数组
ADC_DL_Temp[ADC_Count]=ADC_RESL; // ADC_RESL&0X03; //取低2位数据存入数组
ADC_Count++; //采样计数
if(ADC_Count>=128)
{
ADC_Count=0;
ADC_Flag=1;
}
else
{
ET0 = 1; //开定时器0中断
EADC=1; //开AD中断
}
}
现在的问题是,取8位AD数据是正确的,如果取10AD数据该如何取?
我最开始定义一个INT的变量,然后左移两位,在加上低2位的数据,但上传上来的数据不对。
还有问题就是,这个信号中包含直流2.5V的直流,应该怎么计算采进来的数据呢?
电路图最后一级为I/V转换电路,那么转换出来的电压如何计算呢?
那位好心的师傅帮帮我,谢谢了,弄这个我以经弄了两个多月了,我并非电子出身,我是学强电的,就是对单片机非常的感兴趣,所以都是自己学的。谢谢好心人的帮助!
|