切换到宽版
  • 24390阅读
  • 38回复

(提供源码,使用RTX51tiny)初试电压电流表——发现STC的AD其实挺好用的 [复制链接]

上一主题 下一主题
离线senya21
 
发帖
579
M币
3013
专家
5
粉丝
82
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2012-10-19
前段时间买了两片STC12C5A60S2来玩,手头又有3R33,遂准备搭个可调电源,带电压电流指示的。
STC12C5A60S2有60K的程序空间啊,不跑个RTOS实在对不起这配置,所以软件上就选择了RTX51 TINY作为操作系统,这样编程上方便了N倍!硬件上采用TL431A作为基准,而不使用芯片的Vcc,这样加上电流,电压,总共需要3路的AD转换,算法很简单,就是先用TL431的2.5V基准(后面测出来是2.45V的,不知是万用表还是器件的问题)算出电源电压Vcc,然后再求出另外两路的电压,软件滤波算法如下:


unsigned int GetADCResult(unsigned char ch)
{
    unsigned int AD_result;
    ADC_RES = 0;
    ADC_RESL = 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDL | ch | ADC_START;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));

    ADC_CONTR &= ~ADC_FLAG;
    AD_result = ADC_RES;
    AD_result <<= 2;
    AD_result += ADC_RESL;


    return AD_result;
}


unsigned int GetResult(unsigned char ch)
{
    unsigned int ADC_min, ADC_max, ADC_tmp, ADC_result, ADC;
    unsigned char i, j;

    ADC = 0;
    for(j = 0; j < 16; j++)
    {
        ADC_result = 0;
        ADC_min = ADC_max = GetADCResult(ch);
        for(i = 0; i < 8; i++)
        {
            ADC_tmp = GetADCResult(ch);
            if(ADC_tmp < ADC_min)
            {
                ADC_result += ADC_min;
                ADC_min = ADC_tmp;
            }
            else if(ADC_tmp > ADC_max)
            {
                ADC_result += ADC_max;
                ADC_max = ADC_tmp;
            }
            else
            {
                ADC_result += ADC_tmp;
            }
        }

        ADC_result /= 8;
        ADC += ADC_result;
    }
    ADC /= 16;

    return ADC;
}
测试后,发现单片机还有很多的空闲时间在打瞌睡(外接了一个LED,当系统空闲是就电亮),
在CONF_TNY.A51文件里面修改一下这个部分



CPU_IDLE    MACRO
        MOV P1,#0EFH ;进入空闲模式时点亮LED
        ORL    PCON,#1    ; set 8051 CPU to IDLE
        MOV P1,#0FFH ;离开空闲模式时熄灭LED
        ENDM


所以就把采样次数取得很高,发现STC12C5A60S2性能还是很强的,在RTX51上跑了3个任务,分别是读取计算3路的AD、读取温度、1602LCD显示,单片机依旧有很多的时间在打瞌睡。把采用次数设置为2的倍数,可以优化CPU的性能,编译器直接用位运算取代乘除运算。


上图!


用洞洞板搭了一个3R33可调电源,然后输出电压用3枚51K的电阻取了1/3给STC12C5A60S2的一路AD,测量范围为0~15V,三枚电阻有配过,测出来都是50.7K,电压取样电路到单片机AD引脚的连接要严格按照STC手册的,这样测出来的电压才是稳定的,不会飘。



测出来都是5.07V,TL431A的基准取2.45V,之前用2.5V,发现和万用表测出来的电压偏差大,后面取为2.45就一致了




调压用的电位器用多圈的,考虑到电压不需要经常调,没用大的那种。




这是开发板,看见那颗亮着的红色LED没,它说单片机现在正在睡觉




发现开发板还是不错的,调试好后,做个系统板,把单片机,1602统统搞过去,再用杜邦线连一下(PS:作者很喜欢杜邦线),就OK了。

电流检测电路 http://bbs.mydigit.cn/read.php?tid=484474


源码如下(不包含温度检测)PS:RTX51tiny要禁止任务循环,具体查看手册




#include <STC12C5A.H>
#include <rtx51tny.h>
#include <intrins.h>
#include <stdio.h>




sbit rs=P2^3;//H数据,L命令
sbit lcden=P2^5;//高脉冲使能,使能脉宽最小150ns
sbit rw=P2^4;


unsigned int value;


float ADC_v = 0;
float ADC_i = 0;


/******************************************************************************/
void lcddelay(unsigned char x)
{    
    unsigned int y;
    for(;x>0;x--)
    {                                    
        for(y=100;y>0;y--);
    }
}
void lcdwrdata(unsigned char dat)
{
    rs=1;//写数据时RS拉高
    lcden=1;
    P0=dat;
    lcddelay(6);
    lcden=0;
    lcddelay(6);
}
void lcdwrcom(unsigned char cdat)//写指令数据到LCD  
{    
    rs=0;//写指令时RS拉低
    lcden=1;
    P0=cdat;//
    lcddelay(6);//不加此延时将导致不能写入指令,但能写入显示数据
    lcden=0;
    lcddelay(6);
}
void lcd_init()
{
    lcdwrcom(0x38);//0x38设置显示模式为:16X2 显示,5X7 点阵,8 位数据接口
    lcdwrcom(0x0c);//打开显示光标闪烁
    lcdwrcom(0x06);//
    lcdwrcom(0x01);//
}
/******************************************************************************/
void InitADC()
{
    P1ASF = 0xf;
    ADC_RES = 0;
    ADC_CONTR = ADC_POWER|ADC_SPEEDL;
}


unsigned int GetADCResult(unsigned char ch)
{
    unsigned int AD_result;
    ADC_RES = 0;
    ADC_RESL = 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDL | ch | ADC_START;
    _nop_();                        //Must wait before inquiry
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag

    ADC_CONTR &= ~ADC_FLAG;         //Close ADC
    AD_result = ADC_RES;
    AD_result <<= 2;
    AD_result += ADC_RESL;


    return AD_result;             //Return ADC result 10bit
}


unsigned int GetResult(unsigned char ch)
{
    unsigned int ADC_min, ADC_max, ADC_tmp, ADC_result, ADC;
    unsigned char i, j;

    ADC = 0;
    for(j = 0; j < 16; j++)
    {
        ADC_result = 0;
        ADC_min = ADC_max = GetADCResult(ch);
        for(i = 0; i < 8; i++)
        {
            ADC_tmp = GetADCResult(ch);
            if(ADC_tmp < ADC_min)
            {
                ADC_result += ADC_min;
                ADC_min = ADC_tmp;
            }
            else if(ADC_tmp > ADC_max)
            {
                ADC_result += ADC_max;
                ADC_max = ADC_tmp;
            }
            else
            {
                ADC_result += ADC_tmp;
            }
        }

        ADC_result /= 8;
        ADC += ADC_result;
    }
    ADC /= 16;

    return ADC;
}
/******************************************************************************/


void TaskInit() _task_ 0
{
    char n;
        rw = 0;
    lcddelay(200);
    lcden = 0;
    lcd_init();

    InitADC();

    os_wait2(K_TMO, 80);

    TMOD |= 0x10;

    os_create_task(0);
    os_create_task(1);
    os_create_task(2);
    os_delete_task(0);
}


void TaskDisp() _task_ 1
{
    float fv;
    char buf[16], i, n;


    while(1)
    {
        n = sprintf(buf, "U:%5.2fV I:%4.2fA", ADC_v, ADC_i);
        lcdwrcom(0x00|0x80);
        for(i=0;i<n;i++)
        {
            lcdwrdata(buf);
            lcddelay(100);
        }
        for(;i<16;i++)
        {
            lcdwrdata(0x10);
            lcddelay(100);
        }

        os_wait2(K_TMO, 40);
    }
}


void TaskGetPowerInfo() _task_ 2
{
    unsigned int v_ref, v_out, v_i;

    while(1)
    {
        v_ref = GetResult(0);
        v_out = GetResult(1);
        v_i = GetResult(2);

        ADC_v = v_out * 2.50f / v_ref;
        ADC_i = v_i * 2.50f / v_ref;

        os_wait2(K_TMO, 50);
    }
}
[ 此帖被senya21在2012-10-25 11:14重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共12条打赏M币+75
12
关键词: STCRTX51
离线sting2k1

发帖
304
M币
899
专家
2
粉丝
7
只看该作者 1楼 发表于: 2012-10-19
请登录后查看
离线smfox10

发帖
875
M币
5116
专家
10
粉丝
185
只看该作者 2楼 发表于: 2012-10-20
请登录后查看
离线cpf10170024
发帖
3
M币
978
专家
0
粉丝
2
只看该作者 3楼 发表于: 2012-10-20
请登录后查看
离线数码家园

发帖
5228
M币
16486
专家
31
粉丝
540
只看该作者 4楼 发表于: 2012-10-21
请登录后查看
离线zhou1946

发帖
596
M币
2761
专家
1
粉丝
83
只看该作者 5楼 发表于: 2012-10-21
请登录后查看
离线铁木珍

发帖
11823
M币
6790
专家
170
粉丝
13907
只看该作者 6楼 发表于: 2012-10-21
请登录后查看
离线yishuizi

发帖
686
M币
1970
专家
5
粉丝
61
只看该作者 7楼 发表于: 2012-10-22
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线xiaoniren

发帖
497
M币
433
专家
0
粉丝
55
只看该作者 8楼 发表于: 2012-10-22
请登录后查看
本帖最近打赏记录:共1条打赏M币+5
离线hp34401a
发帖
255
M币
0
专家
4
粉丝
7
只看该作者 9楼 发表于: 2012-10-22
请登录后查看
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共1条打赏M币+5
快速回复
限80 字节
“新手上路”发帖需审核后才能显示(请认真发帖),达到数码9级后取消此限制
 
上一个 下一个