嵌入式系统应用实训

嵌入式系统应用实训

论文

                    简易数控直流稳压电源 

                               电信0912        

                                          

                                  

                              

                                                       

  2011 6

一、    方案设计

前言
数控直流电源是一种常见的电子仪器,广泛应用于电路,教学试验和科学研究等领域。目前使用的可控直流电源大部分是点动的,利用分立器件,体积大,效率低,可靠性差,操作不方便,故障率高。随着电子技术的发展,各种电子,电器设备对电源的性能要求提高,电源不断朝数字化,高效率,模块化和智能化发展。以单片机系统为核心而设计的新一代——数控直流电源,它不但电路简单,结构紧凑,价格低廉,性能优越,而且由于单片机具有计算和控制能力,利用它对数据进行各种计算,从而可排除和减少模拟电路引起的误差,输出电压和限定电流采用数输入采用键盘方式,电源的外表美观,操作使用方便,具有较高的使用价值。

1、设计要求:(1)输出电压:范围0~+9.9V,步进0.1V;

            (2)输出电流:500m A;

            (3)输出电压值由数码管显示;

            (4)由“+”、“—”两键分别控制输出电压步进增减;

2、实训目的:

(1)掌握模拟电子电路与数字电路分析和设计能力;

(2)掌握电路基本设计工艺和常用仪器仪表的使用能力,熟练排除电路故障;

(3)具备电路装配、检测与调试工艺和流程控制能力;

(4)具备电路测试方案设计能力和测试数据分析能力;

3、工作原理:

简易数控直流稳压电源主要包括三大部分:数字控制部分,D/A变换部分及可调稳压部分。完成这三大部分功能的电路及集成芯片品种很多。合理的设计及选择电路则是完成本设计的关键。除了上述的三大部分之外,还包括一些附加的功能电路,如电压显示、控制、防止误操作等。

数字控制部分用+/-按键控制产生可增加或减少BCD码,BCD码输入到D/A变换,变换成相应的电压,此电压通过放大到合适的电平后加到可调稳压部分,控制输出电压以手动0.1V的电压步进或步减,或自动连续步进(减),或直接变化到某一设定的电压值。

方案一:采用数字电位器与运放到组合

在该方案中我们用两个数字电位器代替了MCU中的D/A,这样可以降低成本,同时简化电路,从两个串连的数字电位器可以直接输出-5V到+5V的电压同上面方案一样,当输出反相电压时在送电压回A/D采样时要先经过一次反相。但同样存在上面的问题。
优点:电路结构更简单,降低了成本
缺点:因为数字电位器电阻误差大,且单片机的A/D口容易损坏。

方案二:采用7805构成直流电源

采用7805构成直流电源的电路,改变RP阻值使7805的公共端的电压在0到-10V之间可调,则7805的    输出端电压就可实现0V-+9.9V之间可调了。这种方案是利用了7805的输出端与公共端的电压固定为+5的特性来设计的。但同样存在不好数控的问题。

方案三  方案一与方案二结合,然后再以+5V为参考输出
    如上图所示,采用数模转换器输出电流,经电压转换和反向放大之后得到0V~9.9V的电压,把这个电压送到三端稳压器件7805的公共端,然后,再以+5V作为参考则输出的电压就能实现在0V~+9.9V任意可调。采样时,是对地采样的,就省去了负电压不好采样的麻烦,这也是我们的创新之处。

二、 硬件设计

方案一:数控部分用单片机带动数模转换芯片提供线性稳压电压的参考电压。

优点:对于单片机,系统工作在开环状态,对数模转换的精度要求较高,设计成本低。

缺点:功耗较大,数码管输出显示不足系统的精确输出电压,须对它进行软件补偿。

方案二:数控部分用AVR单片机的PWM组成开关电源,再利用AVR的AD转换对输出电压进行实时转换,利用软件进行电压调整以达到稳压。

优点:硬件简单,稳压的大部分工作由软件完成。

缺点:对单片机的运行速度要求很高,利用手头的ATmaga16L单片机最高8MHz工作频率很难达到速度要求。对软件要求较高,功耗小。

设计思想

以STC89C51为核心的单片机控制,通过编程,并通过按键来进行数据的改变,并通过P2口将数据传给TLC5615芯片输出电流信号,再通过LM324芯片将电流转换成电压并放大再经过滤波作为LM317的基准电压实现的稳压直流电源,同时单片机P0口输出相应代码使数码管显示相应的电流值。设计的关键调好TLC5615的基准电压,作品的精度就能够实现。

三、 软件设计

本系统软件设计要实现的功能是:按键对单片机输入数据,单片机对获得的数据进行处理,处理后的数据送3位8段共阳数码管,同时送到8位数模转换芯片(TLC5615),以实现数字量对电压的控制。系统中的主程序主要完成按键扫描、判断、处理和数码显示。

上图为主程序流程图,程序一开始对硬件进行初始化,例如系统对YLC5615单片机端口进行定义,然后进行按键判断处理程序,首先通过按键扫描判断是否有按键按下,进入按键服务陈旭,否则继续读按键状态。

根据按键功能表,软件设计部分中键盘实现的功能如下:

按“调整”键开始社决定电压,超过0~9V视为无效操作,十位、个位、十分位循环输入,按“确认”键确认,不再闪动。按过“调整”键后,按“增加”键,数值控制住在0~9,调整需要值后按确定键。按“—”键进行减0.1V微调,按“+”键进行加0.1V微调。

键盘服务程序如下:

四. 制作与调试

硬件的调试过程:

1、 输出电压:范围0V~+9.V,步进0.1V。。初始状态时,可以通过4个按键输入.0V~+9.9V之间的任意电压值,并实时显示。显示值与实际测量值同步,且在0V~+9.9V之间的调节过程中最大误差为0.03V;
2、 输出电压可预置在0V~+9.9V之间的任意一个值,并且设有电压步进0.1V的增减键,实时可调,有自动扫描代替人工按键功能,步进0.1V ;
3、 输出电流≤500mA ;
4、 输出电压调整率≤0.5%(输入电压220V变化范围+15%~-20%下,空载到满载);                               
    输出电压/ 输出电流特性:
分析:输出电压在无负载时,已调整到5.00V,在500mA输出电流流动时,输出电压为4.94,要比此时无负载电压5.00V低0.06V(1.2%)。因此对电源的等效输出电阻进行计算为0.12Ω(0.06V/500mA)
   由于射极跟随器的输出阻抗为数欧,可以知道,加上负反馈之后大大减小了电源的输出阻抗。

5、在调试过程中,碰到了电阻不够大,后来经过计算,我们又串联了一个2.7K的电阻,这样电压就更加稳定了,可以输出相应的电压值。
6、线性度:(测试数据分析)

软件的调试过程:

DA转换器的内部电路构成无太大差异,一般按输出是电流还是电压、能否作乘法运算等进行分类。大多数DA转换器由电阻阵列和n个电流开关(或电压开关)构成。按数字输入值切换开关,产生比例于输入的电流(或电压)。此外,也有为了改善精度而把恒流源放入器件内部的。一般说来,由于电流开关的切换误差小,大多采用电流开关型电路,电流开关型电路如果直接输出生成的电流,则为电流输出型DA转换器,如果经电流椀缪棺缓笫涑觯蛭缪故涑鲂?/FONT>DA转换器。此外,电压开关型电路为直接输出电压型DA转换器。

TLC5615是一个串行10位DAC芯片,性能比早期电流输出的DAC要好。只需要通过3根串行总线就可以完成10位数额的串行输入,易于和工业标准的微处理器或控制器(单片机)接口,适用于电池供电的测试仪表、移动电话,也适用于数字失调于增益调整以及工业控制场合。其主要特点如下:

供5V电源工作、3线串行接口、高阻抗基准输入端、DAC输出的最大电压为2倍基准输入电压、上电时内部自动复位、微处理,最大功耗为1.75m W、转换速率快,更新率为1.2MHz。

五、总结

本设计制作完成了题目要求的基本部分,达到了预期目标。本系统以高性能STC89C51单片机芯片和8位精度的DA转换器TLC5615为核心部件,利用常用的三端稳压器件7805的公共端与输出端固定的5伏电压特性,最终实现了数字显示输出电压值和电流值可实时控制并显示的高性能数控电源 。

   通过此次数控直流稳压电源的设计,我对数控直流稳压电源的结构有了很深的理解。我们综合应用课本上的理论解决实际问题的能力得到了提高,我觉得课程设计对我们的帮助很大,它需要我们将学过的理论知识与实际情况联系起来,加强我们对学过的知识的实际应用能力。在这次课程设计过程中,我遇到了几个自己不能解决的问题,通过老师和同学的帮助,最终把问题解决,因此,我发现自己的电子知识还是有限的,而且我们所学的理论知识是很有用的,没有坚实的知识基础,是不可能完成设计的。通过自己实际地设计和操作,也进一步熟悉了各种模拟和数字器件的功能和软件的基本功能,体会到了设计电子产品的过程和其深刻意义。

附录1:单片机程序

#include<at89x52.h>

#define CS   P1_2

#define DIN  P1_0

#define CLK  P1_1

 void delay(void);

 unsigned char a[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

 unsigned char b[6]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb};

 unsigned char x=5,y=0;z=0;

 unsigned char c[3];

 unsigned char i,m,s=3,temp,flg,count=0,h,j;

///////////////////////////////////////////////////////////////////////////////////

void hex_to_bcd(void)

{

    c[0]=x%10/1;

    c[1]=y%10/1;

    c[2]=z%10/1;

}

//////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////

void display(void)

{

  unsigned char i;

  for(i=0;i<3;i++)

  { if(m>20&&(i==s))     P0=0xff;             

    else {    P0=a[c[i]];

        if(i==0)  P0=a[c[i]]&0X7f;

         }

     P2=b[i];delay();

    }m++;if(m==40)m=0;

}

//////////////////////////////////////////////////////////////////////////////////

/*

/////////////////////////////////////////////////////////////////////////////////

void key(void)

{

  temp=P3;temp=temp|0xc3;

 if(temp!=0xff)          

 {delay();    

  temp=P3;temp=temp|0xc3;

  if(temp!=0xff){

                  if(temp==0xfb)  { s=s+2; if(s>6) s=0; if(s<6) TR0=0;else TR0=1;}

 //K4 1111 1011 

                             if(temp==0xf7)  {if(s==0) {x++; if(x>23) x=0;}

                                               else if(s==2) {y++;if(y>59) y=0;}

                                                           else if(s==4) {z++;if(z>59) z=0;}

                                                           }//K3 1111 0111

                             if(temp==0xef)  {if(s==0) { if(x==0) x=23; else x--;}

                                               else if(s==2) {if(y==0) y=59; else y--;}

                                                           else if(s==4) {if(z==0) z=59; else z--;}

                                                           }//K2 1110 1111

                              while((P3|0xc3)!=0xff) {display();}

                              }

  }

}

//////////////////////////////////////////////////////////////////////////////////

*/

////////////////////////////////////////////////////////////////////////////////

void da_delayus(unsigned char t)

{ unsigned char i;

  for(i=0;i<t;i++)

  {;}

}

 void yc(void)

{

 unsigned char i;

 unsigned int tmp;

 tmp=(x*100L+y*10+z)<<2;

 CLK=0;

 CS=0;

 for(i=0;i<12;i++)

 {

       if((tmp&0x0800)==0) DIN=0;

       else                    DIN=1;

       tmp=tmp<<1;

    CLK=1;

       da_delayus(1);   

       CLK=0;

       da_delayus(1);

       }

  CS=1;

 }

/////////////////////////////////////////////////////////////////////////////////

void key(void)

{

  temp=P3;temp=temp|0xd3;  //11010011

 if(temp!=0xff)          

 {delay();    

  temp=P3;temp=temp|0xd3;

  if(temp!=0xff){ switch(temp)

                  {

                                case 0xfb: s=s+1; if(s==3) yc(); if(s>3) s=0;

                                              break;  //K4 1111 1011  

                               case 0xf7: if(s==0) {x++; if(x>9) x=0;}

                                           else if(s==1) {y++;if(y>9) y=0;}

                                                    else if(s==2) {z++;if(z>9) z=0;}

                                                    break;//K3 1111 0111

                               case 0xdf: if(s==0) { if(x==0) x=9; else x--;}

                                           else if(s==1) {if(y==0) y=9; else y--;}

                                                    else if(s==2) {if(z==0) z=9; else z--;}

                                                    break;//K1 1101 1111

                              }

                              while((P3|0xd3)!=0xff) {display();}

                }

 }

}

//////////////////////////////////////////////////////////////////////////////////

main()

  yc();

  while(1)

  {

   hex_to_bcd();

   display();

   key();

   }

}

/////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

void delay(void)

{ unsigned char j,k;

  for(k=0;k<100;k++)

  for(j=0;j<10;j++);

  }

//////////////////////////////////////////////////////////////////////////////

附录2:程序清单

 

第二篇:嵌入式系统的开发与应用实习任务书

嵌入式系统的开发与应用实习任务书

一、实习目的:

通过一个参数个数不固定函数的设计和调试,练习嵌入式系统C程序的设计方法。

二、实习内容

编写一个简化的仿scanf函数,名为myscanf函数,实现从键盘中输入十进制整数和小数型实数的功能。该函数格式如下

int myscanf(char *formatstr,...)

在VC平台上开发。

三、实习具体要求

1.第一个参数是格式字符串,格式只识别%d和%f这两种格式,分别表示十进制int型数据(32位有符号整数)和小数格式的double型数据。在格式字符串中,如果发现%后有其它字符(非d和非f),认为有错,停止处理,并打印出错信息,返回-1。

2.当然输入的整数数据超出范围时,按出错处理,停止处理,并打印出错信息,返回-1。由于小数格式double类型的整数部分最多可以到达三百多位,因此我们不处理超出数据范围的错误。

3.在格式的其他字符匹配中,只要有不匹配的字符,按出错处理,停止处理,并打印出错信息,返回-1。

4.该函数只处理一行数据,不处理跨行数据。

5.当处理正确完成后,返回值就是输入的整数和实数的总个数。

6.可以使用C语言本身所带的gets函数。

五、实习报告要求

1.所提交内容包括程序设计书和程序清单两部分

2.所做程序必须保证程序的健壮性。在完成基本功能的同时,能处理各种错误 处理以及意外事件。

3.提交的程序设计书应该包含各个过程的功能、参数说明。并用流程图表示该 过程的算法。

4.所提交的程序必须结构清晰,层次分明。程序应该有比较好的可读性。程 序清单中至少30%是注解。

// test.cpp : Defines the entry point for the console application. //

#include "stdafx.h"

#include <stdio.h>

#include <string.h>

#include <stdarg.h>

#define MAX_LEN 200

#define MAX_POSINTSTR "2147483647" //最大整数字符串

#define MAX_NEGINTSTR "2147483648" //最小整数绝对值字符串

/*

判断一个整数字符串是否越界

如果越界则返回1-,否则返回0

intstr:用于判断的整数字符串

*/

int defineoverflow(char *intstr)

{

int n1,i,n2;

char standstr[15];

if(intstr[0]=='-')

{

//如果是负数,则用最小整数绝对值进行判断 strcpy(standstr, MAX_NEGINTSTR);

intstr++; //越过负号

}

else

{

//如果是负数,则用最小整数绝对值进行判断 strcpy(standstr, MAX_POSINTSTR);

if(intstr[0]=='+')

intstr++; //越过正符号

}

n1 = strlen(intstr);

n2 = strlen(standstr);

//整数字符串位数过长,则定越界,返回-1

if(n1 > n2)

return -1;

//整数字符串位数较短,则肯定不越界,返回0

if(n1 < n2)

return 0;

//如果位数一样,从最高位开始比较

for(i = 0; i < n1;i++)

{

if(intstr[i] < standstr[i]) return 0;

if(intstr[i] > standstr[i]) return -1;

}

//如果刚好是极限值

return 0;

}

/*

从整型字符串得到整数值

intstr:整形字符串

返回值是所得到的整数

*/

int getintvalue(char *intstr)

{

int sgn; //符号变量,表示该整数的正负 int v = 0;

char *p = intstr;

if(intstr[0]=='-')

{

sgn = -1;

p++;

}

else

{

sgn = 1;

if(intstr[0]=='+')

p++;

}

while(*p!='\0')

{

v = v*10 + (*p - '0');

p++;

}

v = v * sgn;

return v;

}

/*

从实型字符串得到double值 doublestr:整形字符串

返回值是所得到的实数值

*/

double getdoublevalue(char *doublestr)

{

int sgn; //符号变量,表示该整数的正负

double v = 0;

char *p = doublestr;

double k = 10; //小数的比例因子

if(doublestr[0]=='-')

{

sgn = -1;

p++;

}

else

{

sgn = 1;

if(doublestr[0]=='+')

p++;

}

while(*p!='\0' && *p!='.')

{

v = v*10 + (*p - '0');

p++;

}

if(*p=='.')

{ p++;

while(*p!='0')

{

v += (*p - '0')/k;

k = k* 10;

p++;

}

}

v = v * sgn;

return v;

}

/*

匹配普通字符串,要求输入字符串中指定位置之处存在一个完全匹配的子串

ppf :一个二维指针,它所指向的指针值就是格式字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

ppin:一个二维指针,它所指向的指针值就是输入字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

成功返回0,否则返回-1。

#include "stdafx.h"

#include <stdio.h>

#include <string.h>

#include <stdarg.h>

#define MAX_LEN 200

#define MAX_POSINTSTR "2147483647" //最大整数字符串

#define MAX_NEGINTSTR "2147483648" //最小整数绝对值字符串

/*

判断一个整数字符串是否越界

如果越界则返回1-,否则返回0

intstr:用于判断的整数字符串

*/

int defineoverflow(char *intstr)

{

int n1,i,n2;

char standstr[15];

if(intstr[0]=='-')

{

//如果是负数,则用最小整数绝对值进行判断 strcpy(standstr, MAX_NEGINTSTR);

intstr++; //越过负号

}

else

{

//如果是负数,则用最小整数绝对值进行判断 strcpy(standstr, MAX_POSINTSTR);

if(intstr[0]=='+')

intstr++; //越过正符号

}

n1 = strlen(intstr);

n2 = strlen(standstr);

//整数字符串位数过长,则定越界,返回-1

if(n1 > n2)

return -1;

//整数字符串位数较短,则肯定不越界,返回0

if(n1 < n2)

return 0;

//如果位数一样,从最高位开始比较

for(i = 0; i < n1;i++)

{

if(intstr[i] < standstr[i])

return 0;

if(intstr[i] > standstr[i]) return -1;

}

//如果刚好是极限值

return 0;

}

/*

从整型字符串得到整数值

intstr:整形字符串

返回值是所得到的整数

*/

int getintvalue(char *intstr)

{

int sgn; //符号变量,表示该整数的正负 int v = 0;

char *p = intstr;

if(intstr[0]=='-')

{

sgn = -1;

p++;

}

else

{

sgn = 1;

if(intstr[0]=='+')

p++;

}

while(*p!='\0')

{

v = v*10 + (*p - '0');

p++;

}

v = v * sgn;

return v;

}

/*

从实型字符串得到double值 doublestr:整形字符串

返回值是所得到的实数值

*/

double getdoublevalue(char *doublestr) {

int sgn; //符号变量,表示该整数的正负 double v = 0;

char *p = doublestr;

double k = 10; //小数的比例因子

if(doublestr[0]=='-')

{

sgn = -1;

p++;

}

else

{

sgn = 1;

if(doublestr[0]=='+')

p++;

}

while(*p!='\0' && *p!='.')

{

v = v*10 + (*p - '0');

p++;

}

if(*p=='.')

{ p++;

while(*p!='\0')

{

v += (*p - '0')/k;

k = k* 10;

p++;

}

}

v = v * sgn;

return v;

}

/*

匹配普通字符串,要求输入字符串中指定位置之处存在一个完全匹配的子串

ppf :一个二维指针,它所指向的指针值就是格式字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

ppin:一个二维指针,它所指向的指针值就是输入字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

成功返回0,否则返回-1。

*/

int matchstr(char **ppf, char **ppin)

{

char *pf = *ppf;

char *pin = *ppin;

while(*pf!='\0' && *pf!='%')

{

if(*pf!=*pin)

{

*ppf = pf;

*ppin = pin;

return -1;

}

pf++;

pin++;

}

*ppf = pf;

*ppin = pin;

return 0;

}

/*

匹配整数,要求输入字符串中指定位置之处提取一个整数

intstr :存放所提取的整数字符串

ppin:一个二维指针,它所指向的指针值就是输入字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

成功返回0,否则返回-1。

*/

int matchint(char *intstr, char **ppin)

{

char *pin = *ppin;

int i = 0;

int j;

//略去所有空格

while(*pin==' ')

pin++;

if(*pin=='-')

intstr[i++] = *pin++;

else if(*pin=='+')

intstr[i++] = *pin++;

j = i;

while(*pin>= '0' && *pin<= '9')

{

intstr[j++] = *pin++;

}

if(i == j)

{

//一个整数不能没有任何数字

return -1;

}

intstr[j] = '\0';

*ppin = pin;

return 0;

}

/*

匹配实数,要求输入字符串中指定位置之处提取一个实数

doublestr :存放所提取的实数字符串

ppin:一个二维指针,它所指向的指针值就是输入字符串中的开始匹配的位置,当匹配

结束后,它所指向的指针值应该是下一个匹配的起始位置,传回给调用函数

成功返回0,否则返回-1。

*/

int matchdouble(char *doublestr, char **ppin)

{

char *pin = *ppin;

int i = 0;

int j;

//略去所有空格

while(*pin==' ')

pin++;

if(*pin=='-')

doublestr[i++] = *pin++;

else if(*pin=='+')

doublestr[i++] = *pin++;

j = i;

while(*pin>= '0' && *pin<= '9')

{

doublestr[j++] = *pin++;

}

if(*pin == '.')

{

doublestr[j++] = '.';

pin++;

while(*pin>= '0' && *pin<= '9')

{

doublestr[j++] = *pin++;

}

}

if(i == j)

{

return -1;

}

doublestr[j] = '\0';

*ppin = pin;

return 0;

}

int myscanf(char *formatstr,...)

{

char inputstr[MAX_LEN]; //存放从键盘输入的字符串 char *pin;

char *pf;

char intstr[MAX_LEN];

char doublestr[MAX_LEN];

va_list marker;

int *d; //存放整数参数的地址

double *r; //存放实数参数的地址

//参数列表初始化

va_start(marker, formatstr);

gets(inputstr);

pin = inputstr;

pf = formatstr;

while(*pf!='\0')

{

if(*pf=='%')

{

pf++;

if(*pf=='d')

{

//匹配整数

if(matchint(intstr, &pin)==-1) {

va_end(marker);

return -1;

}

if(defineoverflow(intstr)==-1) {

va_end(marker);

return -1;

}

d = va_arg(marker, int* ); *d = getintvalue(intstr);

pf++;

}

else if(*pf=='f')

{

//匹配实数

if(matchdouble(doublestr, &pin)==-1) {

va_end(marker);

return -1;

}

r = va_arg(marker, double* ); *r = getdoublevalue(doublestr);

pf++;

}

else

{

va_end(marker);

return -1;

}

}

else

{

//匹配普通字符串

if(matchstr(&pf, &pin)==-1)

{

va_end(marker);

return -1;

}

}

}

va_end(marker);

return 0;

}

void main()

{

int x;

double y,z;

if(myscanf("%d#%f#%f",&x, &y, &z)==-1)

{

printf("EEROR\n");

return ;

}

printf("%d %lf %lf\n", x,y,z);

}}

相关推荐