c51写的测转速源程序

发布者:温柔阳光最新更新时间:2016-09-08 来源: eefocus关键字:c51  测转速 手机看文章 扫描二维码
随时随地手机看文章
以前写的c51单片机测转速源程序,比较久了,当时电路板有数码显示,代码不是最优化的,不过朋友可以看看其中的测速代码,当时费了点心思写的,24c02的读写代码,贴出来给朋友看看,写的很差劲,高手就不要见笑了。

#include
#include
#include 

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

sbit key0=P3^0;//按键0
sbit key1=P3^1;//按键1
sbit key2=P3^3;//按键2
sbit key3=P3^4;//按键3
sbit led0=P1^0;//数码管0
sbit led1=P1^1;//数码管1
sbit led2=P1^2;//数码管2
sbit led3=P1^3;//数码管3
sbit scl=P1^6;//24c02scl端
sbit sda=P1^5;//24c02scd端
sbit out=P1^7;//输出端
sbit in=P3^2;//输入

code uchar  ascled[12]={
0x3f,0x06,0x5b,0x4f,0x66, //0,1,2,3,4
0x6d,0x7d,0x07,0x7f,0x6f, //5,6,7,8,9
0x71,0x00};               //F,''

/*****************函数列表**********************/
uchar x24c02_read(uchar addr);  //从24c02的地址addr中读取一个字节数据
void x24c02_write(uchar addr,uchar info);  //向24c02的addr地址中写入一字节数据info
void x24c02_init();   //24c02初始化子程序
void delay(uchar x);//延时子程序ms
void flash();//24c02延时子程序nop
void start();//24c02ic开始
void stop();//24c02ic停止
void ack();//24c02ic应答
void nack();//24c02ic不应答
void writex(uchar j);//24c02ic写1byte数据
void dsp();//显示子程序
void delay(uchar i);//us延时
void delay1(uchar i);//us延时
uchar readx();//24c02ic读1byte数据
/****************全局变量定义*******************/
uchar ktemp;
uchar disp[4];

uint count;//预设报警值
uint zs;//转速值
uint time0;//
uint time1;//记时器
bit  begin1;//T1开始启动标志
uchar  ltj=1;//高低速
uint js;//脉冲计数器
ulong t0;
ulong t1;

bit key_set;//设置标志
uchar disp_i[4];//显示闪动标志
uint disp_c;//闪动显示计数器//借用time0
uint disp_j;//闪动显示定时//借用time1
bit ss=0;//闪动标志
uint bj;//报警输出信号定时
bit en_bj=0;//允许报警标志
bit bjing=0;//报警中

//m:菜单级数 mi:参数标号 bh:检测保护时间1-10
uchar bh=0;
uchar m=0,mi=0;//借用zs,js
uchar bhtm=0;//保护检测
//bit cmi=0;//参数设置改变标志//借用bjing
/**********************************************/

void int_ex0() interrupt 0 using 0
{
/*外部中断0*/
delay1(20);
if(key_set==0){///0  非设置状态
if(in==0){
  if(ltj==1)
    {
  js++;
      EA=0;
      TR0=0;
      TL0=0xaf; //50ms
      TH0=0x3c;      /*计数初值重装*/
      if(begin1==0)
        { //开始记数
      begin1=1;
      js=0;
      TR1=0;
      TL1=0xaf; //50ms
          TH1=0x3c;      /*计数初值重装*/ 
          TR1=1;           /*启动T1*/ 
    }
         /*启动T0*/ 
      TR0=1; 
      time0=0;
      EA=1;
}
  else
    {
  if(begin1==0)
    {
  begin1=1;
  EA=0;
          TR0=0;
  zs=0;
          /*启动T0*/ 
          TL0=0xaf; //50ms
          TH0=0x3c;      /*计数初值重装*/
          TR0=1; 
          time0=0;
          EA=1;
}
  else
    {
 EA=0;
         TR0=0;
 begin1=0;
 if(time0==0)
   {
     zs=0;
   }
 else
   {//计算转速
     t0=(time0*50000+(TH0*256+TL0)-0x3caf);
 if(t0>0){zs=60000000/t0;}
   }
 if(zs    { 
     if(en_bj==1)
       {
             out=1;
 bjing=1;//报警
   }
   }
         disp[3]=(zs%10000)/1000;//显示转速
         disp[2]=(zs%1000)/100;
         disp[1]=(zs%100)/10;
         disp[0]=zs%10;
 TL0=0xaf; //50ms
         TH0=0x3c;      /*计数初值重装*/
         TR0=1; 
         time0=0;
         EA=1;
   }
}
}
//
}///0
}
void timer0(void)interrupt 1 using 0//记时定时中断
{uchar t;
//////
if(key_set==0){///0  非设置状态
time0++;
TL0=0xaf; //50ms
TH0=0x3c;      /*计数初值重装*/ 
TR0=1;
/*启动T1*/ 
t=time0%20;
if(t==0){en_bj=0;}
if(time0>1200)//超时
  {
    time0=0;
    disp[3]=0;
disp[2]=0;
disp[1]=0;
disp[0]=0;
zs=0;
     if(en_bj==1)
       {
             out=1;
 bjing=1;//报警
   }
  }
}///0
}
void timer1(void)interrupt 3 using 0//1s记时定时中断
{
/*T1中断服务程序入口*/ 
//////
if(key_set==0){///0  非设置状态
time1++;
if(time1==20)//1s
  { EA=0;
TR1=0;
       //计算转速
   ///////////////////
   t0=time0*50000+(TH0*256+TL0)-0x3caf;
 t1=1000000-t0;
 t0=60*js*t0;
 zs=60*js+t0/t1;
 if(zs>6000){zs=0;}
 if(zs    { 
     if(en_bj==1)
       {
     if(bhtm>=bh)
       {
             out=1;
 bjing=1;//报警
       }
 bhtm++;
   }
   }
 else
   {
     bhtm=0;
   }
 if(zs==0)
   { ///////
     ///////
     disp[3]=0;
     disp[2]=0;
     disp[1]=0;
     disp[0]=0;
   }
 else
   {
             disp[3]=zs/1000;//显示转速
             disp[2]=(zs%1000)/100;
             disp[1]=(zs%100)/10;
             disp[0]=zs%10;
   }
   begin1=0;
   js=0;
   time0=0;
   time1=0;
   en_bj=0;//非保护状态
  }
//////
TL1=0xaf; //50ms
TH1=0x3c;      /*计数初值重装*/ 
TR1=1;           /*启动T1*/ 
EA=1;
}///0
}
void delay(uchar i)
{ uchar j;
  for(j=0;j<=i;j++);
}

void delay1(uchar i)
{ uchar j;
  for(j=0;j<=i;j++);
}

void flash()
{
_nop_();
_nop_();
_nop_();
//_nop_();
//_nop_();
}
void x24c02_init()
{
   scl=1;
   flash();
   sda=1;
   flash();
}
void start()
{
    sda=1;
flash();
scl=1;
flash();
sda=0;
flash();
scl=0;
flash();
}
void stop()
{
    sda=0;
flash();
scl=1;
flash();
sda=1;
flash();
}
void ack()
{
   sda=0;
   flash();
   scl=1;
   flash();
   scl=0;
   flash();
}
void nack()
{
   sda=1;
   flash();
   scl=1;
   flash();
   scl=0;
   flash();
}
void writex(uchar j)
{
   uchar i,temp;
   temp=j;
   for (i=0;i<8;i++){
      temp=temp<<1;
  scl=0;
      flash();
  sda=CY;
  flash();
  scl=1;
      flash();
   }
   scl=0;
   flash();
   sda=1;
   flash();
}
uchar readx()
{
   uchar i,j,k=0;
   scl=0;
   flash();
   sda=1;
   for (i=0;i<8;i++){
      flash();
  scl=1;
  flash();
      if (sda==1) j=1;
      else j=0;
      k=(k<<1)│j;
  scl=0;
  flash();
   }
   return(k);
}

uchar x24c02_read(uchar addr)
{
   uchar i;
   start();
   writex(0xa0);
   ack();
   writex(addr);
   ack();
   start();
   writex(0xa1);
   ack();
   i=readx();
   nack(); 
   stop();
   delay(10);
   return(i);
}
void x24c02_write(uchar addr,uchar info)
{
   //EA=0; //中断总禁止
   start();
   writex(0xa0);
   ack();
   writex(addr);
   ack();
   writex(info);
   ack();
   stop();
   //EA=1;//中断开//设置状态禁止所有外部中断
}
void getdate(void)
{uchar da5,da4,da3,da2,da1,da0;
x24c02_init();
da0=(x24c02_read(0x00)%10);
da1=(x24c02_read(0x01)%10);
da2=(x24c02_read(0x02)%10);
da3=(x24c02_read(0x03)%10);
da4=(x24c02_read(0x04)%10);
da5=(x24c02_read(0x05)%10);
ltj=(x24c02_read(0x06)%10);
count=da3*1000+da2*100+da1*10+da0;
bh=da5*10+da4;
if(bh>99){bh=0;}
if(count>6000){count=6000;}
if(ltj>1){ltj=1;}

}
void savedate(void)
{uchar da5,da4,da3,da2,da1,da0;
da5=bh/10;
da4=bh%10;
da3=count/1000;
da2=(count%1000)/100;
da1=(count%100)/10;
da0=count%10;
dsp();
x24c02_init();
x24c02_write(0x00,da0);
x24c02_write(0x00,da0);
dsp();
x24c02_write(0x01,da1);
x24c02_write(0x01,da1);
dsp();
x24c02_write(0x02,da2);
x24c02_write(0x02,da2);
dsp();
x24c02_write(0x03,da3);
x24c02_write(0x03,da3);
dsp();
x24c02_write(0x04,da4);
x24c02_write(0x04,da4);
dsp();
x24c02_write(0x05,da5);
x24c02_write(0x05,da5);
dsp();
x24c02_write(0x06,ltj);
x24c02_write(0x06,ltj);
dsp();
}
//动态显示
void dsp(void)
{
P2=ascled[disp[0]];led0=0;delay(50);led0=1;//led0=0显示,=1不显示
P2=ascled[disp[1]];led1=0;delay(50);led1=1;
P2=ascled[disp[2]];led2=0;delay(50);led2=1;
P2=ascled[disp[3]];led3=0;delay(50);led3=1;
}

//闪烁动态显示有效
void en_dsp(void)
{disp_j=0;
disp_i[0]=0x0;//显示闪动标志 0显示
disp_i[1]=0x0;
disp_i[2]=0x0;
disp_i[3]=0x0;
}
//闪烁动态显示
void dsp_flash(void)
{
  disp_j++;
  if(disp_j>240)
    {disp_j=0;
 disp_i[disp_c]=!(disp_i[disp_c]&0x01);
}
P2=ascled[disp[0]];led0=disp_i[0];delay(50);led0=1;//led0=0显示,=1不显示
P2=ascled[disp[1]];led1=disp_i[1];delay(50);led1=1;
P2=ascled[disp[2]];led2=disp_i[2];delay(50);led2=1;
P2=ascled[disp[3]];led3=disp_i[3];delay(50);led3=1;
}

void display(void)
{
  //设定状态时如果有键按下就不闪烁
  if((ss==0)││(ktemp!=0x1b))
    {
      dsp();
}
  else
    {
  dsp_flash();
}
}

void kbscan(void)//键盘扫描
{ uchar temp,i;//0
  temp=P3;
  ktemp=temp&0x1b;//检查key0,key1,key2,key3  00011011
  if (ktemp!=0x1b)
    {//1
  for(i=0;i<250;i++){display();}
  temp=P3;
  if(ktemp==(temp&ktemp))
    {//2
          //keyval=ktemp;//记录键值
          if(key_set==1)
    {//3
    switch(ktemp){
   case 0x1a://key0
         {
  /////////////////
  m++;
  if(m>2){m=1;}    
  switch(m){
case 1:////显示参数名称
  ss=0;disp_c=0;en_dsp();
                          switch(mi){
    case 0:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
      disp[2]=11;
      disp[1]=10;
      disp[0]=1;
  dsp();
  break;
case 1:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
      disp[2]=11;
      disp[1]=10;
      disp[0]=2;
  dsp();
  break;
case 2:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间,2显示高低转速测量
      disp[2]=11;
      disp[1]=10;
      disp[0]=3;
  dsp();
  break;
  }
  break;
case 2:////显示参数
  ss=1;en_dsp();
  switch (mi){//显示设定参数mi=0显示预设报警值,1显示保护检测时间
    case 0:
  disp[3]=count/1000;
          disp[2]=(count%1000)/100;
          disp[1]=(count%100)/10;
          disp[0]=count%10;
  for(i=0;i<150;i++){dsp();}
  break;
    case 1:
      disp[3]=11;
          disp[2]=11;
          disp[1]=bh/10;
          disp[0]=bh%10;
  for(i=0;i<150;i++){dsp();}
  break;
case 2:
  disp[3]=11;
          disp[2]=11;
          disp[1]=11;
          disp[0]=ltj;
  for(i=0;i<150;i++){dsp();}
  break;
  }
  break;
  }
  /////////////////
 }
               case 0x19://key1
                 {
             break;
                 }
               case 0x13://key2
                 {
  //闪动位移
                      if(ss==1)
    {
  switch (mi){
    case 0:
      en_dsp();////预设转速4位显示
          disp_c++;
          if(disp_c>3){disp_c=0;}
      break;
        case 1:
          en_dsp();////输出保护时间2位显示
      disp_c++;
      if(disp_c>1){disp_c=0;}
  break;
case 2:
  break;
  }
}
                      if(m==1)
    {//保存数据退出设置状态
  savedate();
      //借用后恢复
  //bjing=0;
  m=0;
  mi=0;
      key_set=0;
  ss=0;
                          en_dsp();
      disp[0]=0;
      disp[1]=0;
      disp[2]=0;
      disp[3]=0;
      for(i=0;i<150;i++){dsp();}
  if(ltj==1)
    {
  TMOD=0x11;TL0=0xaf;TH0=0x3c;TL1=0xaf;TH1=0x3c;ET0=1;ET1=1;TR0=1;TR1=1;
}
  EA=1;//数据保存允许中断
}
              break;
                 }
   case 0x0b://key3
                 {
  /////////////////
  if(m==1)
    { disp_c=0;
  mi++;if(mi>2){mi=0;}
  switch(mi){
    case 0:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
      disp[2]=11;
      disp[1]=10;
      disp[0]=1;
  dsp();
                              break;
    case 1:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
      disp[2]=11;
      disp[1]=10;
      disp[0]=2;
  dsp();
  break;
case 2:
  disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
      disp[2]=11;
      disp[1]=10;
      disp[0]=3;
  dsp();
  break;
  }
}
  else
    { 
  m=0;
  switch(mi){
    case 0:
  disp[disp_c]++;
          if(disp[disp_c]>9){disp[disp_c]=0;}
                              if((disp[3]*1000+disp[2]*100+disp[1]*10+disp[0])>6000)
            { //如果超出设定范围
          disp[3]=0;disp[2]=0;disp[1]=0;disp[0]=0;
        }
  count=disp[3]*1000+disp[2]*100+disp[1]*10+disp[0];
          dsp_flash();
      break;
        case 1:
  disp[disp_c]++;
          if(disp[disp_c]>9){disp[disp_c]=0;}
  bh=disp[1]*10+disp[0];
          dsp_flash();
      break;
case 2:
  disp[disp_c]++;
          if(disp[disp_c]>1){disp[disp_c]=0;}
  ltj=disp[0];
          dsp_flash();
      break;
  }
          }
  break;
                 }
  }
}//3
  else
{//4
            switch(ktemp){
               case 0x1a://key0
                 {
  ////////////////
  //禁止测转速
    EA=0;
    key_set=1;
en_bj=0;//如果设定状态允许报警标志0
out=0;//
/////
//bjing=0;
    ///disp_c=0;//time0
/////
m=1;
disp[3]=11;////显示设定参数mi=0显示预设报警值,1显示保护检测时间
disp[2]=11;
disp[1]=10;
disp[0]=1;
for(i=0;i<150;i++){dsp();}
                        
              break;
                 }
   case 0x19://key1
                 {
  //允许报警
  en_bj=1;
              break;
                 }
   }
}//4
    }//2
}//1
}//0

main()
{uchar i;
out=0;
key_set=0;
disp[0]=0;
disp[1]=0;
disp[2]=0;
disp[3]=0;
for(i=0;i<250;i++)display();

getdate();
en_dsp();
//////
time0=0;time1=0;zs=0;bj=0;js=0;begin1=0;bjing=0;
EA=0;EX0=1;IT0=1;PT1=1;//CPU关中断,INT0请求中断,设定INT0触发方式
if(ltj==1)
  {
    TMOD=0x11;TL0=0xaf;TH0=0x3c;TL1=0xaf;TH1=0x3c;ET0=1;ET1=1;TR0=1;TR1=1; /*50ms,T1T0工作在定时器方式1,T1开中断,启动T1*/           
  }
else
  {
    TMOD=0x11;TL0=0xaf;TH0=0x3c;ET0=1;TR0=1;
  }
EA=1;
//////
begin:
  if(bjing==1)
    {
  bj++;
  if(bj>500)
    {
      bjing=0;out=0;//清除报警
      bj=0;bhtm=0;
}

}
  else
    {
  bj=0;
}
  display();
  kbscan();
goto begin;
}

关键字:c51  测转速 引用地址:c51写的测转速源程序

上一篇:51单片机12M晶振的延时程序
下一篇:单片机复位电路的可靠性设计及精典实用复位电路

推荐阅读最新更新时间:2024-03-16 15:09

C51学习心得体会,static和extern在程序中的应用
1、用stat IC 、extern可以声明变量 1.1 可用static声明全局变量和局部变量(包括数组)。 (1)用static声明的局部变量只能被定义该变量的函数识别,在退出函数时该局部变量仍然保持其值, e.g. void temp() { static int array ;//静态局部变量 ...... } 用static声明局部数组可以避免在每次调用函数时都建立和初始化数组,以及在每次退出函数时撤销数组,缩短程序执行时间。 (2)用static声明静态外部变量,可以限定外部变量只被本文件引用,不会被其他文件引用.为文件的模块化、通用性提供方便. e.g. file1.c(file1文件) static int A;/
[单片机]
printf in KEIL C51 使用注意事项
在keil中使用printf()函数的要点 在网上找资料时找到一篇介绍在keil中使用printf()函数的文章,copy到这里,作为备忘。 在keil中printf默认是向串口中发送数据的,所以,如果应用该函数,必须先初始化串口,否则可能引起死机的情况,并且在printf之前应该先将TI置位,摘抄原因如下: 1.printf函数是调用putchar函数输入的,而putchar应该是先判断ti是否为1,不为1则等待为1。如果为1则清0,然后送出一 个字符。因此你如果直接使用printf函数,你的程序就会在putchar函数中等待ti为1。这时你的程序就相当于直接死掉了。你可以通过改写 putchar函数实现自己的目的的
[单片机]
C51教程 第四个51程序:中断控制--外部中断0
内部资源之外部中断 中断类型 中断入口地址 中断序号 外部中断0(INT0)P3.2 0003H 0 外部中断1(INT1)P3.3 0013H 2 定时计数器0(T0) 16bit 000BH 1 定时计数器1(T1) 001BH 3 定时计数器2(T2) 002BH 5 异步串行通信口(UART) 0023H 4 CPU外围模块的掌握方法: (1)相关口线 (2)相关控制字 (3)模块的工作方式 一、外部中断 (1)相关口线 P3.2:int0,外部
[单片机]
<font color='red'>C51</font>教程 第四个51程序:中断控制--外部中断0
C51定时器和计数器 timer and counter
代码: #include reg52.h unsigned char a,num; sbit LED1=P1^0; void main() { num=0; EA=1; //开总中断 ET0=1; //开定时器 0 分开关 TMOD=0X01; //设置为定时器 0 ,方式 1 TH0=(65536-50000)/256; //给定时器 0 装初值,12 Mhz晶振定时时间为 50ms TL0=(65536-50000)%256; TR0=1; //启动定时器0 while(1) { if(num==20) { num=0; LED1=~LED1; } } } void time
[单片机]
<font color='red'>C51</font>定时器和计数器 timer and counter
C51内存优化(data/idata/xdata)
对 51 单片机内存的认识,很多人有误解,最常见的是以下两种 ① 超过变量128后必须使用compact模式编译 实际的情况是只要内存占用量不超过 256.0 就可以用 small 模式编译 ② 128以上的某些地址为特殊寄存器使用,不能给程序用 与 PC 机不同,51 单片机不使用线性编址,特殊寄存器与 RAM 使用重复的重复的地址。但访问时采用不同的指令,所以并不会占用 RAM 空间。 由于内存比较小,一般要进行内存优化,尽量提高内存的使用效率。 以 Keil C 编译器为例,small 模式下未指存储类型的变量默认为data型,即直接寻址,只能访问低 128 个字节,但这 128 个字节也不是全为我们的程序所用,
[单片机]
51单片机之实现流水灯
在实现流水灯之前,我们有必要提一点,C51代码在写之前,要参考电路图来写。拿流水灯来说,我们来看图二,LED灯,也就是二极管,八只LED的正极通过一根总线接在+5V的电压上,再看图一,可知八只LED灯的负极接在LED、P2的8个I/O口上。根据二极管的导通条件可知,在单片机的IO口输出低电平时,才能点亮LED灯。 下面贴上代码: #include reg52.h #define uchar unsigned char #define uint unsigned int sbit LED1 = P2^0; sbit LED2 = P2^1; sbit LED3 = P2^2; sbit LED4 = P2^3;
[单片机]
51单片机之实现流水灯
单片机c语言教程:C51运算符和表达式(指针和地址运算符)
我们学习数据类型时,学习过指针类型,知道它是一种存放指向另一个数据的地址的变量类型。指针是单片机C语言中一个十分重要的概念,也是学习单片机C语言中的一个难点。对于指针将会在第九课中做详细的讲解。在这里我们先来了解一下单片机C语言中供给的两个专门用于指针和地址的运算符: * 取内容 & 取地址取内容和地址的一般形式分别为: 变量 = * 指针变量 指针变量 = & 目标变量 取内容运算是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算是将目标变量的地址赋给左边的变量。要注意的是:指针变量中只能存放地址(也就是指针型数据), 一般情况下不要将非指针类型的数据赋值给一个指针变量。 下面来看一个例子,并用一个图表和实
[单片机]
单片机c语言教程:<font color='red'>C51</font>运算符和表达式(指针和地址运算符)
直流电机控制Keil c51源代码
直流电机开环控制Keil c51源代码 //-----------------------函数声明,变量定义------------------------ #include reg51.h #include intrins.h #include ABSACC.H //-----------------------定义管脚---------------------------------- sbit PWM=P1^0; //PWM波形输出 sbit DR=P1^1; //方向控制 #define timer_da ta (256-100) //定时器预置值,12M时钟是,定时0.1
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved