使用STC12C5A60S2内部AD测量电压0-5V(单片机应使用5V电压供电)
main.c
/***********************************************************
程序功能:ADC采集电压信号(0-5V)+LCD1602液晶显示
***********************************************************/
#include "reg51.h"
#include "intrins.h"
//sfr P4 = 0XC0;
sfr ADC_CONTR = 0XBC;
sfr ADC_RES = 0XBD;
sfr ADC_LOW2 = 0XBE;
sfr P1ASF = 0X9D;
typedef unsigned char BYTE;
typedef unsigned int WORD;
#include "1602.h"
#define ADC_POWER 0X80
#define ADC_FLAG 0X10
#define ADC_START 0X08
#define ADC_SPEEDLL 0X00
#define ADC_SPEEDL 0X20
#define ADC_SPEEDH 0X40
#define ADC_SPEEDHH 0X60
void InitADC();
void Delay(WORD n);
WORD GetADCResult(BYTE ch);
void DisplayADCResult(BYTE Channel);
char bai=0,shi=0,ge=0;
void main()
{
WORD i=0;
InitADC();
LCDInit();
DisplayListChar(0, 0, "Volt:");
while(1)
{
i++;
if(i==500)
{
DisplayADCResult(0);
i=0;
}
}
}
/平均滤波//
#define N 100
float AD_average(BYTE Channel)
{
float value=0;
BYTE count;
for(count=0;count<100;count++)
{
value+=GetADCResult(Channel); //100次采样
}
//value/=202.5;
// value/=205;
// value/=2048;
// value/=512;
value/=100; //求平均
value=value*5.0/1024;//val/1024*5
return value;
}
void DisplayADCResult(BYTE Channel)
{
float ADResult;
WORD Result;
ADResult=AD_average(Channel)*100;
Result=(int)ADResult;
bai=Result/100;
shi=Result%100/10;
ge=Result%10;
DisplayOneChar(6,0,table[bai]);
DisplayOneChar(7,0,'.');
DisplayOneChar(8,0,table[shi]);
DisplayOneChar(9,0,table[ge]);
DisplayOneChar(10,0,'V');
}
WORD GetADCResult(BYTE ch)
{
ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ch|ADC_START;
_nop_();
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR&ADC_FLAG));
ADC_CONTR&=~ADC_FLAG;
return ADC_RES*4+ADC_LOW2;
}
void InitADC()
{
P1ASF = 0XFF;
ADC_RES = 0;
ADC_CONTR = ADC_POWER|ADC_SPEEDLL;
Delay(2);
}
void Delay(WORD t)
{
WORD x;
while(t--)
{
x = 5000;
while(x--);
}
}
1602.h
sbit LCD_RS=P0^7;//定义引脚
sbit LCD_RW=P0^6;
sbit LCD_E=P0^5;
#define LCD_Data P2
/********宏定义***********************************************************/
#define Busy 0x80 //用于检测LCD状态字中的Busy标识
/********数据定义*************************************************************/
code BYTE table[]={48,49,50,51,52,53,54,55,56,57}; //0-9 ascii码的数字
/********函数声明*************************************************************/
void WriteDataLCD(BYTE WR_DATA); //写数据
void WriteCommandLCD(BYTE WCLCD); //写命令
void WriteCommandLCD1(BYTE WCLCD); //写命令
void busy_check(void); //读状态
void LCDInit(void); //初始化
void DisplayOneChar(BYTE X, BYTE Y, BYTE DData); //相应坐标显示字节内容
void DisplayListChar(BYTE X, BYTE Y, BYTE code *DData); //相应坐标开始显示一串内容
//void delay1MS(uint t)
//{
// uint i,j;
// for(i=0;i<t;i++)
// for(j=0;j<935;j++);
//}
/*初始化*/
void LCDInit(void)
{
WriteCommandLCD(0x38);//不检测忙信号
WriteCommandLCD(0x08); //关闭显示
WriteCommandLCD(0x01); //显示清屏
WriteCommandLCD(0x06); //显示光标移动设置
WriteCommandLCD(0x0C); //显示开及光标设置
}
/*按指定位置显示一串字符*/
void DisplayListChar(BYTE X, BYTE Y, BYTE code *DData)
{
BYTE ListLength;
ListLength = 0;
X &= 0xF;
Y &= 0x1; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>=0x20){ //若到达字串尾则退出
if (X <= 0xF){ //X坐标应小于0xF
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
/*按指定位置显示一个字符*/
void DisplayOneChar(BYTE X, BYTE Y, BYTE DData)
{
X &= 0xF;
Y &= 0x1; //限制X不能大于15,Y不能大于1
if (Y)
X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCD(X); //发送地址码
WriteDataLCD(DData);
}
/***********写指令********************************************************/
void WriteCommandLCD(BYTE WCLCD)
{
busy_check();
LCD_Data = WCLCD;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
LCD_E = 0;
}
/***********写数据********************************************************/
void WriteDataLCD(BYTE WR_DATA)
{
busy_check(); //检测忙
LCD_Data = WR_DATA;
LCD_RS = 1;
LCD_RW = 0;
LCD_E = 1;
LCD_E = 0;
}
//检测忙信号
void busy_check(void)
{
LCD_Data = 0xFF;
LCD_E = 0;
LCD_RS = 0;
LCD_RW = 1;
LCD_E = 1;
while (LCD_Data & Busy);
LCD_E = 0;
}
效果