📄 shijie.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 + -