ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

基于Linux和4412处理器实现SPI接口的RF控制

2021-10-07 16:02:18  阅读:204  来源: 互联网

标签:spifd int 4412 SPI RF uChar buf define


         本文介绍了基于4412(4核,cotex-A9)和Linux,基于SPI接口控制RF无线模块,代码和分析总结如下,便于以后查阅,只要是ARM-LINUX平台都可以参考:

#include "spiRf2401.h"

int spiOpen(void)
{
	int spifd=0;
	spifd = open("/dev/spidev0.0", O_RDWR);
	
	if ( spifd < 0 ) 
	{
		return -1;
	}
	else
	{
		return spifd;
	}
}

int gpioOpen(void)
{
	int gpiofd=0;
	gpiofd = open("/dev/use_gpio_0", O_RDWR);
	if ( gpiofd < 0 ) 
	{
		return -1;
	}
	else
	{
		return gpiofd;
	}
}

void spiClose(int spifd)
{
	close(spifd);
	printf("spi close\n");
}

void gpioClose(int gpiofd)
{
	close(gpiofd);
	printf("gpiofd close\n");
}

int spiSet(int fd)
{
	int ret = 0;
    uChar mode=0, mode1=0;
    uChar bits = 8, bits1=0;
    uint32_t speed = 4000000, speed1=0;  //4MHz

	// spi mode
	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
	if (ret == -1)
	{
		printf("can't set spi mode\n");
		return -1;
	}
	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode1);
	if (ret == -1)
	{
		printf("can't get spi mode\n");
		//return -1;
	}
	
	
	// bits per word
	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
	if (ret == -1)
	{
		printf("can't set bits per word\n");
		return -1;
	}
	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits1);
	if (ret == -1)
	{
		printf("can't get bits per word\n");
		//return -1;
	}
	// max speed hz
	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	if (ret == -1)
	{
		printf("can't set max speed hz\n");
		return -1;
	}
	
	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed1);
	if (ret == -1)
	{
		printf("can't get max speed hz\n");
		//return -1;
	}
    printf("spi mode: %d\n", mode1);
    printf("bits per word: %d\n", bits1);
    printf("max speed: %d Hz (%d KHz)\n", speed1, speed1/1000);
    printf("spi_set(): OK \n");
	return 0;
}

void nRF24L01Init(int gpiofd)
{
	//CSN_1
	//SCLK_0
	//IRQ_1
	
    ioctl(gpiofd, 12, 0);   //spi0
    //ioctl(gpiofd, 13, 0);  //spi1
    //printf("nRF24L01_init(): OK \n");
}

int SCSPI_Write_TX_ADDR_reg(int spifd,uChar reg, uChar *pBuf, uChar len)
{
	int status;
	uChar i, j;
	struct spi_ioc_transfer transfer_data[1];
	uChar	W_buf[32], R_buf[32];
	
	if (len > ((sizeof(W_buf)) - 1))
    {
        len = (sizeof(W_buf)) - 1;
    }
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
 
	W_buf[0] = reg;
	
	for(i=1,j=0; j<len; i++,j++) {
		W_buf[i] = pBuf[j];
	}
	
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = len + 1;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SCSPI_Write_TX_ADDR_reg():SPI_IOC_MESSAGE");
		return -1;
	}
	
	return 0;
}


int SCSPI_Read_TX_ADDR_reg(int spifd,uChar reg, uChar *pBuf, uChar len)
{
	int status, i = 0;
	struct spi_ioc_transfer transfer_data[1];
	uChar	W_buf[32], R_buf[32];
	
	if (len > ((sizeof(W_buf)) - 1))
    {
        len = (sizeof(W_buf)) - 1;
    }
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
	
	W_buf[0] = reg;
	for(i=1; i<len+1; i++)
	{
		W_buf[i] = 0xff;
	}
	
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = len + 1;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SCSPI_Read_TX_ADDR_reg():SPI_IOC_MESSAGE");
		return -1;
	}
	
	for(i=0; i<(len+1); i++)
	{
		pBuf[i] = R_buf[i+1];  //R_buf[0] is the return flag
	}
	return 0;
}
 
int rfBeginTransfer(int spifd,uChar value,uChar *pBuf1)
{
	int status;
	struct spi_ioc_transfer transfer_data[1];
	uChar	W_buf[2]={0,0}, R_buf[2]={0,0};
	
	memset(transfer_data, 0, sizeof transfer_data);
	
	W_buf[0] = value;
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = 1;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("rfBeginTransfer():SPI_IOC_MESSAGE");
		return -1;
	}
	
	pBuf1[0] = R_buf[0]; 
	pBuf1[1] = R_buf[1]; 
	
	return 0;
}

/**********************************************************************
* 函数名称 : NRF24L01_SelCheck_Exist
*  函数功能 : 判断NRF24L01是否存在或损坏,
*             方法: 向NRF24L01写5个数据然后再读回来进行比较,
*                   相同时返回值:1,表示存在;否则返回0,表示不存在。
**********************************************************************/
int  nRF2401SelfCheckExist(int spifd)
{
	  uChar  selfCheck_buf_0[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
	  uChar  selfCheck_buf_1[5]={0,0,0,0,0};
	  uChar  i;

	  SCSPI_Write_TX_ADDR_reg(spifd,SCWRITE_REG+SCTX_ADDR, selfCheck_buf_0, 5);
	  SCSPI_Read_TX_ADDR_reg(spifd,SCREAD_REG+SCTX_ADDR, selfCheck_buf_1, 5);
	 
	  for( i = 0 ; i < 5 ; i++ )
	  {
		  printf("selfCheck_buf_1[%d]=%#x\n",i,selfCheck_buf_1[ i ]);
		  if( selfCheck_buf_1[ i ] != 0xA5 )
		  {
			  break;					   
		  }
	  }

	  if( i == 5 )
	  {
		  return 0 ; 
	  }
	  else
	  {
		  return -1 ; 
	  }

}	


/*
  待机模式Ⅰ:
  (1)处于上电状态
  (2)不管是发送还是接收模式,只要CE为低电平,此时进入待机模式Ⅰ
  (3)此时无数据传输
  待机模式Ⅱ:
  (1)处于上电状态
  (2)处于发送模式,即PRIM_RX位为0
  (3)发送端TX FIFO寄存器为空,并且CE为高电平时进入待机模式Ⅱ
  其他注意:
  (1)在待机模式期间,配置寄存器内存保持不变
  (2)根据RF芯片手册的时序说明,掉电模式到待机模式的转换时间最长不能超过1.5ms,
       最小无限制,待机模式到发送/接收模式最大不能超过130us
  (3)CE高电平持续时间不能少于10us
  (4)CSN为低电平,CE上升沿的延迟时间不能少于4us
  (5)RF在掉电模式转入发射模式或接收模式前必须经过1.5ms的待机模式
 */
void TX_Mode(int gpiofd,int spifd,uChar *addr,uChar * txBuf)
{	
	//CE_0;	 待机模式Ⅰ开始
    ioctl(gpiofd, XEINT12_B, LOW);

	SPI_Write_Reg(spifd,WRITE_REG+CONFIG, 0x0e);
	SPI_Write_Reg(spifd,FLUSH_TX, 0xff);
	
	SPI_Write_Buf(spifd,WRITE_REG+TX_ADDR, addr, TX_ADR_WIDTH);
	SPI_Write_Buf(spifd,WRITE_REG+RX_ADDR_P0, addr, RX_ADR_WIDTH);
	SPI_Write_Buf(spifd,WR_TX_PLOAD,txBuf,TX_PLOAD_WIDTH);//装入数据
	
	SPI_Write_Reg(spifd,WRITE_REG+EN_AA, 0x01);
	SPI_Write_Reg(spifd,WRITE_REG+EN_RXADDR, 0x01);
	SPI_Write_Reg(spifd,WRITE_REG+SETUP_RETR, 0x3F);
	SPI_Write_Reg(spifd,WRITE_REG+RF_CH, 0x70);//频段为0x70
	SPI_Write_Reg(spifd,WRITE_REG+RF_SETUP, 0x0f);
	SPI_Write_Reg(spifd,WRITE_REG+SETUP_AW, 0x03);
	
	//CE_1;	 待机模式Ⅰ结束
    ioctl(gpiofd, XEINT12_B, HIGH);//启动发送 高电平保持时间>10us
}
 

void RX_Mode(int gpiofd,int spifd,uChar *addr)
{
	//CE_0;   进入待机Ⅰ模式
    ioctl(gpiofd, XEINT12_B, LOW);
	
	SPI_Write_Reg(spifd,WRITE_REG+CONFIG, 0x0F);
	SPI_Write_Reg(spifd,FLUSH_RX, 0xff);
	
	SPI_Write_Buf(spifd,WRITE_REG+RX_ADDR_P0, addr, RX_ADR_WIDTH); 
	
	SPI_Write_Reg(spifd,WRITE_REG+EN_AA, 0x01);
	SPI_Write_Reg(spifd,WRITE_REG+EN_RXADDR, 0x01);
	SPI_Write_Reg(spifd,WRITE_REG+RF_CH, 0x70);
	SPI_Write_Reg(spifd,WRITE_REG+RX_PW_P0, RX_PLOAD_WIDTH);
	SPI_Write_Reg(spifd,WRITE_REG+RF_SETUP, 0x0f);
	SPI_Write_Reg(spifd,WRITE_REG+SETUP_AW, 0x03);
	
	//CE_1;
    ioctl(gpiofd,XEINT12_B, HIGH);//启动接收模式
	//usleep(160);  //>130us,from rf datasheet 
}


int SPI_Write_Reg(int spifd,uChar reg,uChar value)
{
	int status;
	struct spi_ioc_transfer transfer_data[1];
	uint8_t	W_buf[2], R_buf[2];
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
	
	W_buf[0] = reg;
	W_buf[1] = value;
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = 2;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SPI_Write_Reg():SPI_IOC_MESSAGE\n");
		return -1;
	}
	
	return 0;
}


int SPI_Read_Reg(int spifd,uChar reg,uChar *buf)
{
	int status;
	struct spi_ioc_transfer transfer_data[1];
	uint8_t	W_buf[2], R_buf[2];
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
	
	W_buf[0] = reg;
	W_buf[1] = 0xff;
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = 2;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SPI_Read_Reg():SPI_IOC_MESSAGE\n");
		return -1;
	}
	memcpy(buf, R_buf, sizeof(R_buf));
	return 0;
}


int SPI_Write_Buf(int spifd,uChar reg, uChar *pBuf, uChar len)
{
	int status;
	uChar i, j;
	struct spi_ioc_transfer transfer_data[1];
	uChar	W_buf[32], R_buf[32];
	
	
	if (len > ((sizeof(W_buf)) - 1))
    {
        len = (sizeof(W_buf)) - 1;
    }
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
 
	W_buf[0] = reg;
	
	for(i=1,j=0; j<len; i++,j++) {
		W_buf[i] = pBuf[j];
	}
	
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = len + 1;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SPI_Write_Buf():SPI_IOC_MESSAGE\n");
		return -1;
	}
	
	return 0;
}


int SPI_Read_Buf(int spifd,uChar reg, uChar *pBuf, uChar len)
{
	int status, i = 0;
	struct spi_ioc_transfer transfer_data[1];
	uint8_t	W_buf[32], R_buf[32];
	
	if (len > ((sizeof(W_buf)) - 1))
    {
        len = (sizeof(W_buf)) - 1;
    }
	
	memset(transfer_data, 0, sizeof transfer_data);
	memset(W_buf, 0, sizeof W_buf);
	memset(R_buf, 0, sizeof R_buf);
	
	W_buf[0] = reg;
	for(i=1; i<len+1; i++)
	{
		W_buf[i] = 0xff;
	}
	
	transfer_data[0].tx_buf = (unsigned long)W_buf;
	transfer_data[0].rx_buf = (unsigned long)R_buf;
	transfer_data[0].len = len + 1;
	
    status = ioctl(spifd, SPI_IOC_MESSAGE(1), transfer_data);
	if (status < 0) 
	{
		perror("SPI_Read_Buf():SPI_IOC_MESSAGE\n");
		return -1;
	}
	
	for(i=0; i<(len+1); i++)
	{
		pBuf[i] = R_buf[i+1];  //R_buf[0] is the return flag
	}
	return 0;
}

int RF_Send_to_MSub(int spifd)
{	
	int loop = 0;
	uChar TxStatBuf[2]={0,0};
	do {
		usleep(1000);//这个时间的确定:(1)主机和子机开机,然后用1ms延时,看串口打印终端loop的值,如果是loop=5,表示5ms后收到接收方的回应帧,表示发送成功,并且每次轮询都是5ms,那么就可以把这里延时改为5ms,这样能减少do...while循环里面函数的调用次数,减少无用的开销。(2)实际考虑时,要考虑循环里面函数执行时间的开销
		SPI_Read_Reg(spifd,READ_REG+STATUS,TxStatBuf);
        //printf("RF24L01_transmit():TxStatBuf[0] = 0x%02x,TxStatBuf[1] = 0x%02x,send_loop=%d\n", TxStatBuf[0], TxStatBuf[1],loop);
		loop++; 
	} while ( (TxStatBuf[1] == 0x0e) && (loop < 333));
	
	SPI_Write_Reg(spifd,WRITE_REG+STATUS,TxStatBuf[1]);//clear STATUS
	
	if( (TxStatBuf[1]) & TX_OK) 
	{
		SPI_Write_Reg(spifd,FLUSH_TX, 0xff);//如果收到应答信号,则认为数据成功发送到接收端,此时状态寄存器TX_DS位置高,并把数据冲TX FIFO中清掉(马上清理缓冲区)
		//printf("\nRF_Send_to_MSub(): TxStatBuf[0]=%#x,TxStatBuf[1]=%#x,send_loop=%d, rf  send successful\n",TxStatBuf[0],TxStatBuf[1],loop);
		return 1;
	}
	else if( (TxStatBuf[1]) & MAX_TX )
	{
		SPI_Write_Reg(spifd,FLUSH_TX, 0xff);
		printf("\nRF_Send_to_MSub():send_loop=%d,rf send Times Out\n",loop);
		return 0;
	}
	else
	{	
		printf("\nRF_Send_to_MSub(): rf send failed!\n");
		return -1;
	}
}


void RF_Revc_from_MSub(int spifd,uChar *rxBuf)
{
	int loop = 0;
	uChar RxStatBuf[2]={0,0};
	do { 
		 usleep(6000);
		 
		 //usleep(1000); 这种情况会出现频繁超时现象,改成50ms后超时偶尔发生
		 SPI_Read_Reg(spifd,READ_REG+STATUS,RxStatBuf);
		 
		 SPI_Write_Reg(spifd,WRITE_REG+STATUS, RxStatBuf[1]);
		
		 if( RxStatBuf[1] == 0x4e )
			 printf("RF_Revc_from_MSub():RxStatBuf[0]=%#x,RxStatBuf[1]=%#x,loop-rev=%d,rf rev 0x4E\n",RxStatBuf[0],RxStatBuf[1],loop);
		
		 if((RxStatBuf[1] != 0x4e) && (RxStatBuf[1] & RX_OK))
		 {
			SPI_Read_Buf(spifd,RD_RX_PLOAD, rxBuf, RX_PLOAD_WIDTH);
			SPI_Write_Reg(spifd,FLUSH_RX, 0xff); // 接收有效数据完成后,马上清理缓冲区
			//printf("RF_Revc_from_MSub():rxBuf[0]=%#x,rxBuf[1]=%#x,loop-rev=%d,rf rev successful\n",rxBuf[0],rxBuf[1],loop);
			//printf("\n");
			break;
		 }
		 else 
		 { 
			//printf("RF_Revc_from_MSub():loop-rev=%d,rf rev failed\n",loop);
			//SPI_Write_Reg(spifd,FLUSH_RX, 0xff);  //如果调用这一句  会出现0x4e
		 }
		 loop++;
	} while(loop < 25);//while(loop < 1000);
	
	//SPI_Write_Reg(spifd,WRITE_REG+CONFIG, 0x0D);  //这里注释掉,表示不进入掉电模式
}

头文件:

#ifndef SPIRF2401_H
#define SPIRF2401_H

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>//memset
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>


#define SCREAD_REG        0x00
#define SCWRITE_REG       0x20
#define SCTX_ADDR         0x10

/************* nRF24L01 register command *************/
#define READ_REG        0x00
#define WRITE_REG       0x20
#define RD_RX_PLOAD     0x61
#define WR_TX_PLOAD     0xA0
#define FLUSH_TX        0xE1
#define FLUSH_RX        0xE2
#define REUSE_TX_PL     0xE3
#define NOP             0xFF


/************* nRF24L01 register address *************/
#define CONFIG          0x00
#define EN_AA           0x01
#define EN_RXADDR       0x02
#define SETUP_AW        0x03
#define SETUP_RETR      0x04
#define RF_CH           0x05
#define RF_SETUP        0x06
#define STATUS          0x07
#define OBSERVE_TX      0x08
#define CD              0x09
#define RX_ADDR_P0      0x0A
#define RX_ADDR_P1      0x0B
#define RX_ADDR_P2      0x0C
#define RX_ADDR_P3      0x0D
#define RX_ADDR_P4      0x0E
#define RX_ADDR_P5      0x0F
#define TX_ADDR         0x10
#define RX_PW_P0        0x11
#define RX_PW_P1        0x12
#define RX_PW_P2        0x13
#define RX_PW_P3        0x14
#define RX_PW_P4        0x15
#define RX_PW_P5        0x16
#define FIFO_STATUS     0x17


/************* send and receive data width *************/
#define TX_ADR_WIDTH    5	//send address width
#define RX_ADR_WIDTH    5	//rcve address width
#define TX_PLOAD_WIDTH  2	//send data width
#define RX_PLOAD_WIDTH  2	//rcve data width


/************* send and receive status *************/
#define MAX_TX  0x10
#define TX_OK   0x20
#define RX_OK   0x40


/******************** the others ******************/

//ioctl(fd,IOCTL_LED_1, LED_ON);//
#define IOCTL_LED_1 1
#define IOCTL_LED_2 2
#define IOCTL_LED_3 3
#define IOCTL_LED_4 4
#define LED_ON 0
#define LED_OFF 1


#define XEINT12_B  12
#define XEINT13_B  13

#define LOW 0
#define HIGH 1

typedef unsigned char uChar;

int spiOpen(void);
int gpioOpen(void);
void spiClose(int spifd);
void gpioClose(int gpiofd);
int spiSet(int fd);
void nRF24L01Init(int gpiofd);
int SCSPI_Write_TX_ADDR_reg(int spifd,uChar reg, uChar *pBuf, uChar len);
int SCSPI_Read_TX_ADDR_reg(int spifd,uChar reg, uChar *pBuf, uChar len);
int rfBeginTransfer(int spifd,uChar value,uChar *pBuf1);
int  nRF2401SelfCheckExist(int spifd);
void TX_Mode(int gpiofd,int spifd,uChar *addr,uChar * txBuf);
void RX_Mode(int gpiofd,int spifd,uChar *addr);
int SPI_Write_Reg(int spifd,uChar reg,uChar value);
int SPI_Read_Reg(int spifd,uChar reg,uChar *buf);
int SPI_Write_Buf(int spifd,uChar reg, uChar *pBuf, uChar len);
int SPI_Read_Buf(int spifd,uChar reg, uChar *pBuf, uChar len);
int RF_Send_to_MSub(int spifd);
void RF_Revc_from_MSub(int spifd,uChar *rxBuf);


#endif

标签:spifd,int,4412,SPI,RF,uChar,buf,define
来源: https://blog.csdn.net/fengel_cs/article/details/120637074

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有