#include
#define uint unsigned int //定义数据类型替代码
#define uchar unsigned char
#define dat P1OUT //定义lcd1602的数据口为P1
#define CLR_RS P2OUT&=~BIT0 //置零P2.0位,即置零RS
#define SET_RS P2OUT|=BIT0 //置一P2.0位,即置一RS
#define CLR_RW P2OUT&=~BIT1
#define SET_RW P2OUT|=BIT1
#define CLR_EN P2OUT&=~BIT2
#define SET_EN P2OUT|=BIT2
uchar busy; //1602判忙标志
void delay_lms(int x); //延时程序,短延时
void delay_ls(int x); //延时程序,长延时
void display(void); //显示程序
void busy_1602(void); //液晶查忙程序
void init_1602(void); //液晶初始化
void shj_1602(uchar a); //液晶写数据程序
void zhl_1602(uchar a); //液晶写指令程序
//typedef unsigned char uchar;
//typedef unsigned int uint;
#define Num_of_Results 32
uchar table0[16]={"The Volt is"}; //定义lcd1602显示两行的字符
uchar table1[16]={"0123456789.v"};
static uint results[Num_of_Results]; //保存ADC转换结果的数组
void main(void)
{
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
//下面六行程序关闭所有的IO口
P1DIR=0XFF;P1OUT=0XFF;
P2DIR=0XFF;P2OUT=0XFF;
P3DIR=0XFF;P3OUT=0XFF;
P4DIR=0XFF;P4OUT=0XFF;
P5DIR=0XFF;P5OUT=0XFF;
P6DIR=0XFF;P6OUT=0XFF;
init_1602(); //复位1602液晶
P6SEL|=BIT0; //使能ADC通道
ADC12CTL0=ADC12ON+SHT0_8+MSC;//打开ADC,设置采样时间
//上面的配置中并没有打开内部的参考电压,ADC12MCTLx用来选择通道和参考电压,这里面没有对此寄存器进行配置为默认值,默认值是参考电压选择AVCC(3.3v),通道时A0,所以测量范围是0-3.3V
ADC12CTL1=SHP+CONSEQ_2;//使用采样定时器,转换模式为单路重复转换
ADC12MCTL0=INCH_0;
ADC12IE=BIT0;//使能ADC中断
ADC12CTL0|=ENC; //使能转换
ADC12CTL0|=ADC12SC; //开始转换
_BIS_SR(GIE); //开启全局中断
LPM0;
}
/****************************
函数名称:Trans_val
功能:将16禁止ADC转换数据变换成三位10进制真是的模拟电压数据,并在液晶上显示
参数:Hex_val 16进制数据
n 变换时的分母等于2的n次方
返回值:无
*****************************/
void Trans_val(uint Hex_Val_1)
{
unsigned long caltmp;
uint Curr_Volt;
uchar t1,i;
uchar ptr[5];
uint Hex_Val;
Hex_Val=Hex_Val_1;
caltmp=Hex_Val;
caltmp=(caltmp<<5)+Hex_Val; //caltmp=Hex_Val*33
caltmp=(caltmp<<3)+(caltmp<<1); //caltmp=caltmp*10
Curr_Volt=caltmp>>12; //Curr_Volt=caltmp/2^n
//参考电压为3.3V,所以计算公式应该是Hex_Val*3.3/2^n
//乘除计算通过移位来进行可以有效的提高程序运行效率
ptr[0]=Curr_Volt/100; //Hex->Dec变换
t1=Curr_Volt-(ptr[0]*100);
ptr[2]=t1/10;
ptr[3]=t1-(ptr[2]*10);
ptr[1]=10; //shuzi表中第10位对应的符号“.”
ptr[4]=11;
init_1602(); //初始化1602
zhl_1602(0x08); //关闭显示
zhl_1602(0x01); //显示清屏
for(i=0;i<16;i++) //发送数据第二行
{
shj_1602(table0[i]);
}
zhl_1602(0x80+0x40+4); //显示换行
for(i=0;i<5;i++) //发送数据第一行
{
shj_1602(table1[ptr[i]]);
}
zhl_1602(0x0c); //显示开及光标设置
//在液晶上显示变换后的结果
}
/****************************
函数名称:ADC12ISR
功能:ADC中断服务函数,在这里用多次平均计算P6.0的模拟电压数值
参数:无
返回值:无
***************************/
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR(void)
{
static uint index=0;
results[index++]=ADC12MEM0; //将转换的结果存入数组
if(index==Num_of_Results) //如果数组存满
{
uchar i;
unsigned long sum=0;
index=0; //再从头开始存,会覆盖原来的数据
for(i=0;i
{
sum+=results[i];
}
sum>>=5; //除以32
Trans_val(sum);
}
}
void busy_1602(void) //查询忙碌标志信号程序
{
do
{
CLR_EN; //EN置零
SET_RW; //RW置一 读信号线
CLR_RS; //RS置零 读取指令
SET_EN; //EN置一 读信息
busy=dat;
CLR_EN; //EN置零
delay_lms(10);
}
while(busy&&0x10==1);
}
void zhl_1602(uchar a) //写指令到lcm程序
{
busy_1602();
CLR_EN; //EN置零
CLR_RW; //RW置零 写信号线
CLR_RS; //RS置一 读取指令
SET_EN; //EN置一 读信息
dat=a;
CLR_EN; //EN置零
}
void shj_1602(uchar a) //写数据到lcm程序
{
busy_1602();
CLR_EN; //EN置零
CLR_RW; //RW置零 写信号线
SET_RS; //RS置一 读取数据
SET_EN; //EN置一 读信息
dat=a;
CLR_EN; //EN置零
}
void init_1602(void) //启动lcm程序
{
zhl_1602(0x38); //写指令
zhl_1602(0x0c); //显示开及光标设置
zhl_1602(0x06); //光标移动设置
}
void delay_lms(int x) //延时程序,短延时
{
while(x--)
for(int i=0;i<25;i++);
}
void delay_ls(int x)
{
for(int i=0;i<8;i++)
{
while(x--)
for(int i=0;i<150;i++);
}
}
自我感觉内部A/D就没有工作,直接默认的参考电压3.3V在进行计算,所以在Proteus中一直显示3.29v. 可是怎么改呢??求指导