打印
[国产单片机]

STC12C5A60S2内部ADC采集电压,采集到电压比实际电压小0.5V左右

[复制链接]
4915|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
明眸|  楼主 | 2015-10-28 09:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 明眸 于 2015-10-29 09:41 编辑

比如采集3.534电压,采集到确实3.023V,请什么原因啊?


#include <STC12C5A60S2.h>
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

//extern void InitLcd1602();
//extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
//extern void LcdWriteCmd(unsigned char cmd);
unsigned char str[10];
//unsigned char str1[]={"Measuring..."};
long result;
int ADC;
void DELAY_MS (unsigned int a)
{
        unsigned int i;
        while( a-- != 0){
                for(i = 0; i < 600; i++);
        }
}

void InitADC(unsigned char CHA)
{
        P1ASF=0xFF;                   //设置P1.7口为模拟输入端口
        CHA &= 0x07;                        //选择ADC的8个接口中的一个(0000 0111 清0高5位)
        ADC_CONTR=0x60;   //设置180个时钟周期为转换周期         0110 0000
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ADC_CONTR|=CHA;          //选择通道
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ADC_CONTR|=0x80;         //启动电源
        DELAY_MS(1);//延时1ms
        AUXR1|=0xFB;//ADRJ=0,10位A/D转换结果的高8位存放在ADC_RES中,低2位存放在ADC_RESL的低2位中
}

unsigned int ReadADC()
{
        unsigned char ADC_FIN=0;//储存AD转换标志

        ADC_CONTR|=0X08;//启动AD转换标志
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        while(ADC_FIN==0)//等待AD转换结束
        {
                ADC_FIN=ADC_CONTR&0x10;//0001 0000测试AD转换是否结束
        }
        ADC_CONTR&=0xE7;//1110 0111 清ADC_FLAG位, 关闭A/D转换
        return (ADC_RES*4+ADC_RESL);//返回A/D转换结果(10位ADC数据高8位在ADC_RES中,低2位在ADC_RESL中)
}
/*平均滤波*/
float filter()
{
        float val;
        unsigned char i;
        for(i=0;i<100;i++)
        {
                val+=ReadADC();
        }
        val=val/100;
        return (val);
}
/*void  ValueToString(unsigned char *str, unsigned int val)
{
        val = (val*4.94)/1024;
                               
        str[0] = (val/10) + '0';
        str[1] = '.';
        str[2] = (val%100/10) + '0';
        str[3] = (val%100%10)+'0';
        str[4] = 'V';

}*/
void UART_init()
{
        TMOD=0x20;        //设置T1为方式1
        SCON=0x50;        //设置SCON方式1
        TH1=0xFD;
        TL1=0xFD;                  //256-11059200(12*32*9600)
        TR1=1;                          //打开定时器1
}
void UART_send_byte(unsigned char dat)      //UART 发送一字节
{
    SBUF=dat;                   //现将数据存放在SBUF,然后单片机自动发送
        while(TI==0);           //判断发送中断标志
        TI=0;                           //清零
}

void UART_send_string(unsigned char *buf)  //UART 发送字符串
{
        while (*buf != '\0')
        {
                UART_send_byte(*buf++);
        }
}
void main()
{
       
         //InitLcd1602();
         InitADC(7);
         UART_init();
         P1M1=0x80;
         P1M0=0X00;//将P1.7设置为高阻输入

         while(1)
         {
                   result=filter();                         //10位
                  result = (result*49.4)/1024;
                  
                  str[0] = (result/10) + '0';
                  str[1] = '.';
              str[2] = (result%1000/100) + '0';
                  str[3] = (result%1000%100/10) + '0';
                  str[4] = (result%10) + '0';
              str[5] = 'V';
              str[6] = '\n';
                 
                  UART_send_string(str);
                 // ValueToString(str,result);
                 // LcdShowStr(0,0,str1);
                  //LcdShowStr(0,1,str);
                  DELAY_MS(1000);
                  //LcdWriteCmd(0x01);  //清屏
         }
}




                                                                                                                                                                         







相关帖子

沙发
autopccopy| | 2015-10-29 17:29 | 只看该作者
该芯片使用Vcc作ADC基准, 需确认电源是否为程序中的准确值(49.4),另外如Vcc电压不稳,可增加TL431做参照基准,并可数字滤波平均处理。这些在该芯片的数据手册有描述。

STC官方测试的ADC性能结果,非常线性! 可参见:http://www.stcisp.com/stc12c5a60_adc.html

(32)

12C5A60S2@5.00V.jpg (183.91 KB )

12C5A60S2@5.00V.jpg

使用特权

评论回复
板凳
ywlzh| | 2015-11-9 09:52 | 只看该作者
result = (result*49.4)/1024;
这句话本身的结果就丢失部分数据

使用特权

评论回复
地板
s976228410| | 2015-11-9 10:05 | 只看该作者
ywlzh 发表于 2015-11-9 09:52
result = (result*49.4)/1024;
这句话本身的结果就丢失部分数据

丢部分数据不假,丢的那部分必定属于误差比较小的范围内,楼主也说了误差0.5V左右,相比不是这句话直接引起的

使用特权

评论回复
5
ywlzh| | 2015-11-9 10:12 | 只看该作者
s976228410 发表于 2015-11-9 10:05
丢部分数据不假,丢的那部分必定属于误差比较小的范围内,楼主也说了误差0.5V左右,相比不是这句话直接引 ...

   str[0] = (result/10) + '0';
                  str[1] = '.';
              str[2] = (result%1000/100) + '0';
                  str[3] = (result%1000%100/10) + '0';
                  str[4] = (result%10) + '0';

看看这段程序,有没有感觉几个位错位了?

使用特权

评论回复
6
tt98| | 2015-11-11 16:54 | 只看该作者
/1023;P

使用特权

评论回复
7
明眸|  楼主 | 2016-1-14 16:50 | 只看该作者
ywlzh 发表于 2015-11-9 10:12
str[0] = (result/10) + '0';
                  str[1] = '.';
              str[2] = (result%1000 ...

求赐教啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

138

帖子

5

粉丝