⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 绝对原创``` 才用51单片机做的一个数控电源的原程序`!
💻 C
字号:
#include "AT89X52.H"
unsigned int U_set;
unsigned int I_set;
unsigned int U_real;
unsigned int I_real;
unsigned int DATA;  //最后需要从DA输出的数  16位 ;
unsigned char select[]={0x01,0x02,0x04,0x08,0x10,0x20};//移位的控制码字~!
unsigned char displaycode[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};    //显示的码字 前10个为不带小数点,后10个带小数点  但是貌似反了  再斟酌一下

void inti()  //单片机初始化
{
     P1=0x00; //数码管片选端 全为0  因为为共阳极的
	 P0=0xff;  //码字端全为1
 //AD 初始化
   //  P2=0x00; //按键初始化
     P3_4=1;        // CS=1;
     P3_1=1;        //SCLK=1;
 // P3_0=1;        //AD_IN=1;

 //DA初始化
     P3_3=1;   //DA片选 SYNC 为高电平  
}

void delay2ms(void)         //延时2ms秒子程序,用作数码管扫描
{
  unsigned char i,j;
    for(i=20;i>0;i--)
      for(j=48;j>0;j--);
}

void delay10ms(void)         //延时10ms秒子程序,用作键盘扫描
{
  unsigned char i,j;
    for(i=20;i>0;i--)
      for(j=250;j>0;j--);
}


unsigned char keyscan()    
{
    if(P2_0==0)//键盘按下 显示低电平  key1;
      {
	    delay10ms();//延迟10ms,看键盘是否真的按下。。
	    if(P2_0==0)
		    return(1);
	  }      //key1 为"+"
	else if(P2_1==0)
      {
	    delay10ms();
	    if(P2_1==0)
		    return(2);
	  }      //key2 为"-"
    else if(P2_2==0)
      {
	    delay10ms();
	    if(P2_2==0)
		    return(3);
	  }      //key3为"set"
    else if(P2_3==0)
      {
	    delay10ms(); 
	    if(P2_3==0)
		    return(4);
	  }     //key4为 sure
    return(0);//无键盘按下时,返回0
}


void ledplay(unsigned short U_num,unsigned short I_num)  //电流用 0 电压用 1 表示。
{ 
   unsigned char i;
   unsigned char temp;
   U_num=(U_num<<6)>>6;
   I_num=(I_num<<6)>>6;
    //unsigned char select[]={0x01,0x02,0x04,0x08,0x10,0x20} //移位的控制码字~!
    //unsigned char displaycode[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x89,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};    //显示的码字 前10个为不带小数点,后10个带小数点  貌似反了  已经移到最前边去了··
   for(i=0;i<6;i++)  //这一部分的代码貌似比较劣质  先看能调成功不嘛··
   {

     switch(i)
	 { 
	    case 0:temp=U_num/100+10;break;     //去U_num 的第也百位,并加小数点
        case 1:temp=U_num/10-((U_num/100)*10);break;     //去U_num 的第二位
        case 2:temp=U_num%10; break;  //去U_num 的第三位
        case 3:temp=I_num/100+10;break;         //取I_num 的第百位,并加小数点
        case 4:temp=I_num/10-((I_num/100)*10); break;      //取I_num 的第2位
        case 5:temp=I_num%10; break;        //取I_num 的第3位 10 
        
     }
     P0=displaycode[temp];   //P0口输出对应的码字
     P1=select[i];   //选择数码管 
     delay2ms();
   }  
}




void ledplay200ms(unsigned int U_num,unsigned int I_num) 
{
      unsigned char i;
       for(i=20;i>0;i--)   //再算一下 调整一下!
          ledplay(U_num,I_num);
}


void key3process()  //set 按键功能程序
{
   // U_set=500;
    while(1)
      {
	  ledplay200ms(U_set,0);
      if((keyscan())==1)
            U_set=U_set+10;
      else if((keyscan())==2)
            U_set=U_set-10; 
     
                       //显示设置的电压,电流显示为0
      else if((keyscan())==4)	
                      break;        
       }
    ;
}






//电压输出程序 DA 转化

//sbit SCLK = P3_1 ;   // 时钟引脚 根据实际情况调整
//sbit SYNC_=P3_3 ;   // 相当于片选引脚  根据实际情况调整
//sbit Dout_bit = P3_0;   //输出数据位
//unsigned int DATA;  //最后需要从DA输出的数  16位 ;
void U_numProcess()   
{   
  //  unsigned short U_ref=500;   // 基准电压值,根据实际情况调整
   
    unsigned int Dout_mid;  //从U_num计算DATA的中间数
    Dout_mid=U_set*4;             //  Dout_mid=(unsigned long)U_set*4096/1000;    // 不确定这个算式是正确的,貌似溢出了··
    DATA=((Dout_mid<<4)>>4)|0x0001;    //算出最后输出的数   前4位为 0001 后12位为转换的数。

}

void Uout_inti()
{
    P3_3=1;   //SYNC_=1  片选为高电平(低电平为有效)
    P3_1=1;   //SCKL为高电平  
}

void delay02ms()     //还要在看一下  跟据实际情况调整  DA 的时间控制延迟函数
{
   unsigned char i,j;
    for(i=10;i>0;i--)
        for(j=10;j>0;j--)
	      {;}
}

void Vout()
{

  unsigned char i;
  unsigned int check;  //检验数。
  check=0x8000;
  U_numProcess();  //计算出最后从DA输出的数
  Uout_inti();  //进行初始化
  P3_3=0;            //SYNC=0;  打开片选
  delay02ms();
  for(i=0;i<16;i++)
  {  
    
    if((DATA&check)==check)
	 P3_0=1; //Dout_bit=1;     //检验数为1,输出
	else P3_0=0;  //Dout_bit=0;
	delay02ms();   
	delay02ms();
    P3_1=0;   //SCLK=0;   //时钟下降沿  读数据
	delay02ms();
	delay02ms();
    P3_1=1;      //SCLK=1;   //时钟上升沿
    check=(check>>1); //check 右移一位
  }                  //进行16次移位检验输出。
  
 // P3_1=1  ;  //SCLK=1
  P3_3=1 ;    // SYNC=1  关闭 完成DA转换

}


//对电压进行采样


///电压采样程序


//sbit SCLK=P3_1;
//sbit CS=P3_4;
//sbit AD_OUT=P3_5;
//sbit AD_IN=P3_0;

void ADU_inti()
{
 P3_4=1; //CS=1;
 P3_1=1; //SCLK=1;
 P3_0=1; //AD_IN=1;
}  //对AD 端口进行初始化


void U_select()
{  
   unsigned char i;
   P3_4=0;     // CS=0;
   for(i=0;i<32;i++)
   {
      delay02ms();
	  delay02ms();
      P3_1=~P3_1;  // SCLK=~SCLK; 
    }
	delay02ms();
	//完成选择
    P3_4=1;	//CS=1;
  //  P3_1=1;   //SCLK=1;
}  //第一次 AD  不进行转换 只选择是进行U 还是 I 的转换。  AD_IN=1 的时候 选择IN4 AD_IN=0的时候选择IN1 ;

void U_convert()
{ 
   unsigned char i;
   unsigned int U_check=0; 
   unsigned int temp_check=0x0800;
   
   ADU_inti();
   U_select();
  
   P3_4=0;  //CS=0;   //开启进行转换
   for(i=0;i<8;i++)   //前4个周期 空运做 不做任何工作 完成后 SCLK 处于高电平  下一个低电平 开始读取
     {
	    delay02ms();
		delay02ms();
      	P3_1=~P3_1;     	//SCLK=~SCLK;
	 }
	
   for(i=0;i<12;i++)
    {  
      delay02ms();
      P3_1=(~P3_1); //SCLK=~SCLK;   //高电平转换为低电平
	  delay02ms(); 
	  delay02ms();
	  P3_1=(~P3_1);  //低电平转化为高电平
	  if(P3_5==1)       //if(AD_OUT==1)
	    U_check=(U_check|temp_check);
	  temp_check=(temp_check>>1);
     }
   delay02ms();
   P3_4=1;     //  CS=1;   //完成转换 关闭片选,现在SCLK为高电平;
   U_real=U_check/4;             // U_real=U_check*1000/4096;  //把转换获取的值赋给U_real;
}

//对电流进行采样

//sbit SCLK=P3_1;
//sbit CS=P3_4;
//sbit AD_OUT=P3_5;
//sbit AD_IN=P3_0;

void ADI_inti()
{
  P3_4=1;     // CS=1;
  P3_1=1;     // SCLK=1;
  P3_0=0;     // AD_IN=0;
}  //对AD 端口进行初始化


void I_select()
{  
   unsigned char i;
   P3_4=0;//CS=0;
   for(i=0;i<32;i++)
   {
      delay02ms();
      P3_1=~P3_1;         // SCLK=~SCLK; 
    }
	delay02ms();
	//完成选择
	// P3_1=1;          //   SCLK=1;
    P3_4=1;          //	CS=1;
   
}  //第一次 AD  不进行转换 只选择是进行U 还是 I 的转换。  AD_IN=1 的时候 选择IN4 AD_IN=0的时候选择IN1 ;

void I_convert()
{  
   unsigned char i;
   unsigned int I_check=0;
   unsigned int temp_check=0x0800;
   ADI_inti();
   I_select();
   
   P3_4=0;        //CS=0;  //开启进行转换
   for(i=0;i<8;i++) //前4个周期 空运做 不做任何工作 完成后 SCLK 处于高电平  下一个低电平 开始读取
     {
	    delay02ms();
		delay02ms();
	    P3_1=~P3_1; //	SCLK=~SCLK;
	 }
	
   for(i=0;i<12;i++)
   {
      delay02ms();
      P3_1=(~P3_1); 	// SCLK=~SCLK;  //高电平转换为低电平
      delay02ms();
      delay02ms();  
      P3_1=~P3_1;	 // SCLK=~SCLK;//低电平转化为高电平
	 if(P3_5==1)  //if(AD_OUT==1)
	    I_check=(I_check|temp_check);
	  temp_check=temp_check>>1;

    } 
   delay02ms();
   P3_4=1;      // CS=1;  //完成转换 关闭片选,现在SCLK为高电平;
   I_real=I_check/4;  //把转换获取的值赋给I_real; 需要根据实际情况更改;
}

//主函数


//unsigned short U_set;
//unsigned short I_set;
//unsigned short U_real;
//unsigned short I_real;
void main()
{   
    unsigned temp;
    U_set=500;
//	U_real=300;  //为了测试数据
   // I_real=200; //为了测试数据
    inti(); //对单片机进行初始化

    while(1)
	{
	    ledplay200ms(U_set,1); //
		temp=keyscan();
	    if(temp==3)break;
	}    //等待初始化按键
 	 key3process();



	Vout();      //输出SET电压值
	U_convert();
	I_convert();
	ledplay200ms(U_real,I_real);
	while(1)
	{
	   if((keyscan())==1) 
	     {
		    U_set=U_set+10;
            Vout();
	     	U_convert();
	     	I_convert();
	//	U_real=U_real+10;  // 测试用
		 }
	 else  if((keyscan())==2) 
	     {
             U_set=U_set-10;
   	    	 Vout();
             U_convert();
             I_convert();
	   // 	U_real=U_real-10;  //测试用
     	  }
     ledplay200ms(U_real,I_real);
       
	}
	
 //最外层循环
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -