AD没有转换 LCD上一直显示3.29v.求大神耐心看看,小弟毕设需过此关!!!

2019-03-24 11:44发布

#include <msp430x24x.h>
#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);                                                   //液晶写指令程序



#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<Num_of_Results;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++);
  }
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
19条回答
tianshuihu
2019-03-25 01:47
本帖最后由 tianshuihu 于 2014-4-1 09:28 编辑

建议在ADC中断函数的最后做如下尝试

  sum>>=5;            //除以32
sum=512;    //修改此数值看看最终的显示是否正确,如正确显示则可删除此行
    Trans_val(sum);

另外LCD初始化一次即可,显示的长度一样的话,每次会自动覆盖之前的显示内容,所以每次只需更新显示的数值即可

一周热门 更多>

相关问题

    相关文章