CC1101芯片如何做到收发一体 既可以发送也可以接收 单独收发是没有问题的 软件SPI
[复制链接]
本帖最后由 沉睡毛毛虫 于 2024-11-22 18:10 编辑
#include "config.h" // Device header
#ifndef __USE_SOFT_SPI_INTERFACE__
/** 硬件SPI */
#define SPI_WAIT_TIMEOUT ((uint16_t)0xFFFF)
/**
* @brief :SPI初始化(硬件)
* @param :无
* @note :无
* @retval:无
*/
void drv_spi_init( void )
{
GPIO_InitTypeDef SpiGpioInitStructer;
SPI_InitTypeDef SpiInitStructer;
/** SPI引脚配置 */
RCC_APB2PeriphClockCmd(SPI_CLK_GPIO_CLK | SPI_MISO_GPIO_CLK | SPI_MOSI_GPIO_CLK | SPI_NSS_GPIO_CLK, ENABLE ); //打开端口时钟
//SCK MOSI MISO 配置为复用
SpiGpioInitStructer.GPIO_Speed = GPIO_Speed_10MHz;
SpiGpioInitStructer.GPIO_Mode = GPIO_Mode_AF_PP;
SpiGpioInitStructer.GPIO_Pin = SPI_CLK_GPIO_PIN;
GPIO_Init( SPI_CLK_GPIO_PORT, &SpiGpioInitStructer ); //初始化SCK
SpiGpioInitStructer.GPIO_Pin = SPI_MOSI_GPIO_PIN;
GPIO_Init( SPI_MOSI_GPIO_PORT, &SpiGpioInitStructer ); //初始化MOSI
SpiGpioInitStructer.GPIO_Pin = SPI_MISO_GPIO_PIN;
GPIO_Init( SPI_MISO_GPIO_PORT, &SpiGpioInitStructer ); //初始化MISO
//NSS配置为推挽输出
SpiGpioInitStructer.GPIO_Mode = GPIO_Mode_Out_PP;
SpiGpioInitStructer.GPIO_Pin = SPI_NSS_GPIO_PIN;
GPIO_Init( SPI_NSS_GPIO_PORT, &SpiGpioInitStructer ); //初始化NSS
GPIO_SetBits( SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PIN ); //置高
/** SPI配置 */
SPI_I2S_DeInit( SPI_PORT ); //复位SPI
if( SPI1 == SPI_PORT )
{
RCC_APB2PeriphClockCmd( SPI_PORT_CLK, ENABLE ); //SPI1在APB2上,打开相应SPI时钟
}
else
{
RCC_APB1PeriphClockCmd( SPI_PORT_CLK, ENABLE ); //SPI2 3在APB1上
}
SPI_Cmd( SPI_PORT, DISABLE ); //关闭SPI外设,配置前关闭
SpiInitStructer.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
SpiInitStructer.SPI_Mode = SPI_Mode_Master; //主机模式
SpiInitStructer.SPI_CPOL = SPI_CPOL_Low; //空闲状态为低电平
SpiInitStructer.SPI_CPHA = SPI_CPHA_1Edge; //第一个边沿采集数据
SpiInitStructer.SPI_DataSize = SPI_DataSize_8b; //8位数据
SpiInitStructer.SPI_NSS = SPI_NSS_Soft; //从机软件管理
SpiInitStructer.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //64分频
SpiInitStructer.SPI_FirstBit = SPI_FirstBit_MSB; //最高位先发送
SpiInitStructer.SPI_CRCPolynomial = 7; //CRC多项式,默认不使用SPI自带CRC
SPI_Init( SPI_PORT, &SpiInitStructer );
SPI_Cmd( SPI_PORT, ENABLE );
}
/**
* @brief :SPI收发一个字节
* @param :
* @TxByte: 发送的数据字节
* @note :非堵塞式,一旦等待超时,函数会自动退出
* @retval:接收到的字节
*/
uint8_t drv_spi_read_write_byte( uint8_t TxByte )
{
uint8_t l_Data = 0;
uint16_t l_WaitTime = 0;
while( RESET == SPI_I2S_GetFlagStatus( SPI_PORT, SPI_I2S_FLAG_TXE ) ) //等待发送缓冲区为空
{
if( SPI_WAIT_TIMEOUT == ++l_WaitTime )
{
break; //如果等待超时则退出
}
}
l_WaitTime = SPI_WAIT_TIMEOUT / 2; //重新设置接收等待时间(因为SPI的速度很快,正常情况下在发送完成之后会立即收到数据,等待时间不需要过长)
SPI_PORT->DR = TxByte; //发送数据
while( RESET == SPI_I2S_GetFlagStatus( SPI_PORT, SPI_I2S_FLAG_RXNE ) ) //等待接收缓冲区非空
{
if( SPI_WAIT_TIMEOUT == ++l_WaitTime )
{
break; //如果等待超时则退出
}
}
l_Data = (uint8_t)SPI_PORT->DR; //读取接收数据
return l_Data; //返回
}
/**
* @brief :SPI收发字符串
* @param :
* @ReadBuffer: 接收数据缓冲区地址
* @WriteBuffer:发送字节缓冲区地址
* @Length:字节长度
* @note :非堵塞式,一旦等待超时,函数会自动退出
* @retval:无
*/
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length )
{
GPIO_ResetBits( SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PIN); //拉低片选
while( Length-- )
{
*ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收发数据
ReadBuffer++;
WriteBuffer++; //读写地址加1
}
GPIO_SetBits( SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PIN); //拉高片选
}
/** 硬件SPI */
#endif
#ifdef __USE_SOFT_SPI_INTERFACE__
/** 软件SPI */
/**
* @brief :SPI初始化(软件)
* @param :无
* @note :无
* @retval:无
*/
void drv_spi_init( void )
{
GPIO_InitTypeDef SpiGpioInitStructer;
/** SPI引脚配置 */
RCC_APB2PeriphClockCmd( SPI_CLK_GPIO_CLK | SPI_MISO_GPIO_CLK | SPI_MOSI_GPIO_CLK | SPI_NSS_GPIO_CLK, ENABLE ); //打开端口时钟
//SCK MOSI NSS配置为推挽输出
SpiGpioInitStructer.GPIO_Speed = GPIO_Speed_10MHz;
SpiGpioInitStructer.GPIO_Mode = GPIO_Mode_Out_PP;
SpiGpioInitStructer.GPIO_Pin = SPI_CLK_GPIO_PIN;
GPIO_Init( SPI_CLK_GPIO_PORT, &SpiGpioInitStructer ); //初始化SCK
GPIO_ResetBits( SPI_CLK_GPIO_PORT, SPI_CLK_GPIO_PIN); //初始化状态设置为低
SpiGpioInitStructer.GPIO_Pin = SPI_MOSI_GPIO_PIN;
GPIO_Init( SPI_MOSI_GPIO_PORT, &SpiGpioInitStructer ); //初始化MOSI
GPIO_SetBits( SPI_MOSI_GPIO_PORT, SPI_MOSI_GPIO_PIN); //初始化状态设置为高
SpiGpioInitStructer.GPIO_Pin = SPI_NSS_GPIO_PIN;
GPIO_Init( SPI_NSS_GPIO_PORT, &SpiGpioInitStructer ); //初始化NSS
GPIO_SetBits( SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PIN); //初始化状态设置为高
//初始化MISO 上拉输入
SpiGpioInitStructer.GPIO_Mode = GPIO_Mode_IPU;
SpiGpioInitStructer.GPIO_Pin = SPI_MISO_GPIO_PIN;
GPIO_Init( SPI_MISO_GPIO_PORT, &SpiGpioInitStructer );
GPIO_SetBits( SPI_MISO_GPIO_PORT, SPI_MISO_GPIO_PIN); //初始化状态设置为高
}
/**
* @brief :SPI收发一个字节
* @param :
* @TxByte: 发送的数据字节
* @note :非堵塞式,一旦等待超时,函数会自动退出
* @retval:接收到的字节
*/
uint8_t drv_spi_read_write_byte( uint8_t TxByte )
{
uint8_t i = 0, Data = 0;
spi_set_clk_low( );
for( i = 0; i < 8; i++ ) //一个字节8byte需要循环8次
{
/** 发送 */
if( 0x80 == ( TxByte & 0x80 ))
{
spi_set_mosi_hight( ); //如果即将要发送的位为 1 则置高IO引脚
}
else
{
spi_set_mosi_low( ); //如果即将要发送的位为 0 则置低IO引脚
}
TxByte <<= 1; //数据左移一位,先发送的是最高位
spi_set_clk_high( ); //时钟线置高
__nop( );
__nop( );
/** 接收 */
Data <<= 1; //接收数据左移一位,先接收到的是最高位
if( 1 == spi_get_miso( ))
{
Data |= 0x01; //如果接收时IO引脚为高则认为接收到 1
}
spi_set_clk_low( ); //时钟线置低
__nop( );
__nop( );
}
return Data; //返回接收到的字节
}
/**
* @brief :SPI收发字符串
* @param :
* @ReadBuffer: 接收数据缓冲区地址
* @WriteBuffer:发送字节缓冲区地址
* @Length:字节长度
* @note :非堵塞式,一旦等待超时,函数会自动退出
* @retval:无
*/
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length )
{
spi_set_nss_low( ); //片选拉低
while( Length-- )
{
*ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收发数据
ReadBuffer++;
WriteBuffer++; //读写地址加1
}
spi_set_nss_high( ); //片选拉高
}
/** 软件SPI */
#endif
#ifndef __SPI_H
#define __SPI_H
//#define __CC1101_TX_TEST__ //**@@ 如果测试发送功能则需要定义该宏,如果测试接收则需要屏蔽该宏 **@@//
#define __USE_SOFT_SPI_INTERFACE__ //**@@ 如果使用软件SPI则需要定义该宏,反之如果使用硬件SPI则需要屏蔽该宏 **@@//
/** 发送模式定义 */
enum
{
TX_MODE_1 = 0, //发送模式1,发送固定的字符串
TX_MODE_2 //发送模式2,发送串口接收到的数据
};
//SPI引脚定义
#define SPI_CLK_GPIO_PORT GPIOA //PA5
#define SPI_CLK_GPIO_CLK RCC_APB2Periph_GPIOA
#define SPI_CLK_GPIO_PIN GPIO_Pin_5
#define SPI_MISO_GPIO_PORT GPIOA
#define SPI_MISO_GPIO_CLK RCC_APB2Periph_GPIOA //PA6
#define SPI_MISO_GPIO_PIN GPIO_Pin_6
#define SPI_MOSI_GPIO_PORT GPIOA
#define SPI_MOSI_GPIO_CLK RCC_APB2Periph_GPIOA //PA4
#define SPI_MOSI_GPIO_PIN GPIO_Pin_4
#define SPI_NSS_GPIO_PORT GPIOB
#define SPI_NSS_GPIO_CLK RCC_APB2Periph_GPIOB //PB1
#define SPI_NSS_GPIO_PIN GPIO_Pin_1
#define spi_set_nss_high( ) SPI_NSS_GPIO_PORT->ODR |= SPI_NSS_GPIO_PIN //片选置高
#define spi_set_nss_low( ) SPI_NSS_GPIO_PORT->ODR &= (uint32_t)( ~((uint32_t)SPI_NSS_GPIO_PIN )) //片选置低
#ifdef __USE_SOFT_SPI_INTERFACE__ /** 只有使用软件SPI才需要的封装 */
#define spi_set_clk_high( ) SPI_CLK_GPIO_PORT->ODR |= SPI_CLK_GPIO_PIN //时钟置高
#define spi_set_clk_low( ) SPI_CLK_GPIO_PORT->ODR &= (uint32_t)( ~((uint32_t)SPI_CLK_GPIO_PIN )) //时钟置低
#define spi_set_mosi_hight( ) SPI_MOSI_GPIO_PORT->ODR |= SPI_MOSI_GPIO_PIN //发送脚置高
#define spi_set_mosi_low( ) SPI_MOSI_GPIO_PORT->ODR &= (uint32_t)( ~((uint32_t)SPI_MOSI_GPIO_PIN )) //发送脚置低
#define spi_get_miso( ) (( SPI_MISO_GPIO_PORT->IDR & (uint32_t)SPI_MISO_GPIO_PIN) != SPI_MISO_GPIO_PIN ) ? 0 : 1 // 若相应输入位为低则得到0,相应输入位为高则得到1
void drv_spi_init( void );
uint8_t drv_spi_read_write_byte( uint8_t TxByte );
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length );
#else /** 只有使用硬件SPI时会使用 */
//SPI接口定义
#define SPI_PORT SPI2 //SPI接口
#define SPI_PORT_CLK RCC_APB1Periph_SPI2 //SPI时钟
void drv_spi_init( void );
uint8_t drv_spi_read_write_byte(uint8_t TxByte );
void drv_spi_read_write_string(uint8_t* ReadBuffer,uint8_t* WriteBuffer, uint16_t Length );
#endif
#endif
/**
******************************************************************************
* @author 泽耀科技 ASHINING
* @version V3.0
* @date 2016-10-08
* @brief NRF24L01配置C文件
******************************************************************************
* @attention
*
* 官网 : http://www.ashining.com
* 淘宝 : https://shop105912646.taobao.com
* 阿里巴巴: https://cdzeyao.1688.com
******************************************************************************
*/
#include "config.h"
//10, 7, 5, 0, -5, -10, -15, -20, dbm output power, 0x12 == -30dbm
//const uint8_t PaTabel[ ] = { 0xc0, 0xC8, 0x84, 0x60, 0x68, 0x34, 0x1D, 0x0E};
const uint8_t PaTabel[ ] = { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
static const uint8_t CC1101InitData[ 22 ][ 2 ]=
{
{ CC1101_IOCFG0, 0x06 },
{ CC1101_FIFOTHR, 0x47 },
{ CC1101_PKTCTRL0, 0x05 },
{ CC1101_CHANNR, 0x96 }, //430M
{ CC1101_FSCTRL1, 0x06 },
{ CC1101_FREQ2, 0x0F },
{ CC1101_FREQ1, 0x62 },
{ CC1101_FREQ0, 0x76 },
{ CC1101_MDMCFG4, 0xF6 },
{ CC1101_MDMCFG3, 0x43 },
{ CC1101_MDMCFG2, 0x13 },
{ CC1101_DEVIATN, 0x15 },
{ CC1101_MCSM0, 0x18 },
{ CC1101_FOCCFG, 0x16 },
{ CC1101_WORCTRL, 0xFB },
{ CC1101_FSCAL3, 0xE9 },
{ CC1101_FSCAL2, 0x2A },
{ CC1101_FSCAL1, 0x00 },
{ CC1101_FSCAL0, 0x1F },
{ CC1101_TEST2, 0x81 },
{ CC1101_TEST1, 0x35 },
{ CC1101_MCSM1, 0x3B },
};
/**
* @brief :CC1101写命令
* @param :
* @Command:命令
* @note :无
* @retval:无
*/
void CC1101_Write_Cmd( uint8_t Command )
{
CC1101_SET_CSN_LOW( ); //SPI片选,本工程中该函数都是用作SPI片选
drv_spi_read_write_byte( Command ); //写命令
CC1101_SET_CSN_HIGH( ); //SPI取消片选,本工程中该函数都是用作取消SPI片选
}
/**
* @brief :CC1101写寄存器
* @param :
* @Addr:地址
* @WriteValue:写入的数据字节
* @note :无
* @retval:无
*/
void CC1101_Write_Reg( uint8_t Addr, uint8_t WriteValue )
{
CC1101_SET_CSN_LOW( );
drv_spi_read_write_byte( Addr ); //写地址
drv_spi_read_write_byte( WriteValue ); //写数据
CC1101_SET_CSN_HIGH( );
}
/**
* @brief :CC1101连续写寄存器
* @param :
* @Addr:地址
* @pWriteBuff:写入的数据串首地址
* @WriteSize:写入的数据个数
* @note :无
* @retval:无
*/
void CC1101_Write_Multi_Reg( uint8_t Addr, uint8_t *pWriteBuff, uint8_t WriteSize )
{
uint8_t i;
CC1101_SET_CSN_LOW( );
drv_spi_read_write_byte( Addr | WRITE_BURST ); //连续写命令 及首地址
for( i = 0; i < WriteSize; i ++ )
{
drv_spi_read_write_byte( *( pWriteBuff + i ) ); //连续写入数据
}
CC1101_SET_CSN_HIGH( );
}
/**
* @brief :CC1101读寄存器
* @param :
* @Addr:地址
* @note :无
* @retval:寄存器值
*/
uint8_t CC1101_Read_Reg( uint8_t Addr )
{
uint8_t l_RegValue = 0;
CC1101_SET_CSN_LOW( );
drv_spi_read_write_byte( Addr | READ_SINGLE ); //单独读命令 及地址
l_RegValue = drv_spi_read_write_byte( 0xFF ); //读取寄存器
CC1101_SET_CSN_HIGH( );
return l_RegValue;
}
/**
* @brief :CC1101读一个寄存器状态
* @param :
* @Addr:地址
* @note :无
* @retval:寄存器状态
*/
uint8_t CC1101_Read_Status( uint8_t Addr )
{
uint8_t l_RegStatus = 0;
CC1101_SET_CSN_LOW( );
drv_spi_read_write_byte( Addr | READ_BURST ); //连续读命令 及地址
l_RegStatus = drv_spi_read_write_byte( 0xFF ); //读取状态
CC1101_SET_CSN_HIGH( );
return l_RegStatus;
}
/**
* @brief :CC1101连续读寄存器
* @param :
* @Addr:地址
* @pReadBuff:读取数据存放首地址
* @ReadSize:读取数据的个数
* @note :无
* @retval:无
*/
void CC1101_Read_Multi_Reg( uint8_t Addr, uint8_t *pReadBuff, uint8_t ReadSize )
{
uint8_t i = 0, j = 0;
CC1101_SET_CSN_LOW( );
drv_spi_read_write_byte( Addr | READ_BURST); //连续读命令 及首地址
for( i = 0; i < ReadSize; i ++ )
{
for( j = 0; j < 20; j ++ );
*( pReadBuff + i ) = drv_spi_read_write_byte( 0xFF ); //连续读取数据
}
CC1101_SET_CSN_HIGH( );
}
/**
* @brief :CC1101发送接收模式设置
* @param :
* @Mode:TX_MODE,发送模式 RX_MODE,接收模式
* @note :无
* @retval:寄存器状态
*/
void CC1101_Set_Mode( CC1101_ModeType Mode )
{
if( Mode == TX_MODE ) //发送模式
{
CC1101_Write_Reg(CC1101_IOCFG0,0x46);
CC1101_Write_Cmd(CC1101_STX );
}
else if(Mode== RX_MODE) //接收模式
{
CC1101_Write_Reg(CC1101_IOCFG0,0x46);
CC1101_Write_Cmd(CC1101_SRX );
}
while(0!=CC1101_GET_GDO0_STATUS( )); //等待发送 或 接收开始
}
/**
* @brief :CC1101进入空闲模式
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Set_Idle_Mode( void )
{
CC1101_Write_Cmd( CC1101_SIDLE );
}
/**
* @brief :CC1101初始化WOR功能
* @param :无
* @note :无
* @retval:无
*/
void C1101_WOR_Init( void )
{
CC1101_Write_Reg(CC1101_MCSM0,0x18);
CC1101_Write_Reg(CC1101_WORCTRL,0x78);
CC1101_Write_Reg(CC1101_MCSM2,0x00);
CC1101_Write_Reg(CC1101_WOREVT1,0x8C);
CC1101_Write_Reg(CC1101_WOREVT0,0xA0);
CC1101_Write_Cmd( CC1101_SWORRST ); //写入WOR命令
}
/**
* @brief :CC1101设置地址
* @param :
* @Address:设置的设备地址值
* @AddressMode:地址检测模式
* @note :无
* @retval:无
*/
void CC1101_Set_Address( uint8_t Address, CC1101_AddrModeType AddressMode)
{
uint8_t btmp = 0;
btmp = CC1101_Read_Reg( CC1101_PKTCTRL1 ) & ~0x03; //读取CC1101_PKTCTRL1寄存器初始值
CC1101_Write_Reg( CC1101_ADDR, Address ); //设置设备地址
if( AddressMode == BROAD_ALL ) { } //不检测地址
else if( AddressMode == BROAD_NO )
{
btmp |= 0x01; //检测地址 但是不带广播
}
else if( AddressMode == BROAD_0 )
{
btmp |= 0x02; //0x00为广播
}
else if( AddressMode == BROAD_0AND255 )
{
btmp |= 0x03; //0x00 0xFF为广播
}
CC1101_Write_Reg( CC1101_PKTCTRL1, btmp); //写入地址模式
}
/**
* @brief :CC1101设置同步字段
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Set_Sync( uint16_t Sync )
{
CC1101_Write_Reg( CC1101_SYNC1, 0xFF & ( Sync >> 8 ) );
CC1101_Write_Reg( CC1101_SYNC0, 0xFF & Sync ); //写入同步字段 16Bit
}
/**
* @brief :CC1101清空发送缓冲区
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Clear_TxBuffer( void )
{
CC1101_Set_Idle_Mode( ); //首先进入IDLE模式
CC1101_Write_Cmd(CC1101_SFTX); //写入清发送缓冲区命令
}
/**
* @brief :CC1101清空接收缓冲区
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Clear_RxBuffer( void )
{
CC1101_Set_Idle_Mode(); //首先进入IDLE模式
CC1101_Write_Cmd(CC1101_SFRX ); //写入清接收缓冲区命令
}
/**
* @brief :CC1101发送数据包
* @param :
* @pTxBuff:发送数据缓冲区
* @TxSize:发送数据长度
* @DataMode:数据模式
* @note :无
* @retval:无
*/
void CC1101_Tx_Packet(uint8_t *pTxBuff, uint8_t TxSize, CC1101_TxDataModeType DataMode )
{
uint8_t Address;
uint16_t l_RxWaitTimeout = 0;
if( DataMode == BROADCAST )
{
Address = 0;
}
else if( DataMode == ADDRESS_CHECK )
{
Address = CC1101_Read_Reg( CC1101_ADDR );
}
CC1101_Clear_TxBuffer( );
if(( CC1101_Read_Reg(CC1101_PKTCTRL1) & 0x03 ) != 0 )
{
CC1101_Write_Reg(CC1101_TXFIFO,TxSize + 1 );
CC1101_Write_Reg(CC1101_TXFIFO,Address ); //写入长度和地址 由于多一个字节地址此时长度应该加1
}
else
{
CC1101_Write_Reg( CC1101_TXFIFO, TxSize ); //只写长度 不带地址
}
CC1101_Write_Multi_Reg( CC1101_TXFIFO, pTxBuff, TxSize ); //写入数据
CC1101_Set_Mode(TX_MODE); //发送模式
while( 0 == CC1101_GET_GDO0_STATUS( )) //等待发送完成
{
delay_ms( 1 );
if(1000 == l_RxWaitTimeout++ )
{
l_RxWaitTimeout = 0;
CC1101_Init( );
break;
}
}
}
/**
* @brief :CC1101读取接收到的字节数
* @param :无
* @note :无
* @retval:接收到的数据个数
*/
uint8_t CC1101_Get_RxCounter( void )
{
return ( CC1101_Read_Status( CC1101_RXBYTES ) & BYTES_IN_RXFIFO );
}
/**
* @brief :CC1101接收数据包
* @param :
* @RxBuff:发送数据缓冲区
* @note :无
* @retval:接收到的字节数,0表示无数据
*/
uint8_t CC1101_Rx_Packet(uint8_t *RxBuff )
{
uint8_t l_PktLen = 0;
uint8_t l_Status[ 2 ] = { 0 };
uint16_t l_RxWaitTimeout = 0;
while(0==CC1101_GET_GDO0_STATUS( )) //等待接收完成
{
delay_ms(1);
if( 3000 == l_RxWaitTimeout++ )
{
l_RxWaitTimeout = 0;
CC1101_Init( );
break;
}
}
if(0!= CC1101_Get_RxCounter( ))
{
l_PktLen = CC1101_Read_Reg( CC1101_RXFIFO ); // 获取长度信息
if( ( CC1101_Read_Reg( CC1101_PKTCTRL1 ) & 0x03 ) != 0 )
{
CC1101_Read_Reg( CC1101_RXFIFO ); //如果数据包中包含地址信息 ,则读取地址信息
}
if( l_PktLen == 0 )
{
return 0; //无数据
}
else
{
l_PktLen--; //减去一个地址字节
}
CC1101_Read_Multi_Reg( CC1101_RXFIFO, RxBuff, l_PktLen ); //读取数据
CC1101_Read_Multi_Reg( CC1101_RXFIFO, l_Status, 2 ); //读取数据包最后两个额外字节,后一个为CRC标志位
CC1101_Clear_RxBuffer( );
if( l_Status[ 1 ] & CRC_OK )
{
return l_PktLen;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
/**
* @brief :CC1101复位
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Reset( void )
{
CC1101_SET_CSN_HIGH( );
CC1101_SET_CSN_LOW( );
CC1101_SET_CSN_HIGH( );
delay_us(40);
CC1101_Write_Cmd(CC1101_SRES);
}
/**
* @brief :CC1101引脚初始化
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Gpio_Init( void )
{
GPIO_InitTypeDef GpioInitStructer;
//使能口线时钟
RCC_APB2PeriphClockCmd(CC1101_GDO0_GPIO_CLK|CC1101_GDO2_GPIO_CLK, ENABLE ); //打开端口时钟
//GDO0 GDO2配置为上拉输入
GpioInitStructer.GPIO_Speed = GPIO_Speed_10MHz;
GpioInitStructer.GPIO_Mode = GPIO_Mode_IPU;
GpioInitStructer.GPIO_Pin = CC1101_GDO0_GPIO_PIN;
GPIO_Init( CC1101_GDO0_GPIO_PORT, &GpioInitStructer );
GpioInitStructer.GPIO_Pin = CC1101_GDO2_GPIO_PIN;
GPIO_Init( CC1101_GDO2_GPIO_PORT, &GpioInitStructer );
}
/**
* @brief :CC1101初始化
* @param :无
* @note :无
* @retval:无
*/
void CC1101_Init( void )
{
uint8_t i = 0;
CC1101_Gpio_Init( ); //引脚初始化
CC1101_Reset( ); //模块复位
for( i = 0; i < 22; i++ )
{
CC1101_Write_Reg( CC1101InitData[0], CC1101InitData[1] ); //写入配置参数
}
CC1101_Set_Address( 0x05, BROAD_0AND255 ); //写入设备地址 和地址模式
CC1101_Set_Sync( 0x8799 ); //写入同步字段
CC1101_Write_Reg(CC1101_MDMCFG1, 0x72 ); //调制解调器配置
CC1101_Write_Multi_Reg(CC1101_PATABLE,(uint8_t*)PaTabel,8);
}
/**
******************************************************************************
* @author 泽耀科技 ASHINING
* @version V3.0
* @date 2016-10-08
* @brief NRF24L01配置H文件
******************************************************************************
* @attention
*
* 官网 : http://www.ashining.com
* 淘宝 : https://shop105912646.taobao.com
* 阿里巴巴: https://cdzeyao.1688.com
******************************************************************************
*/
#ifndef __CC1101_H__
#define __CC1101_H__
#define PA_TABLE {0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}
/** CC1101硬件接口定义 */
#define CC1101_GDO0_GPIO_PORT GPIOB //PB0
#define CC1101_GDO0_GPIO_CLK RCC_APB2Periph_GPIOB
#define CC1101_GDO0_GPIO_PIN GPIO_Pin_0
#define CC1101_GDO2_GPIO_PORT GPIOA //PA7
#define CC1101_GDO2_GPIO_CLK RCC_APB2Periph_GPIOA
#define CC1101_GDO2_GPIO_PIN GPIO_Pin_7
#define CC1101_CSN_GPIO_PORT SPI_NSS_GPIO_PORT //PB1
#define CC1101_CSN_GPIO_CLK SPI_NSS_GPIO_CLK
#define CC1101_CSN_GPIO_PIN SPI_NSS_GPIO_PIN
/** 口线操作函数定义 */
#define CC1101_SET_CSN_HIGH( ) spi_set_nss_high( )
#define CC1101_SET_CSN_LOW( ) spi_set_nss_low( )
#define CC1101_GET_GDO0_STATUS( ) (( CC1101_GDO0_GPIO_PORT->IDR & (uint32_t)CC1101_GDO0_GPIO_PIN) != CC1101_GDO0_GPIO_PIN ) ? 0 : 1 //GDO0状态
#define CC1101_GET_GDO2_STATUS( ) (( CC1101_GDO2_GPIO_PORT->IDR & (uint32_t)CC1101_GDO2_GPIO_PIN) != CC1101_GDO2_GPIO_PIN ) ? 0 : 1 //GDO2状态
/** 枚举量定义 */
typedef enum
{
TX_MODE,
RX_MODE
}CC1101_ModeType;
typedef enum
{
BROAD_ALL,
BROAD_NO,
BROAD_0,
BROAD_0AND255
}CC1101_AddrModeType;
typedef enum
{
BROADCAST,
ADDRESS_CHECK
} CC1101_TxDataModeType;
void CC1101_Write_Cmd( uint8_t Command );
void CC1101_Write_Reg( uint8_t Addr, uint8_t WriteValue );
void CC1101_Write_Multi_Reg( uint8_t Addr, uint8_t *pWriteBuff, uint8_t WriteSize );
uint8_t CC1101_Read_Reg( uint8_t Addr );
void CC1101_Read_Multi_Reg( uint8_t Addr, uint8_t *pReadBuff, uint8_t ReadSize );
uint8_t CC1101_Read_Status( uint8_t Addr );
void CC1101_Set_Mode( CC1101_ModeType Mode );
void CC1101_Set_Idle_Mode( void );
void C1101_WOR_Init( void );
void CC1101_Set_Address( uint8_t Address, CC1101_AddrModeType AddressMode);
void CC1101_Set_Sync( uint16_t Sync );
void CC1101_Clear_TxBuffer( void );
void CC1101_Clear_RxBuffer( void );
void CC1101_Tx_Packet( uint8_t *pTxBuff, uint8_t TxSize, CC1101_TxDataModeType DataMode );
uint8_t CC1101_Get_RxCounter( void );
uint8_t CC1101_Rx_Packet( uint8_t *RxBuff );
void CC1101_Reset( void );
void CC1101_Init( void );
void CC1101_Gpio_Init( void );
#endif
/**
******************************************************************************
* @author 泽耀科技 ASHINING
* @version V3.0
* @date 2016-10-08
* @brief CC1101寄存器 命令定义H文件
******************************************************************************
* @attention
*
* 官网 : http://www.ashining.com
* 淘宝 : https://shop105912646.taobao.com
* 阿里巴巴: https://cdzeyao.1688.com
******************************************************************************
*/
#ifndef __DRV_CC1101_REG_H__
#define __DRV_CC1101_REG_H__
/** CC1101寄存器定义 */
#define CC1101_IOCFG2 0x00 // GDO2 output pin configuration
#define CC1101_IOCFG1 0x01 // GDO1 output pin configuration
#define CC1101_IOCFG0 0x02 // GDO0 output pin configuration
#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds
#define CC1101_SYNC1 0x04 // Sync word, high INT8U
#define CC1101_SYNC0 0x05 // Sync word, low INT8U
#define CC1101_PKTLEN 0x06 // Packet length
#define CC1101_PKTCTRL1 0x07 // Packet automation control
#define CC1101_PKTCTRL0 0x08 // Packet automation control
#define CC1101_ADDR 0x09 // Device address
#define CC1101_CHANNR 0x0A // Channel number
#define CC1101_FSCTRL1 0x0B // Frequency synthesizer control
#define CC1101_FSCTRL0 0x0C // Frequency synthesizer control
#define CC1101_FREQ2 0x0D // Frequency control word, high INT8U
#define CC1101_FREQ1 0x0E // Frequency control word, middle INT8U
#define CC1101_FREQ0 0x0F // Frequency control word, low INT8U
#define CC1101_MDMCFG4 0x10 // Modem configuration
#define CC1101_MDMCFG3 0x11 // Modem configuration
#define CC1101_MDMCFG2 0x12 // Modem configuration
#define CC1101_MDMCFG1 0x13 // Modem configuration
#define CC1101_MDMCFG0 0x14 // Modem configuration
#define CC1101_DEVIATN 0x15 // Modem deviation setting
#define CC1101_MCSM2 0x16 // Main Radio Control State Machine configuration
#define CC1101_MCSM1 0x17 // Main Radio Control State Machine configuration
#define CC1101_MCSM0 0x18 // Main Radio Control State Machine configuration
#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation configuration
#define CC1101_BSCFG 0x1A // Bit Synchronization configuration
#define CC1101_AGCCTRL2 0x1B // AGC control
#define CC1101_AGCCTRL1 0x1C // AGC control
#define CC1101_AGCCTRL0 0x1D // AGC control
#define CC1101_WOREVT1 0x1E // High INT8U Event 0 timeout
#define CC1101_WOREVT0 0x1F // Low INT8U Event 0 timeout
#define CC1101_WORCTRL 0x20 // Wake On Radio control
#define CC1101_FREND1 0x21 // Front end RX configuration
#define CC1101_FREND0 0x22 // Front end TX configuration
#define CC1101_FSCAL3 0x23 // Frequency synthesizer calibration
#define CC1101_FSCAL2 0x24 // Frequency synthesizer calibration
#define CC1101_FSCAL1 0x25 // Frequency synthesizer calibration
#define CC1101_FSCAL0 0x26 // Frequency synthesizer calibration
#define CC1101_RCCTRL1 0x27 // RC oscillator configuration
#define CC1101_RCCTRL0 0x28 // RC oscillator configuration
#define CC1101_FSTEST 0x29 // Frequency synthesizer calibration control
#define CC1101_PTEST 0x2A // Production test
#define CC1101_AGCTEST 0x2B // AGC test
#define CC1101_TEST2 0x2C // Various test settings
#define CC1101_TEST1 0x2D // Various test settings
#define CC1101_TEST0 0x2E // Various test settings
// 命令
#define CC1101_SRES 0x30 // Reset chip.
#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
// If in RX/TX: Go to a wait state where only the synthesizer is
// running (for quick RX / TX turnaround).
#define CC1101_SXOFF 0x32 // Turn off crystal oscillator.
#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off
// (enables quick start).
#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and
// MCSM0.FS_AUTOCAL=1.
#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if
// MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled:
// Only go to TX if channel is clear.
#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit
// Wake-On-Radio mode if applicable.
#define CC1101_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer
#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio)
#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high.
#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer.
#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer.
#define CC1101_SWORRST 0x3C // Reset real time clock.
#define CC1101_SNOP 0x3D // No operation. May be used to pad strobe commands to two
// INT8Us for simpler software.
#define CC1101_PARTNUM 0x30
#define CC1101_VERSION 0x31
#define CC1101_FREQEST 0x32
#define CC1101_LQI 0x33
#define CC1101_RSSI 0x34
#define CC1101_MARCSTATE 0x35
#define CC1101_WORTIME1 0x36
#define CC1101_WORTIME0 0x37
#define CC1101_PKTSTATUS 0x38
#define CC1101_VCO_VC_DAC 0x39
#define CC1101_TXBYTES 0x3A
#define CC1101_RXBYTES 0x3B
#define CC1101_PATABLE 0x3E
#define CC1101_TXFIFO 0x3F
#define CC1101_RXFIFO 0x3F
#define WRITE_BURST 0x40 //写多个
#define READ_SINGLE 0x80 //读单个
#define READ_BURST 0xC0 //读多个
#define BYTES_IN_RXFIFO 0x7F //接收缓冲区有效字节
#define CRC_OK 0x80 //CRC校验通过标志位
#endif
/*********************************************************************************
* 模块名称 :
* 文件名称 :
* 版 本 : V1.0
* 说 明 :
*
* 修改记录 :
* 日期 作者 说明
* Copyright (C), 2020-2030,
*
***********************************************************************************/
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永无BUG 永不修改 //
////////////////////////////////////////////////////////////////////
/* USER CODE END Header
编写说明:
******************************************************************************/
/*******************************************************************************
//更新日志
********************************************************************************/
#include "config.h"
const char *g_Ashining = "88888888";
uint8_t g_RF24L01RxBuffer[ 32 ] = { 0 };
int main(void)
{
u16 i=0;
delay_init(); //初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
TIM_Init(); //初始化
KEY_Init(); //初始化
LED_Init();
uart_init(115200); //9位数据 TXD上传上位机指令
uart2_init(115200); //8位数据 RXD上位机指令
//SPI初始化
drv_spi_init( );
//CC1101初始化
//CC1101_Init( );
for( i = 0; i < 6; i++ )
{
led_red_flashing( );
led_green_flashing( );
delay_ms(500);
}
while(1)
{
// CC1101_Tx_Packet((uint8_t *)g_Ashining,8,ADDRESS_CHECK ); //模式1发送固定字符,1S一包
// delay_ms(500);
// delay_ms(500);
// led_red_flashing( );
// CC1101_Clear_RxBuffer( );
// CC1101_Set_Mode(RX_MODE );
// i = CC1101_Rx_Packet(g_RF24L01RxBuffer); //接收字节
// if(0!=i)
// {
// led_green_flashing( );
// uart_send_string(g_RF24L01RxBuffer,i); //输出接收到的字节
// }
}
}
|