标题: NRF24L01 spi 1602液晶显示的奇怪的问题 [打印本页]

作者: codenew    时间: 2014-9-10 10:22
标题: NRF24L01 spi 1602液晶显示的奇怪的问题
      近段时间搞NRF24L01无线模块,头发掉了好几根。有一些疑问,还请指点。
1.SPI_Read(uchar reg )中的reg_val = SPI_RW(0)如何理解,为什么写0后就可读出寄存器中的值了。
/****************************************************************************************************
/*函数:uchar SPI_Read(uchar reg)
/****************************************************************************************************/
uchar SPI_Read(uchar reg)
{
       uchar reg_val;
       CSN = 0;                // CSN low, initialize SPI communication...
       SPI_RW(reg);            // Select register to read from..
       reg_val = SPI_RW(0);    // ..then read registervalue
       CSN = 1;                // CSN high, terminate SPI communication
       return(reg_val);        // return register value
}
2.SPI_RW(uint uchar)最终uchar是返回状态寄存器STAUS(地址0x07)里面的值吗?
**********************
/*函数:uint SPI_RW(uint uchar)
/*功能:NRF24L01的SPI写时序
/****************************************************************************************************/
uint SPI_RW(uint uchar)
{
       uint bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
    {
              MOSI = (uchar & 0x80);         // output 'uchar', MSB to MOSI
              uchar = (uchar << 1);          // shift next bit into MSB..
              SCK = 1;                       // Set SCK high..
              uchar |= MISO;                 // capture current MISO bit
              SCK = 0;                       // ..then set SCK low again
    }
    return(uchar);                     // return read uchar
}
3.    自己从别人的程序里修改一下,做了个最简的小程序来查看NRF24L01寄存器里面的值,结果就出现也问题,怎么想也想不出问题在哪。本意是在NRF24L01上电后,先读出寄存器EN_AA里面的值,让它显示在液晶1602的第一行第一个位值,期望值是063。NRF24L01上电后,EN_AA默认值是 0011 1111,即十进制63。然后向EN_AA写入了0x01,再读出EN_AA里面的值,让它显示在液晶1602的第二行第一个位值,期望值显示的是001。
      结果是液晶1602第一行一开始时是显示063,第二行显示是001,但很快第一行显示变成和第二行一样,即显示001。而且第二行的001不断在闪。不知怎么回事,求指教。程序实际较少,我附在楼下了。还望指点迷津!


作者: codenew    时间: 2014-9-10 10:23
本帖最后由 codenew 于 2014-9-10 20:57 编辑

      本意是在NRF24L01上电后,先读出寄存器EN_AA里面的值,让它显示在液晶1602的第一行第一个位值,期望值是063。NRF24L01上电后,EN_AA默认值是 0011 1111,即十进制63。然后向EN_AA写入了0x01,再读出EN_AA里面的值,让它显示在液晶1602的第二行第一个位值,期望值显示的是001。下面是正常显示的图和程序:

#include<reg51.h>   
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned char uint;
unsigned char code digit[10]={"0123456789"};        //定义字符数组显示数字
//*********NRF24L01 IO端口定义**********//                                    
sbit  MISO =P1^2;
sbit  MOSI =P1^3;
sbit  SCK  =P1^4;
sbit  CE   =P1^6;
sbit  CSN  =P1^5;
sbit  IRQ  =P1^0;
sbit rs=P3^3;//LCD数据/命令选择端(H/L)
sbit rw=P3^4;//LCD/写选择端(H/L)
sbit en=P3^5;//LCD使能控制
//*************NRF24L01寄存器指令***********//
#define READ_REG        0x00   // 读寄存器指令
#define WRITE_REG       0x20   // 写寄存器指令
//*************SPI(nRF24L01)寄存器地址********//
#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
void inerDelay_us(unsigned char n);
uint SPI_RW(uint uchar);
uchar SPI_Read(uchar reg);
uint SPI_RW_Reg(uchar reg, uchar value);
void delays(uint x);
void write_com(uchar com);
void display_temp1(unsigned char x);
void write_date(uchar date);
/*****************************************************
函数功能:主函数
***************************************************/
void main(void)
{     
         unsigned int TN;  
         unsigned int TD;  
        uchar i=0;
         //BEEP=0;          //防止蜂鸣器的电流声
       inerDelay_us(100);
       CE=0;    // chip enable
       CSN=1;   // Spi disable
       SCK=0;   // Spi clock line init high
       write_com(0x38);   //设置工作方式
       write_com(0x0c);   //设置光标
       write_com(0x06);   //设置输入方式
       write_com(0x01);   //清屏
      
                       
                                 TN=SPI_Read(EN_AA);
                                   write_com(0x80);
                                   display_temp1(TN);     //期望值是063(十进制),NRF24L01上电后,EN_AA默认值是 0011 1111,即十进制63
                                   
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                                   
                                   SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);                              
                                  TD=SPI_Read(EN_AA);
                                   write_com(0x80+0x40);      
                                   display_temp1(TD);     //期望值是001,因为前面向EN_AA写入了0x01
                                delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
}
/*****************************************************
函数功能:显示十进制数
入口参数:x
***************************************************/
void display_temp1(unsigned char x)
{
       unsigned char j,k,l;     //j,k,l分别储存温度的百位、十位和个位
       j=x/100;              //取百位
       k=(x%100)/10;         //取十位
       l=x%10;               //取个位  
       write_date(digit[j]);    //将百位数字的字符常量写入LCD
       write_date(digit[k]);    //将十位数字的字符常量写入LCD
       write_date(digit[l]);    //将个位数字的字符常量写入LCD
       //write_date('.');               //小数点
       delays(50);           //延时1ms给硬件一点反应时间     
}           
      
/***********1602液晶显示部分子程序****************/
void write_com(uchar com)
{
       rs=0;//命令
       rw=0;
       P0=com;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
void write_date(uchar date)
{
       rs=1;//数据
       rw=0;
       P0=date;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
/****************************************************************************************************/
/*功能:NRF24L01读写寄存器函数
/****************************************************************************************************/
uint SPI_RW_Reg(uchar reg, uchar value)
{
       uint status;
       CSN = 0;                   // CSN low, init SPI transaction
       status = SPI_RW(reg);      // select register
       SPI_RW(value);             // ..and write value to it..
       CSN = 1;                   // CSN high again
       return(status);            // return nRF24L01 status uchar
}
/****************************************************************************************************
/*函数:uchar SPI_Read(uchar reg)
/*功能:NRF24L01SPI时序
/*详细请参考Page19
/****************************************************************************************************/
uchar SPI_Read(uchar reg)
{
       uchar reg_val;
       CSN = 0;                // CSN low, initialize SPI communication...
       SPI_RW(reg);            // Select register to read from..
       reg_val = SPI_RW(0);    // ..then read registervalue
       CSN = 1;                // CSN high, terminate SPI communication
       return(reg_val);        // return register value
}
/****************************************************************************************************
/*函数:uint SPI_RW(uint uchar)
/*功能:NRF24L01SPI写时序
/*详细请参考Page19
/****************************************************************************************************/
uint SPI_RW(uint uchar)
{
       uint bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
    {
              MOSI = (uchar & 0x80);         // output 'uchar', MSB to MOSI
              uchar = (uchar << 1);          // shift next bit into MSB..
              SCK = 1;                       // Set SCK high..
              uchar |= MISO;                 // capture current MISO bit
              SCK = 0;                       // ..then set SCK low again
    }
    return(uchar);                     // return read uchar
}
//*****************长延时*********************************//
void delays(uint x) //毫秒级延时函数
{
  uint i,j;
  for(i=x;i>0;i--)
     for(j=110;j>0;j--);
}
//********************************************************//
//*延时函数
//********************************************************//
void inerDelay_us(unsigned char n)
{  
for(;n>0;n--)
  _nop_();
}

正常.jpg (61.5 KB, 下载次数: 127)

正常

正常

作者: codenew    时间: 2014-9-10 10:36
本帖最后由 codenew 于 2014-9-10 20:58 编辑

下面程序第一行先显示063,第二行先显示001,很快第一行变成001,而且第二行的001还在不断闪。

#include<reg51.h>   
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned char uint;
unsigned char code digit[10]={"0123456789"};        //定义字符数组显示数字
//*********NRF24L01 IO端口定义**********//                                    
sbit  MISO =P1^2;
sbit  MOSI =P1^3;
sbit  SCK  =P1^4;
sbit  CE   =P1^6;
sbit  CSN  =P1^5;
sbit  IRQ  =P1^0;
//***液晶1602定义,数据口接P0**//
sbit rs=P3^3;//LCD数据/命令选择端(H/L)
sbit rw=P3^4;//LCD/写选择端(H/L)
sbit en=P3^5;//LCD使能控制
//*************NRF24L01寄存器指令***********//
#define READ_REG        0x00   // 读寄存器指令
#define WRITE_REG       0x20   // 写寄存器指令
//*************SPI(nRF24L01)寄存器地址********//
#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
void inerDelay_us(unsigned char n);
uint SPI_RW(uint uchar);
uchar SPI_Read(uchar reg);
uint SPI_RW_Reg(uchar reg, uchar value);
void delays(uint x);
void write_com(uchar com);
void display_temp1(unsigned char x);
void write_date(uchar date);
/*****************************************************
函数功能:主函数
***************************************************/
void main(void)
{     
         unsigned int TN;  
         unsigned int TD;  
       inerDelay_us(100);
       CE=0;    // chip enable
       CSN=1;   // Spi disable
       SCK=0;   // Spi clock line init high
       write_com(0x38);   //设置工作方式
       write_com(0x0c);   //设置光标
       write_com(0x06);   //设置输入方式
       write_com(0x01);   //清屏     
                       
                                 TN=SPI_Read(EN_AA);
                                   write_com(0x80);
                                   display_temp1(TN);// 期望值显示的是063(十进制),NRF24L01上电后,EN_AA默认值是 0011 1111,即十进制63
                                   
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                                   
                                   SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);                              
                                  TD=SPI_Read(EN_AA);
                                   write_com(0x80+0x40);      
                                   display_temp1(TD); //期望值显示的是001,因为前面向EN_AA写入了0x01
                                delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
}
/*****************************************************
函数功能:显示十进制数
入口参数:x
***************************************************/
void display_temp1(unsigned char x)
{
       unsigned char j,k,l;     //j,k,l分别储存温度的百位、十位和个位
       j=x/100;              //取百位
       k=(x%100)/10;         //取十位
       l=x%10;               //取个位  
       write_date(digit[j]);    //将百位数字的字符常量写入LCD
       write_date(digit[k]);    //将十位数字的字符常量写入LCD
       write_date(digit[l]);    //将个位数字的字符常量写入LCD
       delays(50);           //延时1ms给硬件一点反应时间     
}           
      
/***********1602液晶显示部分子程序****************/
void write_com(uchar com)
{
       rs=0;//命令
       rw=0;
       P0=com;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
void write_date(uchar date)
{
       rs=1;//数据
       rw=0;
       P0=date;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
/****************************************************************************************************/
/*功能:NRF24L01读写寄存器函数
/****************************************************************************************************/
uint SPI_RW_Reg(uchar reg, uchar value)
{
       uint status;
       CSN = 0;                   // CSN low, init SPI transaction
       status = SPI_RW(reg);      // select register
       SPI_RW(value);             // ..and write value to it..
       CSN = 1;                   // CSN high again
       return(status);            // return nRF24L01 status uchar
}
/****************************************************************************************************
/*函数:uchar SPI_Read(uchar reg)
/****************************************************************************************************/
uchar SPI_Read(uchar reg)
{
       uchar reg_val;
       CSN = 0;                // CSN low, initialize SPI communication...
       SPI_RW(reg);            // Select register to read from..
       reg_val = SPI_RW(0);    // ..then read registervalue
       CSN = 1;                // CSN high, terminate SPI communication
       return(reg_val);        // return register value
}
/****************************************************************************************************
/*函数:uint SPI_RW(uint uchar)
/*功能:NRF24L01SPI写时序
/****************************************************************************************************/
uint SPI_RW(uint uchar)
{
       uint bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
    {
              MOSI = (uchar & 0x80);         // output 'uchar', MSB to MOSI
              uchar = (uchar << 1);          // shift next bit into MSB..
              SCK = 1;                       // Set SCK high..
              uchar |= MISO;                 // capture current MISO bit
              SCK = 0;                       // ..then set SCK low again
    }
    return(uchar);                     // return read uchar
}
//*****************长延时*********************************//
void delays(uint x) //毫秒级延时函数
{
  uint i,j;
  for(i=x;i>0;i--)
     for(j=110;j>0;j--);
}
//********************************************************//
//*延时函数
//********************************************************//
void inerDelay_us(unsigned char n)
{  
for(;n>0;n--)
  _nop_();
}

异常.jpg (27.85 KB, 下载次数: 117)

异常

异常

作者: codenew    时间: 2014-9-10 20:51
上面两个程序看着是一样的,运行效果却不一样,编译都没错呀,为什么会这样。仔细看了多次,还是觉得一样的,快发疯了。。。
作者: a119    时间: 2014-9-10 22:59
nrf24l01好像有挪威与台湾之分  ,貌似程序不同
作者: codenew    时间: 2014-9-14 21:00
     大家不要花时间看了,找出问题所在了。在程序最后加上while(1);,就什么都正常了。如果不加程序又会从头开始执行。
    主要是平时看C语言教材,主函数最后没有死循环。51单片机主函数必须要有死循环?望大虾解释一下。
作者: ldy4747    时间: 2014-11-30 09:16
高手哦正在找NRF24L01的程序
#include<reg51.h>   
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned char uint;
unsigned char code digit[10]={"0123456789"};        //定义字符数组显示数字
//*********NRF24L01 IO端口定义**********//                                    
sbit  MISO =P1^2;
sbit  MOSI =P1^3;
sbit  SCK  =P1^4;
sbit  CE   =P1^6;
sbit  CSN  =P1^5;
sbit  IRQ  =P1^0;
sbit rs=P3^3;//LCD数据/命令选择端(H/L)
sbit rw=P3^4;//LCD读/写选择端(H/L)
sbit en=P3^5;//LCD使能控制
//*************NRF24L01寄存器指令***********//
#define READ_REG        0x00   // 读寄存器指令
#define WRITE_REG       0x20   // 写寄存器指令
//*************SPI(nRF24L01)寄存器地址********//
#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
void inerDelay_us(unsigned char n);
uint SPI_RW(uint uchar);
uchar SPI_Read(uchar reg);
uint SPI_RW_Reg(uchar reg, uchar value);
void delays(uint x);
void write_com(uchar com);
void display_temp1(unsigned char x);
void write_date(uchar date);
/*****************************************************
函数功能:主函数
***************************************************/
void main(void)
{     
         unsigned int TN;  
         unsigned int TD;  
        uchar i=0;
         //BEEP=0;          //防止蜂鸣器的电流声
       inerDelay_us(100);
       CE=0;    // chip enable
       CSN=1;   // Spi disable
       SCK=0;   // Spi clock line init high
       write_com(0x38);   //设置工作方式
       write_com(0x0c);   //设置光标
       write_com(0x06);   //设置输入方式
       write_com(0x01);   //清屏
      
                       
                                 TN=SPI_Read(EN_AA);
                                   write_com(0x80);
                                   display_temp1(TN);     //期望值是063(十进制),NRF24L01上电后,EN_AA默认值是 0011 1111,即十进制63。
                                   
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                    delays(200);
                                   
                                   SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);                              
                                  TD=SPI_Read(EN_AA);
                                   write_com(0x80+0x40);      
                                   display_temp1(TD);     //期望值是001,因为前面向EN_AA写入了0x01。
                                delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);
                                   delays(200);                                   while(1);/********意思是这里加个while(1);就正常是把很好的模板程序受益匪浅********/

}
/*****************************************************
函数功能:显示十进制数
入口参数:x
***************************************************/
void display_temp1(unsigned char x)
{
       unsigned char j,k,l;     //j,k,l分别储存温度的百位、十位和个位
       j=x/100;              //取百位
       k=(x%100)/10;         //取十位
       l=x%10;               //取个位  
       write_date(digit[j]);    //将百位数字的字符常量写入LCD
       write_date(digit[k]);    //将十位数字的字符常量写入LCD
       write_date(digit[l]);    //将个位数字的字符常量写入LCD
       //write_date('.');               //小数点
       delays(50);           //延时1ms给硬件一点反应时间     
}           
      
/***********1602液晶显示部分子程序****************/
void write_com(uchar com)
{
       rs=0;//命令
       rw=0;
       P0=com;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
void write_date(uchar date)
{
       rs=1;//数据
       rw=0;
       P0=date;
       delays(5);
       en=1;
       delays(5);
       en=0;
}
/****************************************************************************************************/
/*功能:NRF24L01读写寄存器函数
/****************************************************************************************************/
uint SPI_RW_Reg(uchar reg, uchar value)
{
       uint status;
       CSN = 0;                   // CSN low, init SPI transaction
       status = SPI_RW(reg);      // select register
       SPI_RW(value);             // ..and write value to it..
       CSN = 1;                   // CSN high again
       return(status);            // return nRF24L01 status uchar
}
/****************************************************************************************************
/*函数:uchar SPI_Read(uchar reg)
/*功能:NRF24L01的SPI时序
/*详细请参考Page19
/****************************************************************************************************/
uchar SPI_Read(uchar reg)
{
       uchar reg_val;
       CSN = 0;                // CSN low, initialize SPI communication...
       SPI_RW(reg);            // Select register to read from..
       reg_val = SPI_RW(0);    // ..then read registervalue
       CSN = 1;                // CSN high, terminate SPI communication
       return(reg_val);        // return register value
}
/****************************************************************************************************
/*函数:uint SPI_RW(uint uchar)
/*功能:NRF24L01的SPI写时序
/*详细请参考Page19
/****************************************************************************************************/
uint SPI_RW(uint uchar)
{
       uint bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
    {
              MOSI = (uchar & 0x80);         // 用传过来的数据和0x80进行&与运算
              uchar = (uchar << 1);          // shift next bit into MSB..
              SCK = 1;                       // Set SCK high..
              uchar |= MISO;                 // capture current MISO bit
              SCK = 0;                       // ..then set SCK low again
    }
    return(uchar);                     // return read uchar
}
//*****************长延时*********************************//
void delays(uint x) //毫秒级延时函数
{
  uint i,j;
  for(i=x;i>0;i--)
     for(j=110;j>0;j--);
}
//********************************************************//
//*延时函数
//********************************************************//
void inerDelay_us(unsigned char n)
{  
for(;n>0;n--)
  _nop_();
}







欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1