找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 998|回复: 0
打印 上一主题 下一主题
收起左侧

求助按键计数+无线传输计数值和按键时间间隔+超时未按键计数

[复制链接]
跳转到指定楼层
楼主
ID:592558 发表于 2020-1-6 15:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int    //常用数据预定义
#define uchar unsigned char



sfr T2MOD=0xc9;


sbit K1=P3^2;     //按键中断输入

sbit beep=P1^0;    //蜂鸣器 低电平触发
sbit relay=P1^7;   //继电器 低电平触发

uint t0,t1,t2;       //定时器计数标志位
uint time,result;  //存储种茎间隔
double ti;         

uint alarm;        //定时器0计数个数设置

sbit rs=P1^4;
sbit rw=P1^5;
sbit en=P1^6;

uchar busy;

uchar table0[]="OFF l_num:      ";
uchar table1[]="s_num:          ";

uchar TempBuffer1[10],TempBuffer2[10];

uchar KeyValue=0;
unsigned long int num1=0,num2=0;

uchar flag=0;           //启动标志位


sbit NRF_CE   = P1^1;
sbit NRF_CSN  = P1^2;
sbit NRF_MISO = P3^6;
sbit NRF_MOSI = P3^5;
sbit NRF_SCK  = P3^4;
sbit NRF_IRQ  = P3^7;

uchar rece_buf[32];

/**********  NRF24L01寄存器操作命令  ***********/
#define READ_REG        0x00  //读配置寄存器,低5位为寄存器地址
#define WRITE_REG       0x20  //写配置寄存器,低5位为寄存器地址
#define RD_RX_PLOAD     0x61  //读RX有效数据,1~32字节
#define WR_TX_PLOAD     0xA0  //写TX有效数据,1~32字节
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.发射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包数据,CE为高,数据包被不断发送.
#define NOP             0xFF  //空操作,可以用来读状态寄存器         
/**********  NRF24L01寄存器地址   *************/
#define CONFIG          0x00  //配置寄存器地址                             
#define EN_AA           0x01  //使能自动应答功能
#define EN_RXADDR       0x02  //接收地址允许
#define SETUP_AW        0x03  //设置地址宽度(所有数据通道)
#define SETUP_RETR      0x04  //建立自动重发
#define RF_CH           0x05  //RF通道
#define RF_SETUP        0x06  //RF寄存器
#define STATUS          0x07  //状态寄存器
#define OBSERVE_TX      0x08  // 发送检测寄存器
#define CD              0x09  // 载波检测寄存器
#define RX_ADDR_P0      0x0A  // 数据通道0接收地址
#define RX_ADDR_P1      0x0B  // 数据通道1接收地址
#define RX_ADDR_P2      0x0C  // 数据通道2接收地址
#define RX_ADDR_P3      0x0D  // 数据通道3接收地址
#define RX_ADDR_P4      0x0E  // 数据通道4接收地址
#define RX_ADDR_P5      0x0F  // 数据通道5接收地址
#define TX_ADDR         0x10  // 发送地址寄存器
#define RX_PW_P0        0x11  // 接收数据通道0有效数据宽度(1~32字节)
#define RX_PW_P1        0x12  // 接收数据通道1有效数据宽度(1~32字节)
#define RX_PW_P2        0x13  // 接收数据通道2有效数据宽度(1~32字节)
#define RX_PW_P3        0x14  // 接收数据通道3有效数据宽度(1~32字节)
#define RX_PW_P4        0x15  // 接收数据通道4有效数据宽度(1~32字节)
#define RX_PW_P5        0x16  // 接收数据通道5有效数据宽度(1~32字节)
#define FIFO_STATUS     0x17  // FIFO状态寄存器
/*————————————————————————————————————————————————————————————————————*/

/******   STATUS寄存器bit位定义      *******/
#define MAX_TX          0x10            //达到最大发送次数中断
#define TX_OK           0x20            //TX发送完成中断
#define RX_OK           0x40            //接收到数据中断
/*——————————————————————————————————————————————————*/

/*********     24L01发送接收数据宽度定义          ***********/
#define TX_ADR_WIDTH    5     //5字节地址宽度
#define RX_ADR_WIDTH    5     //5字节地址宽度
#define TX_PLOAD_WIDTH  32    //32字节有效数据宽度
#define RX_PLOAD_WIDTH  32    //32字节有效数据宽度

const uchar TX_ADDRESS[TX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址
const uchar RX_ADDRESS[RX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址

void delay_us(uchar num)
{
        uchar i;
        for(i=0;i>num;i++)
        _nop_();
}
void delay_150us()
{
        uint i;

        for(i=0;i>150;i++);
}
void delay(uint t)
{
        uchar k;
        while(t--)
        for(k=0;k<200;k++);
}
/***************************************************************/

/*******************************************************************/
uchar SPI_RW(uchar byte)
{
        uchar bit_ctr;
        for(bit_ctr=0;bit_ctr<8;bit_ctr++)  // 输出8位
        {
                NRF_MOSI=(byte&0x80);                         // MSB TO MOSI
                byte=(byte<<1);                                        // shift next bit to MSB
                NRF_SCK=1;
                byte|=NRF_MISO;                                // capture current MISO bit
                NRF_SCK=0;
        }
        return byte;
}

/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg   要写的寄存器地址          */
/*           value 给寄存器写的值            */
/* 出口参数:status 状态值                   */
/*********************************************/
uchar NRF24L01_Write_Reg(uchar reg,uchar value)
{
        uchar status;

        NRF_CSN=0;                  //CSN=0;   
          status = SPI_RW(reg);                //发送寄存器地址,并读取状态值
        SPI_RW(value);
        NRF_CSN=1;                  //CSN=1;

        return status;
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节)      */
/* 入口参数:reg  要读的寄存器地址               */
/* 出口参数:value 读出寄存器的值                */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
        uchar value;

        NRF_CSN=0;              //CSN=0;   
          SPI_RW(reg);                        //发送寄存器值(位置),并读取状态值
        value = SPI_RW(NOP);
        NRF_CSN=1;                     //CSN=1;

        return value;
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节)   */
/* 入口参数:reg   寄存器地址                */
/*           *pBuf 读出寄存器值的存放数组    */
/*           len   数组字节长度              */
/* 出口参数:status 状态值                   */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;                           //CSN=0      
          status=SPI_RW(reg);                                //发送寄存器地址,并读取状态值             
        for(u8_ctr=0;u8_ctr<len;u8_ctr++)
        pBuf[u8_ctr]=SPI_RW(0XFF);                //读出数据
        NRF_CSN=1;                                 //CSN=1
          return status;                                //返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节)  */
/* 入口参数:reg  要写的寄存器地址            */
/*           *pBuf 值的存放数组               */
/*           len   数组字节长度               */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
        uchar status,u8_ctr;
        NRF_CSN=0;
          status = SPI_RW(reg);                        //发送寄存器值(位置),并读取状态值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_RW(*pBuf++);                                 //写入数据
        NRF_CSN=1;
          return status;                          //返回读到的状态值
}                                                                                                    

/*********************************************/
/* 函数功能:24L01接收数据                   */
/* 入口参数:rxbuf 接收数据数组              */
/* 返回值: 0   成功收到数据                 */
/*          1   没有收到数据                 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
        uchar state;
         
        state=NRF24L01_Read_Reg(STATUS);                          //读取状态寄存器的值             
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
        if(state&RX_OK)                                                                //接收到数据
        {
                NRF_CE = 0;
                NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
                NRF24L01_Write_Reg(FLUSH_RX,0xff);                                        //清除RX FIFO寄存器
                NRF_CE = 1;
                delay_150us();
                return 0;
        }          
        return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
        uchar state;

        NRF_CE=0;                                                                                                //CE拉低,使能24L01配置
          NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);        //写数据到TX BUF  32个字节
        NRF_CE=1;                                                                                                //CE置高,使能发送          
        while(NRF_IRQ==1);                                                                                //等待发送完成
        state=NRF24L01_Read_Reg(STATUS);                                                  //读取状态寄存器的值          
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state);                         //清除TX_DS或MAX_RT中断标志
        if(state&MAX_TX)                                                                                //达到最大重发次数
        {
                NRF24L01_Write_Reg(FLUSH_TX,0xff);                                        //清除TX FIFO寄存器
                return MAX_TX;
        }
        if(state&TX_OK)                                                                                        //发送完成
        {
                return TX_OK;
        }
        return 0xff;                                                                                        //发送失败
}

/********************************************/
/* 函数功能:检测24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/           
uchar NRF24L01_Check(void)
{
        uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
        uchar check_out_buf[5]={0x00};

        NRF_SCK=0;
        NRF_CSN=1;   
        NRF_CE=0;

        NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);

        NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);

        if((check_out_buf[0] == 0x11)&&\
           (check_out_buf[1] == 0x22)&&\
           (check_out_buf[2] == 0x33)&&\
           (check_out_buf[3] == 0x44)&&\
           (check_out_buf[4] == 0x55))return 0;
        else return 1;
}                       


void NRF24L01_RT_Init(void)
{       
        NRF_CE=0;                  
          NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
        NRF24L01_Write_Reg(FLUSH_RX,0xff);                                                                        //清除RX FIFO寄存器   
          NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
          NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK          
          NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   
          NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
          NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
          NRF24L01_Write_Reg(WRITE_REG+RF_CH,0);        //设置RF通道为2.400GHz  频率=2.4+0GHz
          NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0F);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
          NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
        NRF_CE=1;                                                                          //CE置高,使能发送
}

void SEND_BUF(uchar *buf)
{
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);
        NRF_CE=1;
        delay_us(15);
        NRF24L01_TxPacket(buf);
        NRF_CE=0;
        NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);
        NRF_CE=1;       
}

//****************************************************************************//

//********************************LCD1602*************************************//

void delay_1ms()
{
    uchar i,j;
    for(i=0;i<10;i++)
    for(j=0;j<20;j++);

}

void busy_1602()
{
    do
    {
      en=0;
      rw=1;
      rs=0;
      en=1;
      busy=P0;
      en=0;
      delay_1ms();
     }while(busy&&0x10==1);

}

void lcd_wcom(uchar com)
{
    busy_1602();
    en=0;
    rs=0;
    rw=0;
    en=1;
    P0=com;
    en=0;

}

void lcd_wdat(uchar dat)
{
    busy_1602();
    en=0;
    rs=1;
    rw=0;
    en=1;
    P0=dat;
    en=0;

}


void lcd_init()
{
    lcd_wcom(0x38);  //8位数据,双列,5*7字形
    lcd_wcom(0x0c);  //开启显示屏,关光标,光标不闪烁
    lcd_wcom(0x06);  //显示地址递增,即写一个数据后,显示位置右移一位
    lcd_wcom(0x01);  //清屏


}



//整型转换为字符串,便于传输
void IntToStr(unsigned long int t, uchar *str, char n)

{

    uchar a[10];

    char i, j;                                

    a[0]=(t/1000000000)%10;         //取得整数值到数组        

    a[1]=(t/100000000)%10;                                    

    a[2]=(t/10000000)%10;                                      

    a[3]=(t/1000000)%10;                                      

    a[4]=(t/100000)%10;

    a[5]=(t/10000)%10;

    a[6]=(t/1000)%10;

    a[7]=(t/100)%10;

    a[8]=(t/10)%10;

    a[9]=(t/1)%10;                                       

    for(i=0; i<10; i++)         //转成ASCII码              

    a[i]=a[i]+'0';                                    

    for(i=0; a[i]=='0' && i<=8; i++);                    

    for(j=10-n; j<i; j++)       //填充空格               

    { *str=' ';  str++; }                           

    for(; i<10; i++)                                      

    { *str=a[i]; str++; }  //加入有效的数字         



}

void lcd_wstr(uchar *s)   //写字符串子程序,输入:*s
{

   while(*s>0)
   {

      lcd_wdat(*s);
      s++;

   }
}

//**************************************************************************//

//*************************初始化、中断函数*********************************//


void IntConfiguration()
{
    //设置INT0
    IT0=1  ;  //下降沿触发
    EX0=1;  //打开INT0的中断允许

   //设置定时器
   TMOD=0x03; //定时器0工作方式3



   TH0=6;  //定时器0计数250次,为271.275us
   TL0=6;
   ET0=1;   //开定时器0中断
   ET1=1;   //开定时器1中断


   EA=1;   //打开总中断

   T2CON=0x00;   //实现16位自动重载定时
   TCLK=0;
   RCLK=0;
   T2MOD=0x00;
   RCAP2H=0x30;
   RCAP2L=0xb0;

   TL2=0x00;
   TH2=0x4c;

   ET2=1;





}


void Int0()        interrupt 0                //外部中断0的中断函数
{
   delay_1ms();
   if(K1==0)
   KeyValue=1;
}

void TL0_time()  interrupt 1          //定时器0中断函数
{
    TL0=6;
    t0++;
}   

void TH0_time()  interrupt 3          //定时器0中断函数
{
   TH0=6;
   t1++;


                 if(t1==alarm)       //标记长度合格
                  {
                      beep=1;
                      relay=1;

                      TR1=0;         //关闭定时器T01
                      TH0=6;
                      t1=0;
                    }






}



void timer2()  interrupt 5
{
      TF2=0;
      t2++;



}
















//**************************主函数*****************************************//



void main()
{   
    uchar i;

    while(NRF24L01_Check()); // 等待检测到NRF24L01,程序才会向下执行
    NRF24L01_RT_Init();

    lcd_init();
    lcd_wcom(0x80);                                        //写指令
    lcd_wstr(table0);
        lcd_wcom(0xc0);
    lcd_wstr(table1);

    IntConfiguration();


           if(NRF_IRQ==0)                 // 如果无线模块接收到数据
                        {               
                                if(NRF24L01_RxPacket(rece_buf)==0)
                                {                          
                                        if(        rece_buf[1]=='1')                           //第1位以后是收到的命令数据,rece_buf[0]是数据位数长度
                                         {        flag=1;
                        lcd_wcom(0x80);            

                        lcd_wstr("ON  l_num:      ");

                        alarm=(rece_buf[2]+rece_buf[3]*0.1)*3686;     //rece_buf[2]、[3]表示计时长度
                      }


                                        if(        rece_buf[1]=='2')                         //第1位以后是收到的命令数据,rece_buf[0]是数据位数长度
                                                flag=0;               
                                }
                        }


                   if(flag)
                 {
                    
                
           while(1)
      {     
                    if(KeyValue)
                    {

                  TR0=0;      //关闭定时器T00
                  TR2=0;
                  TL0=6;
                  t0=0;


                  while((i<50)&&(K1==0))     //判断种茎是否离开
                                   {
                               
                                     delay(1);          //延时200us
                                     i++;
                               
                               
                                   }
                  TR0=1;       //待种茎离开,开启定时器T00
                  KeyValue=0;
                  num1++;
                             
                              IntToStr(num1,&TempBuffer1[0],10);
                              for(i=1;i<=10;i++)
                              {
                                 rece_buf[i]=TempBuffer1[i-1];
                              }
                              rece_buf[0]=10;       
                              SEND_BUF(rece_buf);


                  IntToStr(num2,&TempBuffer1[0],10);
                   for(i=1;i<=10;i++)
                              {
                                 rece_buf[i]=TempBuffer1[i-1];
                              }
                              rece_buf[0]=10;       
                              SEND_BUF(rece_buf);

                  time=TH2*256+TL2;
                  ti=time*0.001085+t2*50;
                  result=(int)ti;
                  IntToStr(result,&TempBuffer2[0],10);
                  for(i=1;i<=10;i++)
                              {
                                 rece_buf[i]=TempBuffer2[i-1];
                              }
                              rece_buf[0]=10;       
                              SEND_BUF(rece_buf);



                    }

            else
            {

                  TR2=1;
                                if(t0==alarm)
                        {
                                          beep=0;
                                          relay=0;                                                                                                                                                   
                                          TR1=1;
                      num2++;
                                                                                                                                                     
                            }  




            }
            
       
        }


           }
       
             
       
            
          





}



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表