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

📄 shijie.c

📁 智能水分仪的程序
💻 C
字号:

// Target: C8051F005 
// Tool chain: KEIL C51
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "c:\SiLabs\MCU\IDEfiles\C51\Inc\c8051F000.h"                 // SFR declarations
#include "stdio.h"
#include "math.h"
#include "c:\SiLabs\MCU\IDEfiles\C51\Inc\mydef.h"
#include "c:\SiLabs\MCU\IDEfiles\C51\Inc\string.h"

// Global CONSTANTS
//-----------------------------------------------------------------------------
///////////
//sfr CLKSEL   = 0x97;
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
unsigned  int  xdata  save_c[250];
int  xdata   vul;
float vul0;
unsigned char  xdata  current_line,current_row;
unsigned char key,key_h,kpush;
unsigned int key_l;unsigned char key_ddz;
static char  high_byte;     //定义D/A的存储变量
static char low_byte;
static int adc_high;        //定义A/D的存储变量
static  int adc_low;
static int  adc_result;
    
float watercontent;
sbit key1=P1^0; //按键0-5
sbit key2=P1^1;
sbit key3=P1^2;
float watercontent;
 
//-----------------------------------------------------------------------------
// 程序部分主体
//-----------------------------------------------------------------------------
//函数部分定义
void lw(unsigned char x,unsigned char y,unsigned char dd) ;
void write_assic(unsigned char value);
void write_char(unsigned char show_char);
void print_string(const  char *  buf,unsigned char slength);
void write_chinese(unsigned char show_chinese);
void clear_row(unsigned char row);
void  show();
//delay for  some time
//delay程序,大约为1000个时钟周期
void my_delay(unsigned int    time) //1000 codebyte 
{ 
  unsigned int j,i;
  for(j=0;j<time;j++)
  {
    for(i=0;i<73;i++)
       j=j;
  }
}
void delay(int  num)
{  while(num--);}

//端口、晶振初始化//
//----------------------------------------------------------------------------------
void SYSCLK_Init (void)
{
  WDTCN=0x07; // Watchdog Timer Control Register
    WDTCN = 0xDE;   // Disable WDT
    WDTCN = 0xAD;
	XBR0 = 0x00;	// XBAR0: Initial Reset Value
	XBR1 = 0x00;	// XBAR1: Initial Reset Value
	XBR2 = 0x40;	// XBAR2: Initial Reset Value
	PRT0CF = 0x00; // Output configuration for P0 
	PRT1CF = 0x00; // Output configuration for P1 
	PRT2CF = 0xff; // Output configuration for P2 
	PRT3CF = 0x00; // Output configuration for P3 
    OSCICN=0x94;     //USE  internal system clock        
	OSCXCN=0x00;
	CLKSEL=0x00;
} 
//D/A转换
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
	void DAC_0_OUT(unsigned int d_value)
{
                       // enable adc  internal  VREF,
   DAC0CN=0x80;
   high_byte=d_value/256;
   low_byte=d_value-high_byte*256;
   DAC0L=low_byte;
   DAC0H=high_byte;
}
//A/D转换
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
int GET_ADC0 ()
{    
 //	REF0CN=0x03;      //采用内部电压基准
      AMX0SL=0x00;
	  AMX0CF=0x00;  
	  ADC0CF=0x00;        //gain=1
	  ADC0CN=0xc0;
      ADCINT=0;
      ADBUSY=1; 
   while(ADCINT==0);
    
   adc_high=ADC0H;
   adc_low=ADC0L;
   adc_result=adc_high*256+adc_low;
   return adc_result;
}
//A/D转换结果应送水分转换函数
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
void average()
{  unsigned char  i, j;
   int xdata adc_result[200];
   long   xdata sum;
   unsigned char  xdata min;
   unsigned char xdata max;
   
      for (i=0;i<200;i++)  
      {  
       adc_result[i]=GET_ADC0();    //0通道的采样
	   }
 //first find the min of the array
   min=0;
   max=0;
     for (i=0;i<200;i++)
      {
      if (adc_result[min]<adc_result[i])
         min=i;
       }
 //second find the max of the array
     for(i=0;i<200;i++)
      {
      if(adc_result[max]>adc_result[i+1])
      max=i;	 
       } 
   adc_result[min]=0;
   adc_result[max]=0;
   sum=0;
     for(j=0;j<200;j++)
     {sum+=adc_result[j];
      }
   vul=sum/198;
   vul0=2.4*vul/4096;
  
	//end while
}
//-----------------------------------------------
//-----------------------------------------------
void content()
{
    watercontent=66.3*vul0*vul0*vul0-229*vul0*vul0+275*vul0-110;//.162e4*x^3-426.*x^2+74.6*x+.142
}
//存储测得的水分含量的数据-52.4*vul*vul*vul+166*vul*vul-154*vul+46.7,8.841*vul0*vul0*vul0-426*vul0*vul0+74.6*vul0+0.142
//---------------66.3*x^3-229.*x^2+275.*x-110------------------------------
//write a byte to led x line and y row
/*写一个数据到液晶的显示屏上*/
void lw(unsigned char x,unsigned char y,unsigned char dd) 
{
   unsigned char  show_char;
   show_char=dd;
  		P2=0;
		if (x<64) 
		{
			cs1=cs2=0;
			di=rw=0;cs1=1;cs2=0;P2=0xb8|y;e=1;delay(2);e=0;delay(2);// set page;
			di=rw=0;cs1=1;cs2=0;P2=0x40|x;e=1;delay(2);e=0;delay(2); //set y address;
			di=1;rw=0;cs1=1;cs2=0;
			P2=show_char;e=1;delay(2);e=0;delay(2);	
			/*cs1=cs2=0;*/
		}
		else 
		{
			cs1=cs2=0;x=x-64;
			di=rw=0;cs1=0;cs2=1;P2=0xb8|y;e=1;delay(2);e=0;delay(2);			
			di=rw=0;cs1=0;cs2=1;P2=0x40|x;e=1;delay(2);e=0;delay(2);
			di=1;rw=0;cs1=0;cs2=1;
			P2=show_char;e=1;delay(2);e=0;delay(2);
		}
		P2=0xff;
		cs1=cs2=0;
}
/*液晶的初始化*/
//---------------------------------------------
//---------------------------------------------
void lcd_init(void) 
{
	unsigned char  x,y;
	e=di=rw=0;
	cs1=cs2=1;
	cs1=0;cs2=1;
	di=rw=0;P2=0x3f;e=1;delay(2);e=0;delay(2);
	cs1=0;cs2=1;
	di=rw=0;P2=0xc0;e=1;delay(2);e=0;delay(2);
	cs1=cs2=0;
/////////////////////////////////////////////
	cs1=1;cs2=0;
	di=rw=0;P2=0x3f;e=1;delay(2);e=0;delay(2);
	cs1=1;cs2=0;
	di=rw=0;P2=0xc0;e=1;delay(2);e=0;delay(2);
	cs1=cs2=0;	
	for (y=0;y<8;y++) {
		for (x=0;x<128;x++) 
		   lw(x,y,0x00); 
 	}
	current_line=0;
	current_row =0;
}
//设置显示的位置*/
//---------------------------------------------
//---------------------------------------------
void set_showpos(unsigned char  line,unsigned char  row)
{
  current_line=line*8;
  current_row=row*2;  
}
/* this function is clear a row of lcd */
/* 128*64 line表示列数(0 - 16) row 表示行数 (0 - 3 )*/
//仪器显示的开始 
//---------------------------------------------
//---------------------------------------------
void show_screen()
{
    unsigned int s;
	unsigned char x,y;
  	for (y=0;y<8;y++)
	{
		for (x=0;x<128;x++) 
		   {
		    lw(x,y,screen[s]);
		    s++;
			}
 	}
my_delay(5000);
lcd_init();			
}
/*显示的换行*/
//---------------------------------------------
void move_nextpos()
{
    current_line=current_line+8;
    if(current_line>116)
     {	   
      current_line=0;
      current_row=current_row+2;
         if(current_row>8)
           current_row=0;
     }
}
/*清屏*/
//---------------------------------------------
void clear_row(unsigned char row)
{ 
  unsigned char ii;
  set_showpos(0,row);
  for (ii=0;ii<16;ii++)
    write_assic(' ');
  set_showpos(0,row);
}
/* write a assic to lcd                  */
/* current xx,current yy is write  assic postion*/
void write_assic(unsigned char value)
{
   unsigned char  i,j,xx,yy;
   unsigned  int dd,num;	
   xx=current_line;yy=current_row;
  for(i=0;i<2;i++)
  {
	for(j=0;j<8;j++)
	{
	  dd=value*16+i*8+j;
	  num=number_dot[dd];
 	  lw(xx+j,yy+i,num);
   	}	
  }
  move_nextpos();
}
/* 打印数字到显示器*/
/* 格式是最少显示2位,3,4位为零时不显示*/
/* 有负号也要打印出来*/
void print_number(int  shownum)
{
   unsigned char byte4,byte3,byte2,byte1;
   if(shownum<0)
   {
    write_char('-');
    shownum=-shownum;
   }
   byte4=shownum/1000;
   byte3=(unsigned char)((shownum-byte4*1000)/100);//百位存disp
   byte2=(unsigned char)((shownum-byte4*1000-byte3*100)/10);//十位存disp
   byte1=(unsigned char)((shownum-byte4*1000-byte3*100-byte2*10)/1);//个位存disp
   if(byte4!=0)
   write_assic(byte4+16);
   if(byte3!=0 || byte4!=0)
   write_assic(byte3+16);
   write_assic(byte2+16);
   write_assic(byte1+16);
}
//  打印一个字符串到液晶显示屏上了       //
//   注意字符串为常量,并且要告诉他的长度//
//////////////////////////////////////////
void print_string( const char* buf,unsigned char slength)
{
       unsigned char ii;
	   for(ii=0;ii<slength;ii++)
	   write_char(*buf++);
}
//打印一个浮点 ,格式 :4 位整数,3位浮点
void print_float(float vfloat)
{
   unsigned char byte4,byte3,byte2,byte1;
   unsigned int  shownum;
   float  my_float;
    my_float=vfloat;
   if(my_float<0)
    {
    write_char('-');
    my_float=-vfloat;
    }
   shownum=my_float;
   byte4=shownum/1000;
   byte3=(unsigned char)((shownum-byte4*1000)/100);//百位存disp
   byte2=(unsigned char)((shownum-byte4*1000-byte3*100)/10);//十位存disp
   byte1=(unsigned char)((shownum-byte4*1000-byte3*100-byte2*10)/1);//个位存disp
   if(byte4!=0)
   write_assic(byte4+16);
   if(byte3!=0 || byte4!=0)
   write_assic(byte3+16);
   if(byte3!=0 || byte4!=0||byte2!=0)
   write_assic(byte2+16);
   write_assic(byte1+16);
/////////////显示小数部分,显示三位
   write_char('.');
   shownum=(my_float-shownum)*1000;
   byte3=shownum/100;                            // 百位
   byte2=(unsigned char)((shownum-byte3*100)/10);//十位存disp
   byte1=(unsigned char)((shownum-byte3*100-byte2*10)/1);//个位存disp
   write_assic(byte3+16);
   write_assic(byte2+16);
 write_assic(byte1+16);
}
/* 打印一个字符到显示*/
void write_char(unsigned char  show_char)
{
    unsigned char index_char;
    index_char=show_char-32;
    write_assic(index_char);
}
/*显示一个汉字*/
void write_chinese(unsigned char show_chinese)
{
   unsigned char  i,j,xx,yy;
   unsigned  int dd,num;	
   xx=current_line;yy=current_row;
   for(i=0;i<2;i++)
   {
	 for(j=0;j<16;j++)
	 {
	  dd=show_chinese*32+i*16+j;
         num=hz_dot[dd];
 	  lw(xx+j,yy+i,num);
   	 }	
   }
      move_nextpos();
	  move_nextpos();
}
///////////////////////////////////////////////////////////
//   键盘程序
///////////////////////////////////////////////////////////

void int_t0(void) interrupt 1 //interrupt n 中断编号为1时中断源为定时器/计数器0溢出中断
{
//unsigned char dd,i;
 TL0=TL0+30;TH0=0xfb; //计数器赋初值800
 /* 按键判别 */
 if ((P1&0x7)==0x7) 
   {
     if ((key_l>30)&&(key_l<800)&&(key_h>30))   //释放按键,如果之前按键时间少于1秒,读入键值
      { 
      key=kpush;
      }
     if ((++key_h)>200) 
      key_h=200;
      key_l=0;
      if (key>=0x80) 
      key=0;       //如果之前的按键为长按1秒,清除键值
   } 
 else 
   {
     kpush=P1&0x7;
     key_l++;
      if ((key_l>800)&&(key_h>30))     //如果按键超过1秒,键值加0x80标志长按键
      { 
       key=kpush|0x80;
       key_h=0;
       key_l=0;
       }
   }
}
void dealkey()//要改DAC_0_OUT(810)
{
   
   switch(key)
	{    case 6:			
			{
   DAC_0_OUT(650);//纸张的水分含量
   write_chinese(8);
   write_chinese(9);
   my_delay(500);
        
				break;
		  	 }
          case 5:
			{ 
	DAC_0_OUT(570);//地板的水分含量
	write_chinese(10);
    write_chinese(11);
    my_delay(500);
		
				break;
		     }  
   		  case 3:
			{ 
	DAC_0_OUT(1000);//沙子的水分含量
	write_chinese(12);
    write_chinese(13);
    my_delay(500);
	            break;

		     }  
	 }
   
}
//显示水分含量
/*---------------------------------------------*/
void  show()
 { 
  set_showpos(0,1);
  write_chinese(4);write_chinese(5);write_chinese(6);write_chinese(7);//水份含量 
  print_string(":",1);
  
   set_showpos(0,2);
   clear_row(2);
   set_showpos(5,2);
   print_float(watercontent);
  
  set_showpos(14,3); 
  print_string("%",1);
  my_delay(500); 
  }
/* this is main function */
/*---------------------------------------------*/
/*---------------------------------------------*/
void main (void) 
{
  WDTCN = 0xde;                       // disable watchdog timer
  WDTCN = 0xad;
  REF0CN=0x03; 
  SYSCLK_Init();
  lcd_init();
  show_screen();
TMOD=0x1;//定义工作模式1:TL+TH0共十六位全参与计数

TR0=1;//启动计数器

ET0=1;//允许定时器/计数器0溢出中断 ET1=1;//允许定时器/计数器1溢出中断

EA=1;//开中断
 while (1) 
   { 
 while(!key)//无键按下显示等待
      {
        set_showpos(0,0);
		write_chinese(17);
        write_chinese(18);
        write_chinese(19);
		my_delay(300);
		clear_row(0);
  
	  }
        dealkey();
 
   		average();
		content(); 
		show();
  
   }
}  

⌨️ 快捷键说明

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