51单片机验证牛顿第二定律

51单片机验证牛顿第二定律

  1. 运用定时器
  2. 外部中断
  3. lcd1602的 显示
  4. 数据的处理
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
#define s 30
sbit  led = P2^4;
sbit   key1 = P1^7;
sbit  key2 = P3^2;
sbit  key3 = P3^0;

int count =0;
int str[3];
int m = 0;
int m1 = 0;
int flag = 0;
int flag1 = 0;
int temp = 0;
int temp1 = 0;

int t0;
int t2;
int t1;
int a ;
int v0;
int v1;
int v2;

int pp =0;
int pp1 = 0;

void data_deal();
/* 初始化定义引脚 */
sbit rs=P2^0;
sbit rw=P2^1;
sbit lcden=P2^2;

void Delay(uint num)                  //延时函数
{
  while( --num );
}

void delay1(int ms)
{
unsigned char n;
   while(ms--)
   {
     for(n = 0; n<250; n++)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
   }
}

/******** 1602的设置 ********/
void write_com(uchar com)              //写指令
{
    // while(lcd_busy());
    rs = 0;
// LCD_RW = 0;
    lcden = 0;
    _nop_();
    _nop_(); 
    P0 = com;
    delayNOP();
    lcden = 1;
    delayNOP();
    lcden= 0; 
    Delay(10);
}

void write_date(uchar date)            //写数据
{
    // while(lcd_busy());
    rs = 1;
// LCD_RW = 0;
    lcden= 0;
    P0 = date;
    delayNOP();
    lcden = 1;
    delayNOP();
    lcden= 0; 
    Delay(10);

}

void init1()
{
   TMOD=0x10;                   //模式设置,00000001,可见采用的是定时器0,工作与模式1(M1=0,M0=1)。

TH1=(65536-46080)/256;         //由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
TL1=(65536-46080)%256;        //46080的来历,为50000*11.0592/12
    ET1=1;                        //开定时器0中断
    EA=1;                         //开总中断
    EX1 = 1;
    IT1 = 1;
}

/**** 相关的初始化 ******/
void init()
{
   TMOD=0x01;                   //模式设置,00000001,可见采用的是定时器0,工作与模式1(M1=0,M0=1)。

    TH0=(65536-46080)/256;         //由于晶振为11.0592,故所记次数应为46080,计时器每隔50000微秒发起一次中断。
    TL0=(65536-46080)%256;        //46080的来历,为50000*11.0592/12
    ET0=1;                        //开定时器0中断
    EA=1;                         //开总中断
    EX0 = 1;
    IT0 = 1;
}

void init_1602()                     //1602的初始化
{
   rw = 0;
    delay1(15);   
    write_com(0x01);               //清除LCD的显示内容 
    write_com(0x38);               //16*2显示,5*7点阵,8位数据
    delay1(5);
    write_com(0x38);
    delay1(5);
    write_com(0x38);
    delay1(5);

    write_com(0x0c);                //开显示,不显示光标 
    delay1(5);

    write_com(0x01);                //清除LCD的显示内容
    delay1(5);
}
/*** 显示处理 ****/ 
void display_xy(uchar x,uchar y)
{ 
     if(y==0x01)
     {
          x = x + 0x40 + 0x80; 
      }
     else
     {
     x = x+0x80;                    //数据指针设置 80H+地址码 (0-27H,40H-67H)
     }
     write_com(x);
}

void Disp1Char(uchar x,uchar y,uchar f_data)
{
    display_xy(x,y);
    write_date(f_data);                ////输出数据
}

void Disp_float(uint f_data) 
{ 

    unsigned char lcd_table[3];

    lcd_table[0]= f_data/100;          //第一位
    lcd_table[1]= f_data%100/10;       //第二位
    lcd_table[2]=f_data%100%10;

    Disp1Char(3,0,(lcd_table[0]+0x30)); //显示整数部分的十位数 0x30的原因CGROM和CGRAM与字符的对应关系

    Disp1Char(4,0,(0x2e));            //显示小数点"." 小数点对应00101110
    Disp1Char(5,0,(lcd_table[1]+0x30));
    Disp1Char(6,0,(lcd_table[2]+0x30)); //显示小数部分的个位
   // Disp1Char(7,0,(lcd_table[3]+0x30));

   //Disp1Char(8,0,(lcd_table[2]+0x30)); //显示小数部分的十分位 
                                  //加上0x30以便直接得到相应的ASCII码去显示
}

void Disp_float1(uint f_data) 
{ 

    unsigned char lcd_table[3];

    lcd_table[0]= f_data/100;           //第一位
    lcd_table[1]= f_data%100/10;        //第二位
    lcd_table[2]=f_data%100%10;

    Disp1Char(11,0,(lcd_table[0]+0x30));  //显示整数部分的十位数 0x30的原因CGROM和CGRAM与字符的对应关系

    Disp1Char(12,0,(0x2e));             //显示小数点"." 小数点对应00101110
    Disp1Char(13,0,(lcd_table[1]+0x30));
    Disp1Char(14,0,(lcd_table[2]+0x30));  //显示小数部分的个位

}
void Disp_float2(uint f_data) 
{ 

    unsigned char lcd_table[3];

    lcd_table[0]= f_data/100;            //第一位
    lcd_table[1]= f_data%100/10;         //第二位
    lcd_table[2]=f_data%100%10;

    Disp1Char(3,1,(lcd_table[0]+0x30));   //显示整数部分的十位数 0x30的原因CGROM和CGRAM与字符的对应关系

    Disp1Char(4,1,(0x2e));              //显示小数点"." 小数点对应00101110
    Disp1Char(5,1,(lcd_table[1]+0x30));
    Disp1Char(6,1,(lcd_table[2]+0x30));   //显示小数部分的个位

}
 void Disp_float3(uint f_data) 
{ 

    unsigned char lcd_table[3];

    lcd_table[0]= f_data/100;           //第一位
    lcd_table[1]= f_data%100/10;        //第二位
    lcd_table[2]=f_data%100%10;

    Disp1Char(11,1,(lcd_table[0]+0x30)); //显示整数部分的十位数 0x30的原因CGROM和CGRAM与字符的对应关系

    Disp1Char(12,1,(0x2e));           //显示小数点"." 小数点对应00101110
    Disp1Char(13,1,(lcd_table[1]+0x30));
    Disp1Char(14,1,(lcd_table[2]+0x30)); //显示小数部分的个位

}
void  start_inter()
{     
    uint temp;

  while(1 )
 {

      if(pp==20)
     {  

        pp=0;
        m++;

        if(m==600)
        {
           m=0;                     //若到了600s,则归零
        }

}

     temp = m *100;
    // Disp_float(temp);
    if(flag == 1  && count == 1)
{

    TR0 = 0;                        //关闭定时器
    flag = 0;
    t0 = temp;

    break;
}
    if(flag == 1 && count == 2){
    TR0 = 0;
    flag = 0;
    t2 = temp;
    data_deal();
    break;
    }
}

}

  void data_deal()
{   //Disp_float1(t0);
   // Disp_float2(t2);

   //Disp_float(t0);
t1 = t2 -t0;
    a = (2 * s*(2*t0 – t2))  /(t0*t2*(t2- t0));
    v0 = (s -(a/2)*t0*t0)/t0;
    v1 = v0 + a *t0;
    v2 = v0 + a* t2;
    Disp_float(v0);
    Disp_float1(v1);
    Disp_float2(v2);
    Disp_float3(a);
}

void time0() interrupt  1
{
    TH0=(65536-46080)/256;
    TL0=(65536-46080)%256;
    pp++;

}

 void interrupt0() interrupt 0
{
                                     //开外部中断0

  if ( key2 == 0)                        //触发门外光控回路之前,没有触发门内的
{   
count++;    
     flag = 1;                           //启动显示标志

}

}

int main()
{

// int t1;
// int t2;
     init_1602();
    // init();
    Disp1Char(0,0,'v');
    Disp1Char(1,0,'0');                   //将第一个字符a(加速度)写在向右偏移1个字符处,为后面的由右向左划入做准备。
    Disp1Char(2,0,'=');
// Delay(20);

    Disp1Char(8,0,'v');
    Disp1Char(9,0,'1');             //将第二个字符v(瞬时速度)写在向右偏移1个字符处,为后面的由右向左划入做准备。
    Disp1Char(10,0,'=');
// Delay(20); 

    Disp1Char(0,1,'v');
    Disp1Char(1,1,'2');             //将第三个字符t(时间)写在向右偏移1个字符处,为后面的由右向左划入做准备。
    Disp1Char(2,1,'=');

    Disp1Char(8,1,'a');
    Disp1Char(9,1,'=');
// Delay(20);

//EA = 1; //开启串行口中断允许,开启外部中断0、外部中断1

                                //设置外部中断0、1为下降沿触发
while(1) 
{   

if(key1== 0  )

{
        EA = 1;
        TR0 = 1;
        init();
        start_inter();

    if(flag  == 1)
{
        EX0 = 0; 
        EA=0;  
    }

    }

    // Disp_float3(str[0]);

    //Disp_float2(str[1]);
    ;
   }
   return 0;
}

你可能感兴趣的:(51单片机)