找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3121|回复: 0
打印 上一主题 下一主题
收起左侧

基于MSP430单片机的可调恒流源Proteus仿真程序设计

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
/******************************************************************
* 实验说明:
*     通设置系统主时钟(MCLK=8Mhz ) 、辅助时钟(ACLK=8Mhz )、
*      子系统时钟(SMCLK=8Mhz )
******************************************************************/

#include <MSP430x24x.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int

/**************定义接口************************/
#define LCDIO     P1OUT
#define LCD1602_RS_1  P2OUT|=1  
#define LCD1602_RS_0  P2OUT&=~1
#define LCD1602_EN_1   P2OUT|=2
#define LCD1602_EN_0   P2OUT&=~2

#define PWM_1   P2OUT|=8
#define PWM_0   P2OUT&=~8


/**************定义函数************************/
void LCD_write_command(unsigned char command);//写入指令函数
void LCD_write_dat( unsigned char dat);//写入数据函数
void LCD_set_xy( unsigned char x, unsigned char y );//设置显示位置函数
void LCD_dsp_char( unsigned char x,unsigned char y, char dat);//显示一个字符函数
void LCD_dsp_string(unsigned char X,unsigned char Y,const char *s);//显示字符串函数
void LCD_init(void);//初始化函数
void delay_nms(unsigned int n);//延时函数

void TCL5615_DAC(unsigned int Data);
/********************************************/

//变量定义
unsigned char Disbuf[12],flag;

int DAC_num = 5;

unsigned char KEY_OPEN_OR_STOP_times = 1;


//ADC采集函数
void RefreshDis0(unsigned int Data0)
{
  if( Data0 < 10 )
  {
    Disbuf[0] = 0x30 + Data0/100%10;
    Disbuf[1] = '.';
    Disbuf[2] = 0x30 + Data0/10%10;
    Disbuf[3] = 0x30 + Data0%10;
    Disbuf[4] = 'V';
  }
  else
  {
    Disbuf[0] = 0x30 + Data0/100%10;
    Disbuf[2] = 0x30 + Data0/10%10;
    Disbuf[1] = '.';
    Disbuf[3] = 0x30 + Data0%10;
    Disbuf[4] = 'V';
  }
}
//ADC采集函数
void RefreshDis1(unsigned int Data1)
{
    Disbuf[5] = 0x30 + Data1/100%10;
    Disbuf[6] = 0x30 + Data1/10%10;
    Disbuf[7] = 0x30 + Data1%10;
    Disbuf[8] = 0x30;
    Disbuf[9] = 'm';
    Disbuf[10] = 'A';
}

void P23_Onclick( void )
{
  //50mA
   DAC_num = DAC_num + 10;
   if( DAC_num > 420 )
   {
     DAC_num = 420;
   }
    TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA

}

void P24_Onclick( void )
{
  //50mA
   DAC_num = DAC_num - 10;
   if( DAC_num < 5 )
   {
     DAC_num = 5;
   }
    TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA

}

void P25_Onclick( void )
{
    DAC_num = 5;
    TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA

}

void P26_Onclick( void )
{
  //10mA
   DAC_num = DAC_num + 2;
   if( DAC_num > 420 )
   {
     DAC_num = 420;
   }
    TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA

}

void P27_Onclick( void )
{
    //10mA
   DAC_num = DAC_num - 2;
   if( DAC_num < 5 )
   {
     DAC_num = 5;
   }
    TCL5615_DAC( DAC_num );                      //205 对应1.0V    410  对应2.0V   5---20mA

}

//电压显示函数
void Display( void )
{
    LCD_write_command( 0x80 );
    LCD_write_dat('V');
    LCD_write_dat(':');
    LCD_write_dat( Disbuf[0] );
    LCD_write_dat( Disbuf[1] );
    LCD_write_dat( Disbuf[2] );
    LCD_write_dat( Disbuf[3] );
    LCD_write_dat( Disbuf[4] );
    LCD_write_dat( ' ' );
    LCD_write_dat('I');
    LCD_write_dat(':');
    if( Disbuf[5] != 0x30 )
    {
      LCD_write_dat( Disbuf[5] );
    }
    if( Disbuf[6] != 0x30 )
    {
      LCD_write_dat( Disbuf[6] );
    }
    LCD_write_dat( Disbuf[7] );
    LCD_write_dat( Disbuf[8] );
    LCD_write_dat( Disbuf[9] );
    LCD_write_dat( Disbuf[10] );
}


void Display_Set( void )
{
   LCD_write_command( 0x80 + 0x40 );
   LCD_write_dat( 'S' );
   LCD_write_dat( 'e' );
   LCD_write_dat( 't' );
   LCD_write_dat( ':' );
   if( Disbuf[5] != 0x30 )
    {
      LCD_write_dat( Disbuf[5] );
    }
    if( Disbuf[6] != 0x30 )
    {
      LCD_write_dat( Disbuf[6] );
    }
   LCD_write_dat( Disbuf[7] );
   LCD_write_dat( Disbuf[8] );
   LCD_write_dat( Disbuf[9] );
   LCD_write_dat( Disbuf[10] );
   LCD_write_dat( ' ' );
    LCD_write_dat( ' ' );
     LCD_write_dat( ' ' );

   if( KEY_OPEN_OR_STOP_times == 1 )
   {
     LCD_write_dat( 'O' );
     LCD_write_dat( 'P' );
     LCD_write_dat( 'E' );
     LCD_write_dat( 'N' );
   }
   if( KEY_OPEN_OR_STOP_times == 2 )
   {
     LCD_write_dat( 'S' );
     LCD_write_dat( 'T' );
     LCD_write_dat( 'O' );
     LCD_write_dat( 'P' );
   }
}

/*******延时函数************/
void delayms(uint t)
{
    uint i;
    while(t--)
      for(i=1330;i>0;i--);//进过参数的调整
}

/*******检查忙函数*************/
void LCD_check_busy()      //实践证明,在我的LCD1602上,检查忙指令通过率极低,以
{                                          //至于不能正常使用LCD。因此我没有再用检查忙函数。而使

        P1DIR=0x00;
        LCDIO=0xff;
        LCD1602_RS_0;                 //要用200次循环便能完成。   
        LCD1602_EN_1;
        while(P1IN&0x80);
        LCD1602_EN_0;
        P1OUT=0x00;
        P1DIR=0xFF;
}
/******************************/

/**************写指令函数********************************/  
void LCD_write_command(unsigned char command)
{

        LCD1602_RS_0;   
        LCDIO=command;
        LCD1602_EN_1;

        LCD1602_EN_0;
        delayms(1);

}
/***************************************************/
/****************写数据函数************************/
void LCD_write_dat( unsigned char dat)
{
      LCD1602_RS_1;
      LCDIO=dat;
      LCD1602_EN_1;

      LCD1602_EN_0;
      delayms(1);
      LCD1602_RS_0;


}
/****************************************************/
/***************设置显示位置**************************/
void LCD_set_xy( unsigned char x, unsigned char y )
{
        unsigned char address;
        if (y == 1)
             address = 0x80+x;
        else if (y == 2)
        {
               address=0x80+0x40+x;

        }
        LCD_write_command(address);
}
/***************************************************/
/****************显示一个字符**********************/
void LCD_dsp_char( unsigned char x,unsigned char y, char dat)
{
        LCD_set_xy( x, y );
        LCD_write_dat(dat);
}
/**********************************************/
/***************显示字符串函数***************/
void LCD_dsp_string(unsigned char X,unsigned char Y,const char *s)
{
       uchar len,List;
       len=strlen(s);
       LCD_set_xy( X, Y );
       for(List=0;List<len;List++)
       LCD_write_dat(s[List]);

}
/***********************************************/
/********** 延时**********************/
void delay_nms(unsigned int n)      
{
       unsigned int i=0,j=0;
       for (i=n;i>0;i--)
       for (j=0;j<1;j++);  
}
/**************************************/
/************初始化函数****************/
void LCD_init(void)
{
      LCD1602_EN_0;
      //CLEARSCREEN;//clear screen
      LCD_write_command(0x38);//set 8 bit data transmission mode
      delayms(1);
      LCD_write_command(0x38);//set 8 bit data transmission mode
      delayms(1);
      LCD_write_command(0x38);//set 8 bit data transmission mode
      delayms(1);
      LCD_write_command(0x06);//open display (enable lcd display)
      delayms(1);
      LCD_write_command(0x0C);//set lcd first display address
      delayms(1);
      LCD_write_command(0x01);//clear screen
      delayms(1);
      LCD_dsp_string(1,1,"  LCD TEST   ");//在第一行第一列显示"LCD TEST"
      LCD_dsp_string(1,2,"  SUCCSEEE!  ");//在第一行第一列显示"LCD TEST"
      delayms(500);
      LCD_write_command(0x01);//clear screen
      delayms(1);
}
/****************************************************/



//ADC

#define ADCST0          P5OUT &= ~BIT4
#define ADCST1         P5OUT |= BIT4
#define ADCALE0         P5OUT &= ~BIT5
#define ADCALE1         P5OUT |= BIT5
#define ADCEOC0         P5OUT &= ~BIT6
#define ADCEOC1         P5OUT |= BIT6
#define ADCOE0          P5OUT &= ~BIT7
#define ADCOE1          P5OUT |= BIT7  
#define LED_0          P5OUT &= ~BIT3
#define LED_1          P5OUT |= BIT3
unsigned int  ADC1;
void ADC_START(void)
{
  ADCALE1;
  ADCST1;
  delayms(1);
   ADCALE0;
  ADCST0;
   delayms(1);
}

char ADC_READ()
{
  uchar data;
   data=0x00;
   delayms(1);
   ADCOE1;
  ADC_START();
   delayms(5);
  data=P4IN;
   ADCOE0;
  return data;
}

// DAC

//=============================================================================
#define SET_DIN   do{P3OUT |= BIT0;}while(0)      //串行数据输入
#define CLR_DIN   do{P3OUT &= ~(BIT0);}while(0)      //串行数据输入
#define SET_SCLK  do{P3OUT |= BIT1;}while(0)     //串行时钟输入
#define CLR_SCLK  do{P3OUT &= ~(BIT1);}while(0)     //串行时钟输入
#define SET_CS    do{P3OUT |= BIT2;}while(0)      //低电平有效
#define CLR_CS    do{P3OUT &= ~(BIT2);}while(0)      //低电平有效
//=============================================================================

/*****************************************软件延时******************************/
#define CPU_F ((double)16000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
/*******************************************************************************/

void TCL5615_DAC(unsigned int Data)
{
  unsigned char i;
  Data <<= 6;     //移除高6位,int型数据有16位,该DA是10位
  CLR_SCLK;    //在片选有效前,时钟信号要为低
  CLR_CS;        //片选有效


  for(i=0;i<12;i++)       //每次转换需要10个时钟下降沿
  {
    if(Data&0x8000)     //取最高位数据,模拟串行数据
    {
      SET_DIN;
      CLR_SCLK;
      SET_SCLK;
    }
    else
    {
      CLR_DIN;           //数据在时钟上升沿到来前准备好
      CLR_SCLK;
      SET_SCLK;
    }
    Data <<= 1;          //数据左移,为下一次取数据做准备
    CLR_SCLK;
  }

  SET_CS;                    //片选失效
delayms(1);
}

void P22_Onclick( void )
{
    KEY_OPEN_OR_STOP_times++;
    if( KEY_OPEN_OR_STOP_times > 2 )
    {
      KEY_OPEN_OR_STOP_times = 1;
    }
}





void main(void)
{

    WDTCTL=WDTPW + WDTHOLD; // 关闭看门狗
    P1DIR=0xFF;            // 设置方向
    P1SEL=0;            // 设置为普通I/O 口

    P2DIR=0x03;            // 设置方向
   // P2SEL=0;            // 设置为普通I/O 口

    P3DIR=0xFF;            // 设置方向
    //-----配合机械按键,启用内部上拉电阻-----
    P2REN |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7;                     //启用P3.5内部上下拉电阻
    P2OUT |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7;                     //将电阻设置为上拉
    //-----配置P3.5中断参数-----
    P2DIR &= ~BIT2+BIT3+BIT4+BIT5+BIT6+BIT7;                    // P3.5设为输入(可省略)
    P2IES |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7;                     // P3.5设为下降沿中断
    P2IE  |= BIT2+BIT3+BIT4+BIT5+BIT6+BIT7;                    // 允许P3.5中断


    P1OUT=0x00;



    P5DIR |= BIT7+BIT4+BIT5+BIT6+BIT3;

    delayms(200);   
    LCD_init();         //LCD1602初始化
    TCL5615_DAC( DAC_num );


    /****设置AD寄存器****/
    ADC12CTL0=ADC12ON+SHT0_2;//打开AD转换内核,参考电压3.3V
    ADC12CTL1=SHP;
    ADC12IE=0X01;//使能中断允许
    ADC12CTL0|=ENC;
    P6SEL|=0x01;//P6.0电压输入
    P6DIR = 0xFE;
    flag=0;
    ADC12CTL0|=ADC12SC;//启动ADC转换器
    _BIS_SR(LPM0_bits+ GIE);//进入低功耗睡眠模式

    while(1)
    {
      if( KEY_OPEN_OR_STOP_times == 1 )
      {
         LED_1;
        ADC1=ADC_READ();
        RefreshDis0(15-((ADC1*10)+25));
         Display();
         Display_Set();


        if(flag == 1)
         {
            ADC12CTL0|=ADC12SC;//启动ADC转换器
            flag=0;

          }
      }

       if( KEY_OPEN_OR_STOP_times == 2 )
       {
         KEY_OPEN_OR_STOP_times = 2;
         LED_0;
       }
    }  
}

/****ADC12中断服务****/
#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{   
   RefreshDis1(ADC12MEM0/8);

   flag=1;
   LPM0_EXIT;
}

/*
* 名       称:P2_IODect()
* 功       能:判断具体引发中断的IO,并调用相应IO的中断事件处理函数
* 说       明:该函数兼容所有8个IO的检测,请根据实际输入IO激活“检测代码”。
*/
void P2_IODect()
{
    unsigned int Push_Key=0;
    //-----排除输出IO的干扰后,锁定唯一被触发的中断标志位-----
    Push_Key=P2IFG&(~P2DIR);
    //-----延时一段时间,避开机械抖动区域-----
     delayms(5);                  //消抖延时
    //----判断按键状态是否与延时前一致-----
    if((P2IN&Push_Key)==0)                      //如果该次按键确实有效
    {
        //----判断具体哪个IO被按下,调用该IO的事件处理函数-----
        switch(Push_Key)
        {
               case BIT2:     P22_Onclick();      break;
               case BIT3:     if(KEY_OPEN_OR_STOP_times == 1) P23_Onclick();      break;
               case BIT4:     if(KEY_OPEN_OR_STOP_times == 1)P24_Onclick();      break;
               case BIT5:     if(KEY_OPEN_OR_STOP_times == 1)P25_Onclick();      break;
               case BIT6:     if(KEY_OPEN_OR_STOP_times == 1)P26_Onclick();      break;
               case BIT7:     if(KEY_OPEN_OR_STOP_times == 1)P27_Onclick();      break;
            default:                              break;      //任何情况下均加上default
        }
    }
}

#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
    //-----启用Port2事件检测函数-----
    P2_IODect();                                //检测通过,则会调用事件处理函数
    P2IFG=0;                                    //退出中断前必须手动清除IO口中断标志
}



全部资料51hei下载地址:
恒流源.rar (341.46 KB, 下载次数: 76)

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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