找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 342|回复: 0
收起左侧

基于单片机TLC549+TLC5615的稳压电源仿真程序设计

[复制链接]
ID:268547 发表于 2024-3-6 16:36 | 显示全部楼层 |阅读模式
4 稳压电源设计
4.1 电路分析
稳压电路见图4-1所示。三极管射极电压是稳压电源的输出电压,可以接用电器或负载,这个电压值通过TLC549(A/D,同TLC548)数据转换后,送往单片机处理并显示。调整按键可以改变输入TLC5615(D/A,同TLC5616)的数据。TLC5615的输出电压通过运算放大器与实际输出取样电压比较,控制三极管的电压输出。稳压电路的电压输出接受单片机检测,同时又受单片机的控制。电路在仿真时,各点的电压都连接有电压表显示。
51hei.gif
图 1 稳压电路
4.2 电路模块
    一、A/D转换部分
        TLC549 对输出电压进行采集,其操作如下:  
(1)cs先为高电平。(cs为片选信号,为1时,输入脉 i/o clock不起作用);
(2)clock = 0
(3)cs = 0; cs置底电平。 同时date_out为高。(=1);
      (4)延时1.4us。(setup time,cs low before first  clock);  
(5)开始转化数据。因为TLC549是8位串行模数转换器。需将8 位数据依次串行输出。期间,clock高低电平转化一次;
(6)8次数据转化之后。cs置1,片选无效。等待17us后读出数据。
    二、D/A转换部分
TLC5615为10位D/A转换电路,其原理TLC5615的PDF文件。输出电压 = (转
换数值/1024)*2*基准电压
    三、显示
采用数码管对A/D转换后的数据进行显示,因为TLC549 是8位A/D,程序中需要对转化的数据进行处理后才能在七段数码管上动态显示。TLC549的检测电压值范围为0~5V,A/D转换后数据位0~255,应该显示0~5,并且包含小数点部分。
四、按键操作部分
四个独立的按键主要是对DA 的输入数据进行操作的,ADD按键,SUB 按键 这些按键在安下一次松开后便进行加1 的操作,若按键超过一定的时间则增加步长,使其数值能够快速增加,这样就不必要达到一个电压时,一直按几百次。SUB按键也是如此。至于那个预读取按键,主要是用于保存你要常用的电压值,这样一来你就可以在使用此电源时,不必要每次都要按键调整,可以通过读取AT24C04的值进行电压预置,保存按键,是用于保存你长使用的电压值,通过此次的电压值保存,使你可以快速达到你所要求的电压值。
4.3 编程思路
    程序分为键盘处理、D/A、A/D和存储四个模块。运用扫描法,对键盘进行扫描,有按键就更改输入TLC5615 的数值,ADD按键是对数据进行加以操做,长按的话使步进值增大,实现快加,SUB按键与ADD按键同,预读取按键用于读取 AT24C04 中预置的数值,保存按键用于保存当前电压值;显示部分主要是对TLC549采集回来的电压进行处理显示,它主要是在定时器0的中断服务程序中显示,100ms刷新显示一次;TLC5615 模块,通过对dA的串行数据输入,使其在输出电压时可控,输出电压后经lm324,三极管,加上负载输出电压,输出电压后,用TLC549芯片100ms采集一次,送数码管显示。
4.5 程序清单
主函数:
#include <REG51.H>
#include "intrins.h"
#include "AT24C04.h"

#define  uchar unsigned char
#define  uint unsigned int

uchar code  LED[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code Bit_sel[4] = {0x08,0x04,0x02,0x01 }; //各个数码管对应的位选数据

sbit DIO = P1^0;         //数据线
sbit CS = P1^1;             //片选
sbit CLK = P1^2;        //io口时钟

sbit SCS = P1^4;
sbit SDATA = P1^5;
sbit SCLK = P1^3;

sbit ADD = P3^0;
sbit SUB = P3^1;
sbit Pre_read = P3^2;
sbit Store = P3^3;

uint qian,bai,shi,ge;  //用于显示数码管的 千,百,十,个 等四位的显示
uint val,num;           //val 是用于输入DA  的数据,num是用于判断是不是长按的
uint cp;               //计数的变量
uchar key_stat;
uchar add_stat,sub_stat;
uchar st_flag,pre_flag;

void delay(uint x)         //微妙级是延时函数
{
    while(x--)
        _nop_();
}

/**********************************************
    函数名称:deal
    函数作用:处理AD的返回值
    函数参数:无
    函数返回值:无
**********************************************/                                               
void deal(uint num)      //显示程序
{   
    qian=num/1000;          //千,百,十,个处理
    bai=num/100%10;
    shi=num/10%10;
    ge=num%10;
}

/**********************************************
    函数名称:TL549_AD()
    函数作用:返回AD的返回值
    函数参数:无
    函数返回值:data_ad
**********************************************/   
uint TL549_AD()            //TLC549处理
{
    uchar i;
    uint data_ad = 0;
    CS = 1;                //初始化,启动
    CLK = 0;
    CS = 0;
    _nop_();            
    for(i = 0;i < 8;i++)    //读取采集数据,读取的是上一次采集数据
    {
        CLK = 1;     
        if(DIO)data_ad |= 0x01;
        CLK = 0;  
        data_ad = data_ad << 1;  
    }     
    CS = 1;
    data_ad = data_ad  * (500/ 256);   
    return(data_ad);
}

/**********************************************
    函数名称:TLC5615_DA(uint da)
    函数作用:TLC5615_DA 将da转换后模拟输出
    函数参数:da
    函数返回值:无
**********************************************/   
void TLC5615_DA(uint da) //    TLC5615 的DA 转换函数
{
    uchar i;
    da<<=6;

    SCS=0;
    SCLK=0;

    for (i=0;i<12;i++)
    {
        SDATA=(bit)(da&0x8000);
        SCLK=1;
        da<<=1;
        SCLK=0;
    }

    SCS=1;
    SCLK=0;
    for (i=0;i<12;i++);
}
/**********************************************
    函数名称:key_scan()
    函数作用:处理那些独立键盘
    函数参数:无
    函数返回值:无
**********************************************/   
void key_scan()
{
    if (ADD == 0)                           // ADD 按键的键盘处理函数
    {
        delay(10);
        if (ADD == 0)
        {
            add_stat = 1;
            num ++;
        }
        else
        {
            add_stat = 0;
            num = 0;
        }
        //此处判断是不是长按,长按的话 使其步进值 加大
        if (ADD == 0 && add_stat == 1 && num >= 300)  
        {
            val += 5;
            num = 0;
        }
        if (ADD == 1 && add_stat == 1)
        {
            val ++;
            num = 0;
            add_stat = 0;
        }
        if (val >= 1024)
        {
            val = 1023;
        }
    }

    if (SUB == 0)                            //SUB 按键的键盘处理函数
    {
        delay(10);
        if (SUB == 0)
        {
            sub_stat = 1;
            num ++;
        }
        if (SUB == 0 && sub_stat == 1 && num >= 300)
        {
            val -= 5;
            num = 0;
        }
        if (SUB == 1 && sub_stat == 1)
        {
            val --;
            num = 0;
            sub_stat = 0;
        }
        if (val <= 0)
            val = 0;
    }
                                    
    if (Pre_read == 0)                           //预读数据的 键盘处理函数
    {
        delay(100);
        if (Pre_read == 0)
        {
            pre_flag = 1;
        }
        if (Pre_read == 1 &&pre_flag == 1 )
        {
            pre_flag = 0;
            val = read_24C04(20);            //从AT24C04中的地址20 中读出预存储的数据
        }
    }

    if (Store == 0)                        //保存数值 按键的键盘处理函数
    {
        delay(100);
        if (Store == 0)
        {
            st_flag = 1;
        }
        if (Store == 1 && st_flag == 1)
        {
            st_flag    = 0;
            write_24C04(20,val);         //向AT24C04中的地址20 写入存储的数据
        }
    }
}
/**********************************************
    函数名称:timer0_init (void)
    函数作用:初始化定时器0,并设置
    函数参数:无
    函数返回值:无
**********************************************/   
void timer0_init (void)                    // timer0中断初始化函数
{
    EA = 0;                     
    TMOD = 0x01;            
    TR0 = 0;                     
    TL0 = (65536-5000)%256;         //设置计数器初值
    TH0 = (65536-5000)/256;                  
    PT0 = 1;                     
    ET0 = 1;                     
    EA = 1;                     
    TR0 = 1;                     
}
/**********************************************
    函数名称:main(void)
    函数作用:main主函数入口
    函数参数:无
    函数返回值:无
**********************************************/                           
void main(void)                 //主程序
{  
    timer0_init();            //初始化定时器0
    init_24C04();            //初始化AT24C04
    while(1)
    {
        key_scan();            //调用键盘扫描函数
        TLC5615_DA(val);    //处理键盘发送过来的值
    }
}

/**********************************************
    函数名称:timer0_isr(void)  interrupt 1
    函数作用:定时器0,方式1,的中断服务子程序
    函数参数:无
    函数返回值:无
**********************************************/   
void timer0_isr(void)  interrupt 1           // timer0中断服务函数
{
                                             //数码管的位选变量
    TR0 = 0;                                    //停止计数
    TL0 = (65536-5000)%256;                    //重新载入计数器初值
    TH0 = (65536-5000)/256;
    cp++;                                    //位循环变量加1
    if(cp >= 4)
        cp = 0;
    deal(TL549_AD());                       //循环显示1次,j清零
       TR0 = 1;

    P0=0xff;  //与j对应,P2输出数码管的位选信号
    switch(cp)
    {
        case 0: P0 = LED[ge]; break;      
        case 1: P0 = LED[shi]; break;      
        case 2: P0 = LED[bai]&0x7f; break;
        case 3: P0 = LED[qian]; break;      
    }
    P2 = Bit_sel[cp];
}  
AT24C04 的驱动:
    #ifndef AT24C04_10_04_07

sbit ATCLK=P1^6;
sbit SDA=P1^7;


sbit a7=ACC^7;
sbit a6=ACC^6;
sbit a5=ACC^5;
sbit a4=ACC^4;
sbit a3=ACC^3;
sbit a2=ACC^2;
sbit a1=ACC^1;
sbit a0=ACC^0;
/*********************
*******24C04的初始化**
**** **************/
void init_24C04()
{
    SDA=1;
    _nop_();
    ATCLK=1;
    _nop_();
}
/*********************
****启动24C04*********
*******************/
void start_24C04()
{

    SDA=1;
    _nop_();
    ATCLK=1;
    _nop_();

    SDA=0;
    _nop_();
    ATCLK=0;
    _nop_();
}
/********************
*****停止24C04*******
*********************/
void stop_24C04()
{
    SDA=0;
    _nop_();

    ATCLK=1;
    _nop_();
    SDA=1;
    _nop_();

}
/*********************
****24C04应答*********
*******************/
void response()
{
    unsigned char i;
    ATCLK=1;
    _nop_();
    while((SDA==1)&&(i<250))i++;
    ATCLK=0;
    _nop_();   
}
/********************
*****读取24C04一个字节**
**************************/
unsigned char read_byte()
{
    SDA=1;
    ATCLK=1;a7=SDA;ATCLK=0;
    ATCLK=1;a6=SDA;ATCLK=0;
    ATCLK=1;a5=SDA;ATCLK=0;
    ATCLK=1;a4=SDA;ATCLK=0;
    ATCLK=1;a3=SDA;ATCLK=0;
    ATCLK=1;a2=SDA;ATCLK=0;
    ATCLK=1;a1=SDA;ATCLK=0;
    ATCLK=1;a0=SDA;ATCLK=0;
    SDA=1;
    ATCLK=0;
    return ACC;
}
/*************************
**写入24C04一个字节******
*************************/
void write_byte(unsigned char addr)
{
    ACC=addr;
    SDA=a7;ATCLK=1;ATCLK=0;
    SDA=a6;ATCLK=1;ATCLK=0;
    SDA=a5;ATCLK=1;ATCLK=0;
    SDA=a4;ATCLK=1;ATCLK=0;
    SDA=a3;ATCLK=1;ATCLK=0;
    SDA=a2;ATCLK=1;ATCLK=0;
    SDA=a1;ATCLK=1;ATCLK=0;
    SDA=a0;ATCLK=1;ATCLK=0;
    SDA=1;
    ATCLK=0;

}
/***********************
**写24C04的数据*******
*****************/
void write_24C04(unsigned char addr,unsigned char dat)
{
    start_24C04();
    write_byte(0xa0);
    response();
    write_byte(addr);
    response();
    write_byte(dat);
    response();
    stop_24C04();
}
/**********************
***读24C04的数据*******
*****************/
unsigned char read_24C04(unsigned char addr)
{
    unsigned char t;
    start_24C04();
    write_byte(0xa0);
    response();
    write_byte(addr);
    response();
    start_24C04();
    write_byte(0xa1);
    response();
    t=read_byte();
    stop_24C04();
    return t;
}
#endif

仿真程序下载(注意仿真文件是Proteus7.8版本的dsn文件,请勿用高版本的打开): 基于单片机的稳压电源设计.7z (75.3 KB, 下载次数: 11)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表