微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > STC12C5A60S AD采样 5110显示 总是不对啊

STC12C5A60S AD采样 5110显示 总是不对啊

时间:10-02 整理:3721RD 点击:
有没有人帮我看看啊,3.3V测出来是4.9,之后就不动了。
/*-------------------------------------------------------------------------
C文件函数调用说明:
在main 加入头文件       #include"STC12C5A60S2.h"  //加载AD 头文件
在main 主函数应初始化   Init_ADC();//初始化STC12C5A60S2 内部AD
   ADC采用查询方式
uint ad_result;               //定义一个 读取ad转换结果
ad_result=ADC_N(5,50);        // P1^5 采集50次AD结果
需要注意问题:
      
实际电压值 :AD_Result=AD_Result*5/256;          // 计算实际电压值
--------------------------------------------------------------------------*/   
#include"STC12C5A60S2.h"                   //加载AD 头文件
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar code zifu[]={'0','1','2','3','4','5','6','7','8','9','.'};
uchar code voltage[]={"U =        v"};
uchar a[5];
uchar num=123;
uchar vol=0;
uchar Vo;
sbit    LCD_CLK  = P2^0;   //时钟
sbit    SDIN     = P2^1;   //数据
sbit    LCD_DC   = P2^2;   //1写数据,0写指令
sbit    LCD_SCE  = P2^3;   //片选
sbit    LCD_REST = P2^4;   //复位,0复位
/*function
************************/
///////////SPI写操作
void LCD_write_byte(unsigned char dat, unsigned char command);        
///////////5110初始化
void LCD_init(void);
///////////清屏
void LCD_clear(void);
//////////显示一个字符
void LCD_write_char(unsigned char c);
//////////显示字符串
void LCD_write_String(unsigned char X,unsigned char Y,unsigned char *s);
//ASCII码的字库
uchar code ASCII_6_8[][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 20 (空格)
,{0x00, 0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x00, 0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x00, 0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x00, 0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x00, 0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x00, 0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x00, 0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x00, 0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x00, 0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x00, 0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x00, 0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x00, 0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x00, 0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x00, 0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x00, 0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x00, 0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x00, 0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x00, 0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x00, 0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x00, 0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x00, 0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x00, 0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x00, 0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x00, 0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x00, 0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x00, 0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x00, 0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x00, 0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x00, 0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x00, 0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x00, 0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x00, 0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x00, 0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x00, 0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x00, 0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x00, 0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x00, 0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x00, 0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x00, 0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x00, 0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x00, 0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x00, 0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x00, 0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x00, 0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x00, 0x02, 0x04, 0x08, 0x10, 0x20} // 5c \ //
,{0x00, 0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x00, 0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x00, 0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x00, 0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x00, 0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x00, 0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x00, 0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x00, 0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x00, 0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x00, 0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x00, 0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x00, 0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
,{0x00, 0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x00, 0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x00, 0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x00, 0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x00, 0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x00, 0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x00, 0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x00, 0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x00, 0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x00, 0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x00, 0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x00, 0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x00, 0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x00, 0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x00, 0x10, 0x08, 0x08, 0x10, 0x08} // 7e ~
,{0x00, 0x78, 0x46, 0x41, 0x46, 0x78} // 7f (delete)
};

/*----------------------------
Software Delay_ADC function
----------------------------*/
void Delay_ADC(uint n)
{
    uint x;
    while (n--)
    {
        x = 5000;
        while (x--);
    }
}

void DelayMS(uint ms)
{
  uint i;
  while(ms--)
  {
          for(i=0;i<120;i++);
  }
}
/*----------------------------
Get ADC result
----------------------------*/
uchar GetADCResult(uchar ch)           //有参数输入  通道几  0-7   P1^0----P1^7
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;//0x00|0x00|ch|0x08:选择A/D输入通道,开始A/D转换
    _nop_();         //Must wait before inquiry ,
    _nop_();        //设置ADC_CONTR寄存器后需加4个CPU时钟周期的延时,才能保证值被写入ADC_CONTR寄存器
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC
    Vo=ADC_RES*5*10/256;             //Return ADC result(为显示整数,这里将电压值扩大了十倍)   
    return Vo;
}

/*----------------------------
Initial ADC sfr
//P1^0  口为AD 输入
----------------------------*/
void Init_ADC()
{                        //0000 0001
    P1ASF = 0x01;        //选择P1.0作为A/D输入通道
    ADC_RES = 0;         //Clear previous result         // 清除AD转换结果寄存器之前的转换数据
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay_ADC(2);            //ADC power-on and Delay_ADC   //初次打开ADC电源 要等待
}
/*------------函数说明--------------------------------
函数功能:  读取 计算平均值后的AD 结果
函数参数:        chn:0-7  AD 通道   N :采集多少次AD 计算平均值
返回值  : ad值0-255   AD_Result=AD_Result*5/256;          // 计算实际电压值
程序示例:
uint ad_result;   //定义一个 读取ad转换结果
ad_result=ADC_N(5,50);        // P1^5 采集50次AD结果   
------------------------------------------------------*/
uchar ADC_N(uchar chn,uchar N)           //采集N次然后取平均值   通道几 采集次数
{
   unsigned char i;
   unsigned int adc_tem=0;
        for(i=N;i>0;i--)
        {
          adc_tem+=GetADCResult(chn);
        }
        adc_tem/=N;         //adc_tem=adc_tem/N  赋值符合运算      
    return  adc_tem;   //返回         
}

/***********************************************************
函数名称:LCD_write_byte
函数功能:模拟SPI接口时序写数据/命令LCD
入口参数:data    :写入的数据;
          command :写数据/命令选择;
出口参数:无
备 注:
***********************************************************/
void LCD_write_byte(unsigned char dat, unsigned char command)
  {
    unsigned char i;
     LCD_SCE = 0;                  //5110片选有效,允许输入数据
    if (command == 0)              //写命令
        LCD_DC = 0;                  
    else
        LCD_DC = 1;              //写数据
    for(i=0;i<8;i++)              //传送8bit数据
    {
         if(dat&0x80)                    
            SDIN = 1;
        else
            SDIN = 0;
        LCD_CLK = 0;
        dat = dat << 1;
        LCD_CLK = 1;          //时钟上升沿 写
    }
        LCD_SCE = 0;                   //关闭5110
  }

/***********************************************************
函数名称:LCD_init
函数功能:5110初始化
入口参数:无
出口参数:无
备 注:
***********************************************************/
void LCD_init(void)
  {
    LCD_REST = 0;      // 产生一个让LCD复位的低电平脉冲
    _nop_();
    LCD_REST = 1;
   
    LCD_SCE = 0;       // 关闭LCD
    _nop_();
    LCD_SCE    = 1;       //使能LCD
    _nop_();
    LCD_write_byte(0x21, 0);    // LCD模式设置:芯片活动,水平寻址,使用扩展指令
    LCD_write_byte(0xc8, 0);    // 设置液晶偏置电压
    LCD_write_byte(0x06, 0);    // 温度校正
    LCD_write_byte(0x13, 0);    // 1:48
    LCD_write_byte(0x20, 0);    // 使用基本命令,V=0,水平寻址
    LCD_clear();               // 清屏
    LCD_write_byte(0x0c, 0);    // 设定显示模式,正常显示
   
    LCD_SCE = 0;      //禁止LCD
  }
/***********************************************************
函数名称:LCD_set_XY
函数功能:设置LCD坐标函数
入口参数:X       :0-83  横坐标
          Y       :0-5   纵坐标
出口参数:无
备 注:
***********************************************************/
void LCD_set_XY(unsigned char X, unsigned char Y)
  {
      LCD_write_byte(0x80 | X, 0);        // X     行(横坐标)
      LCD_write_byte(0x40 | Y, 0);          // column     列(纵坐标)
  }
/*------------------------------------------
LCD_clear: LCD清屏函数
--------------------------------------------*/
void LCD_clear(void)
{
    unsigned char t;
    unsigned char k;
    LCD_set_XY(0,0);
    for(t=0;t<6;t++)
    {
        for(k=0;k<84;k++)
        {
            LCD_write_byte(0x00,1);
               
        }
    }
}

/***********************************************************
函数名称:LCD_write_char
函数功能:显示英文字符
入口参数:c    :  显示的字符
出口参数:无
备 注:
***********************************************************/
void LCD_write_char(unsigned char c)
{
    unsigned char line;
     c-=0x20;                //数组的行号  ASCII码减去 0x20
    for (line=0; line<6; line++)
        LCD_write_byte(ASCII_6_8[c][line], 1);
}
/*-------------------------------------------
;名称: 英文字符串显示函数
;参数:*s:英文字符串指针
---------------------------------------------*/
void LCD_write_String(unsigned char X,unsigned char Y,unsigned char *s)
{
    LCD_set_XY(X,Y);
    while (*s)                      //等效*s!='\0'
    {
        LCD_write_char(*s);
        s++;
    }
}
void display(uchar db)    //液晶显示函数,用于显示模数转换后得到的数字量
{
    float val;
    val=db;
    a[0]=(uchar)val/100;
    a[1]=(uchar)val%100/10;
    a[2]=10;
    a[3]=(uchar)val%10;
    LCD_set_XY(20,0);
    LCD_write_char(zifu[a[0]]);
    LCD_write_char(zifu[a[1]]);
    LCD_write_char(zifu[a[2]]);
    LCD_write_char(zifu[a[3]]);
    DelayMS(1000);
}

void main()
{
    LCD_init();                    //定义一个 读取ad转换结果
    Init_ADC();
              
    while (1)
    {
        
        vol = ADC_N(0,1000);                 //采集50次然后取平均值   通道0(P1^0) 采集次数50
        display(vol);                     //显示采集的电压值
                                       
        LCD_write_String(0,0,voltage);
        
   
    }
     
}
H 文件如下
/******************************************************************
ADC头文件:
//
函数调用说明:
在main 加入头文件       #include"STC12C5A60S2.h"  //加载AD 头文件
在main 主函数应初始化   Init_ADC();                //Init ADC sfr
********************************************************************/
#ifndef __STC12C5A60S2_H__
#define __STC12C5A60S2_H__ //防重复包含语句
#include <reg51.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int
/*Declare SFR associated with the ADC */
sfr ADC_CONTR   =   0xBC;           //ADC control register         声明ADC 控制寄存器
sfr ADC_RES     =   0xBD;           //ADC high 8-bit result register  ADC 转换结果寄存器 高位
sfr ADC_LOW2    =   0xBE;           //ADC low 2-bit result register          ADC 转换结果寄存器 低位
sfr P1ASF       =   0x80;           //P1 secondary function control registerP1模拟功能控制寄存器
sfr  AUXR1    = 0x8A;

/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER   0x80            //ADC power control bit
#define ADC_FLAG    0x10            //ADC complete flag
#define ADC_START   0x08            //ADC start control bit
#define ADC_SPEEDLL 0x00            //420 clocks
#define ADC_SPEEDL  0x20            //280 clocks
#define ADC_SPEEDH  0x40            //140 clocks
#define ADC_SPEEDHH 0x60            //70 clocks
void Delay_ADC(uint n);                           //延时
void Init_ADC();                                   //初始化
uchar GetADCResult(uchar ch);          //有参数输入  通道几  0-7   P1^0----P1^7
uchar ADC_N(uchar chn,uchar N);          //采集N次然后取平均值   通道几 采集次数

#endif   //防重复包含语句 结束

先看一下是显示的东西不对还是显示的值不对,学会debug

仿真下,看看从ADC出来的值对不对,对的话就是显示的问题,不对的话就是ADC处理的问题。

不溢出才怪呢!
程序示例:
uint ad_result;   //定义一个 读取ad转换结果
ad_result=ADC_N(5,50);        // P1^5 采集50次AD结果   
------------------------------------------------------*/
uchar ADC_N(uchar chn,uchar N)           //采集N次然后取平均值   通道几 采集次数
{
   unsigned char i;
   unsigned int adc_tem=0;
        for(i=N;i>0;i--)
        {
          adc_tem+=GetADCResult(chn);    /*假设每次采样值都为256 ,那么50次累加值为 50*256 = 12800,没有溢出(int 型 为 65536 )*/
        }
        adc_tem/=N;         //adc_tem=adc_tem/N  赋值符合运算      
    return  adc_tem;   //返回         
}
那么问题就来了,到底哪里出错了呢?
你的
main()
{
       ADC_N(0,1000) ; //这一句绝对出错,为什么?因为 1000*256 = 256000 >>65536 ,不出错才怪,建议还是改用50,或者把adc_tem定义为 long
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top