STM32
直播中

迷你洼哇

11年用户 553经验值
私信 关注
[问答]

如何去实现STC12C5A60S2和stm32之间的通信呢

如何去实现STC12C5A60S2和STM32之间的通信呢?
STC12C5A60S2是如何使用NRF24L01和stm32进行通信的?

回帖(2)

何微微

2021-12-16 09:20:46

/******************************************/
//
// 该程序工作的主频是12MHz,单片机使用STC12C5A60S2
//
/******************************************/


#include "STC12C5A60S2.H"


#define uchar unsigned char
#define uint  unsigned int


/**********  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]= {0x34,0x43,0x10,0x10,0x01};
const uchar RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};


***it NRF_CE = P1^2;
***it NRF_CSN = P1^3;
***it NRF_MISO = P1^6;
***it NRF_MOSI = P1^5;
***it NRF_SCK = P1^7;
***it NRF_IRQ = P1^4;


***it LED1=P1^0;         //状态指示灯
***it LED2=P1^1;         //接收时的被控对象


unsigned char send_buf[TX_PLOAD_WIDTH]="qwertyuiopasdfghjklzxcvbnm123456";         //26+6
unsigned char recv_buf[RX_PLOAD_WIDTH];
/* 延时函数    */
/***************/
void delay_ms(unsigned char ms)
{
    unsigned int i;
    do {
        i = 1701;
        while(--i)        ;   //14T per loop
    } while(--ms);
}
/**********************/
/* 初始化硬件SPI口    */
/**********************/
void SPI_Init(void)
{
    NRF_CE=0;
    NRF_CSN=1;
    NRF_SCK=0;
    NRF_IRQ=1;


    //SPSTAT |= 0XC0;
    //SPCTL = 0XD0;
}


/**********************/
/* SPI数据收发函数    */
/**********************/
//uchar SPI_RW(uchar tr_data)
//{
//    uchar i=0;
//
//    SPSTAT |= 0Xc0; // 清高两位,
//    SPDAT=tr_data;
//    while(((SPSTAT&0X80)!=0X80)&&(i<20))
//    {
//        i++;
//        delay_ms(1);
//    }
//    return SPDAT;
//}
// 下面是“模拟SPI”
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         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         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)//接收到数据
    {
        NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
        NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
        return 0;
    }
    return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
    uchar state;
//        uchar i;


    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_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_TX_Mode(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,40);       //设置RF通道为125
    //NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27);  //7db增益,250kbps
    NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   (两边的速率一定要一样!!!!)
    NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0E);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断
    NRF_CE=1;        //CE置高
}


void NRF24L01_RX_Mode(void)
{
    NRF_CE=0;
    NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址


    NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);    //使能通道0的自动应答
    NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
    NRF24L01_Write_Reg(WRITE_REG+RF_CH,40);             //设置RF通信频率
    NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
    NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
    NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
    delay_ms(150);
    NRF_CE = 1; //CE为高,进入接收模式
}








/**********************************************/
void main(void)
{
    LED1=0;
    delay_ms(100); // 延时待系统稳定
    SPI_Init(); // 初始化SPI口
    while(NRF24L01_Check()); // 等待检测到NRF24L01,程序才会向下执行
    LED1=1;
    LED2=1;
    NRF24L01_RX_Mode(); // 配置NRF24L01为发送模式
    while (1)
    {
        delay_ms(500);
        NRF24L01_RxPacket(recv_buf);        // 无线发送数据
        LED1=!LED1;
        if(recv_buf[0]=='a')        LED2=0;
        else                                         LED2=1;
    }


    NRF24L01_TX_Mode(); // 配置NRF24L01为发送模式
    while (1)
    {
        delay_ms(500);
        NRF24L01_TxPacket(send_buf);        // 无线发送数据
        LED1=!LED1;
    }
}
举报

李慎梓

2021-12-16 09:20:49
stm32部分使用的正点原子开发板例程,只对主程序进行了一部分改写。

        if(mode==0)//RX模式
    {
        LCD_ShowString(30,150,200,16,16,"NRF24L01 RX_Mode");
        LCD_ShowString(30,170,200,16,16,"Received DATA:");
        NRF24L01_RX_Mode();
        while(1)
        {
            if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到信息,则显示出来.
            {
                tmp_buf[32]=0;//加入字符串结束符
                LCD_ShowString(0,190,lcddev.width-1,32,16,tmp_buf);
            } else delay_us(100);
            t++;
            if(t==10000)//大约1s钟改变一次状态
            {
                t=0;
                LED0=!LED0;
            }
        };
    } else//TX模式
    {


        LCD_ShowString(30,150,200,16,16,"NRF24L01 TX_Mode");
        NRF24L01_TX_Mode();


        while(1)
        {
            key=KEY_Scan(0);
            if(key==KEY0_PRES)                               
                                                        test[0]='a';
            else if(key==KEY1_PRES)       
                                                        test[0]='b';
            if(NRF24L01_TxPacket(test)==TX_OK)
            {
                LCD_ShowString(30,170,239,32,16,"Sended DATA:");
                LCD_ShowString(0,190,lcddev.width-1,32,16,test);
            } else
            {
                LCD_Fill(0,170,lcddev.width,170+16*3,WHITE);//清空显示
                LCD_ShowString(30,170,lcddev.width-1,32,16,"Send Failed ");
            };
            LED0=!LED0;
            delay_ms(500);
        };
    }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分