stc12c5a60s2_spi程序

HDL语言及源代码

6人已加入

描述

  单片机是STC12C5A60S2,用的是单片机的硬件SPI驱动的nRF24L01+,这个是从机(接收机的)。主机(发射机)是用的STC12C5A60S2单片机,软件模拟SPI。这个是硬件全貌。

  STC12C5A60S2在众多的51系列单片机中,要算国内STC 公司的1T增强系列更具有竞争力,因他不但和8051指令、管脚完全兼容,而且其片内的具有大容量程序存储器且是FLASH工艺的,如STC12C5A60S2单片机内部就自带高达60K FLASHROM,这种工艺的存储器用户可以用电的方式瞬间擦除、改写。

  而且STC系列单片机支持串口程序烧写。显而易见,这种单片机对开发设备的要求很低,开发时间也大大缩短。写入单片机内的程序还可以进行加密,这又很好地保护了你的劳动成果。

  

  stc12c5a60s2 spi调试程序

  ///////////spi.h/////////////////////////////

  #ifndef SPI_H

  #define SPI_H

  #include 《stc12le5a60s2.h》

  #include 《spi.h》

  //sfr P4 = 0xe8;

  //STC12LE5A60S2单片机自带SPI控制器连接

  //sbit VCC1 = P2^0;// VCC1 NO USE

  //sbit SON = P1^6 ;// MISO

  //sbit SIN = P1^5 ;// MOSI

  //sbit SCKN = P1^7 ; // SCK

  sbit CSN = P1^4 ;// 28J60 -- CS

  //sbit RSTN = P3^5 ; //RST, no use

  //sbit INTN = P3^3 ; // INT, no use

  void init_spi(void);

  void WriteByte(u8_t temp);

  u8_t ReadByte(void);

  #endif

  ////////////////////////////////////////////////////////////////

  ///////////////////////////spi.c/////////////////////////////

  #include《spi.h》

  //STC12LE5A60S2单片机自带SPI控制器连接

  void init_spi(void)

  {

  //SSIG = 1; //忽略SS脚

  //SPEN = 1; //允许SPI工作

  //DORD = 0; //先传高位MSB

  //MSTR = 1; //设置单片机为主机

  SPCTL = 0xD0; //SPI Control Register SSIG SPEN DORD MSTR CPOL CPHA SPR1 SPR0 0000,0100

  SPSTAT = 0xC0; //

  //IE2 |= 0x02; //允许SPI中断控制位

  }

  void WriteByte(u8_t temp)

  {

  SPDAT = temp;

  while(!(SPSTAT & 0x80));

  SPSTAT = 0xC0;

  }

  u8_t ReadByte(void)

  {

  idata u8_t temp;

  //SPSTAT = 0xC0;

  SPDAT = 0x00;

  while(!(SPSTAT & 0x80));

  temp = SPDAT;

  SPSTAT = 0xC0;

  return temp;

  }

  ////////////////////////////////////////////////////////////////

  stc12c5a60s2 spi程序

  #include 《reg52.h》

  #include 《intrins.h》

  #define MODE 0 //MODE=1时 为发送代码 MODE=0时 为接收代码

  typedef unsigned char uchar;

  #define uint unsigned int

  //****************************************IO端口定义***************************************

  sfr SPCTL = 0xCE; //SPI Control Register SSIG SPEN DORD MSTR CPOL CPHA SPR1 SPR0 0000,0100

  sfr SPSTAT = 0xCD; //SPI Status Register SPIF WCOL - - - - - - 00xx,xxxx

  sfr SPDAT = 0xCF;

  sbit CE =P1^0;

  sbit CSN =P1^1;

  sbit IRQ =P1^2;

  sbit led = P2^0;

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

  uchar bdata sta; //状态标志

  sbit RX_DR =sta^6;

  sbit TX_DS =sta^5;

  sbit MAX_RT =sta^4;

  //*********************************************NRF24L01*************************************

  #define TX_ADR_WIDTH 5 // 5 uints TX address width

  #define RX_ADR_WIDTH 5 // 5 uints RX address width

  #define TX_PLOAD_WIDTH 32 // 32 uints TX payload

  #define RX_PLOAD_WIDTH 32 // 32 uints TX payload

  uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址

  uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址

  uchar code Tx_Buf[TX_PLOAD_WIDTH]={0xff,0xee,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,

  0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xaa,0xbb,0x11,0x22,0x33,0xee,0xff};//发送数据

  uchar Rx_Buf[RX_PLOAD_WIDTH];//接收数据

  //***************************************NRF24L01寄存器指令*******************************************************

  #define READ_REG 0x00 // 读寄存器指令

  #define WRITE_REG 0x20 // 写寄存器指令

  #define RD_RX_PLOAD 0x61 // 读取接收数据指令

  #define WR_TX_PLOAD 0xA0 // 写待发数据指令

  #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令

  #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令

  #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令

  #define NOP 0xFF // 保留

  //*************************************SPI(nRF24L01)寄存器地址****************************************************

  #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式

  #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 // 频道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接收数据长度

  #define RX_PW_P1 0x12 // 接收频道1接收数据长度

  #define RX_PW_P2 0x13 // 接收频道2接收数据长度

  #define RX_PW_P3 0x14 // 接收频道3接收数据长度

  #define RX_PW_P4 0x15 // 接收频道4接收数据长度

  #define RX_PW_P5 0x16 // 接收频道5接收数据长度

  #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置

  /******************************************延时函数********************************************************/

  //长延时

  void Delay(unsigned int s)

  {

  unsigned int i,j;

  for(i=0;i《1000;i++)for(j=0;j《s;j++);

  }

  //短延时

  void delay_ms(unsigned int x)

  {

  unsigned int i,j;

  i=0;

  for(i=0;i《x;i++)

  {

  j=108;

  while(j--);

  }

  }

  /************初始化5A spi***************/

  void Init_SPI(uchar speed)

  {

  SPDAT=0; //初始化数据寄存器

  SPSTAT=0XC0; //清除状态寄存器

  SPCTL=0XD0|speed;//设置为主机模式 主频不能超过2M

  //忽略SS 使能spi MSB SCLK空闲为0 第一个时钟边沿开始采集 spi通信的频率为CUP_CLK/16

  }

  //SPDAT 读写一个字节

  //TxData:要写入的字节

  //返回值:读取到的字节

  uchar SPI_ReadWriteByte(uchar TxData)

  {

  SPDAT=TxData; //发送一个byte

  while((SPSTAT&0x80)==0);

  SPSTAT=0XC0; //清除状态寄存器

  return SPDAT; //返回收到的数据

  }

  //读取SPI寄存器值

  //reg:要读的寄存器

  uchar SPI_Read_Reg(uchar reg)

  {

  uchar reg_val;

  CSN = 0; //使能SPI传输

  SPI_ReadWriteByte(reg); //发送寄存器号

  reg_val=SPI_ReadWriteByte(0xFF);//读取寄存器内容

  CSN = 1; //禁止SPI传输

  return(reg_val); //返回状态值

  }

  // 向寄存器REG写一个字节,同时返回状态字节 reg寄存器地址 value写入的数据

  uchar SPI_RW_Reg (uchar reg,uchar value)

  {

  uchar status;

  CSN=0;

  status=SPI_ReadWriteByte(reg);//发送寄存器号

  SPI_ReadWriteByte(value); //写入寄存器的值

  CSN=1;

  return(status);

  }

  //写一个数据包

  uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)

  {

  uchar status,byte_ctr;

  CSN = 0;

  status=SPI_ReadWriteByte(reg);

  for(byte_ctr=0; byte_ctr《bytes; byte_ctr++)

  SPI_ReadWriteByte(*pBuf++);

  CSN = 1;

  return(status);

  }

  //读一个数据包

  uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)

  {

  uchar status,uchar_ctr;

  CSN = 0;

  status = SPI_ReadWriteByte(reg);

  for(uchar_ctr=0;uchar_ctr《uchars;uchar_ctr++)

  pBuf[uchar_

  ctr]=SPI_ReadWriteByte(0xFF);

  CSN = 1;

  return(status);

  }

  #if MODE

  /*******************************发*****送*****模*****式*****代*****码*************************************/

  void TX_Mode(void)

  {

  CE=0;

  SPI_RW_Reg(FLUSH_TX,0x00);

  SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写发送的地址 Writes TX_Address to nRF24L01

  SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 写接受的地址 RX_Addr0 same as TX_Adr for Auto.Ack

  SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); //使能自动应答 Enable Auto.Ack:Pipe0

  SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //使能通道0 Enable Pipe0

  SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 自动重发功能设置 500us + 86us, 10 retrans.。.1a

  SPI_RW_Reg(WRITE_REG + RF_CH, 40); //收发频率

  SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 发射速率、功耗功能设置 TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR

  SPI_RW_Reg(WRITE_REG + RX_PW_P0, (unsigned char)RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节

  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);

  CE=1;

  delay_ms(100);

  }

  void Transmit(unsigned char * tx_buf)

  {

  CE=0; //StandBy I模式

  SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //装载接收端地址

  SPI_RW_Reg(FLUSH_TX,0x00); //清除FIFO

  SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据

  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送

  CE=1; //置高CE,激发数据发送

  delay_ms(150);

  }

  #else

  /*******************************接*****收*****模*****式*****代*****码*************************************/

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

  /*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)

  /*功能:数据读取后放如rx_buf接收缓冲区中

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

  unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)

  {

  // unsigned char revale=0;

  sta=SPI_Read_Reg(STATUS); // 读取状态寄存其来判断数据接收状况

  SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志

  if(RX_DR) // 判断是否接收到数据

  {

  SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer

  SPI_RW_Reg(FLUSH_RX,0xFF);//清除接受FIFO

  return 1; //读取数据完成标志

  }

  return 0;

  }

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

  /*函数:void RX_Mode(void)

  /*功能:数据接收配置

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

  void RX_Mode(void)

  {

  CE=0;

  // SPI_RW_Reg(FLUSH_RX,0x00);//清

  除接受FIFO

  //SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01

  SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uchar*)RX_ADDRESS, RX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack

  SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);//使能自动应答 Enable Auto.Ack:Pipe0

  SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //连接通道0和地址 Enable Pipe0

  //SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans.。.1a

  SPI_RW_Reg(WRITE_REG + RF_CH, 125);//通信频率0~125 设置通信的频率 Select RF channel 40

  SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节

  SPI_RW_Reg(WRITE_REG + RF_SETUP,0X0F); //0x07 TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR

  // 设置TX发射参数,0db增益,2Mbps,低噪声增益开启

  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F);//配置基本工作模式的参数

  CE=1;

  delay_ms(130);

  }

  //************************************串口初始化*********************************************************

  void StartUART( void )

  { //波特率9600

  SCON = 0x50; //串口模式1 8bit 使能接收

  TMOD = 0x20;//定时器1模式2 8位自动重装

  // PCON=0x80; //19200

  TH1 = 0xFD;

  TL1 = 0xFD;

  // IE=0x90; //开总中断开串口中断

  EA=1;

  ES=1;

  TR1=1;//启动定时器1

  // TI=1;

  }

  //************************************通过串口将接收到数据发送给PC端**************************************

  void R_S_Byte(uint R_Byte)

  {

  SBUF=R_Byte;

  while(TI==0);

  TI=0;

  }

  #endif

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

  uchar NRF24L01_Check(void)

  {

  uchar buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};

  uchar i;

  SPI_Write_Buf(WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址。

  SPI_Read_Buf(TX_ADDR,buf,5); //读出写入的地址

  for(i=0;i《5;i++) if(buf[i]!=0XA5) break;

  if(i!=5) return 1;//检测24L01错误

  return 0; //检测到24L01

  }

  void main()

  {

  uint i=0;

  CE=0;

  CSN=1;

  led=0;

  Init_SPI(1);

  while(NRF24L01_Check())//检测不到24L01

  {

  delay_ms(500);

  delay_ms(500);

  led=!led;//DS0闪烁

  }

  #if MODE //发送模式代码

  TX_Mode();

  while(1)

  {

  Transmit(Tx_Buf); //清除FIFO

  Delay(10);

  sta=SPI_Read(READ_REG + STATUS);

  if(TX_DS)

  {

  P1=sta; //8位LED显示当前STATUS状态 发送中断应使bit5 = 1 灯灭

  Delay(100);

  SPI_RW_Reg(WRITE_REG + STATUS,sta);

  }

  if(MAX_RT) //如果是发送超时

  {

  P1=0x0f; //发送超时时 8位LED灯 bit4 = 1 灯灭

  Delay(150);

  SPI_RW_Reg(WRITE_REG + STATUS,sta);

  }

  }

  #else //接收 模式代码

  StartUART(); //串口初始

  RX_Mode(); //接受模式

  Delay(0);//防止编译警告

  while(1)

  {

  if(nRF24L01_RxPacket(Rx_Buf))

  {

  for(i=0;i《TX_PLOAD_WIDTH;i++)

  {

  R_S_Byte(Rx_Buf[i]);

  led=0;

  }

  }

  led=1;

  }

  #endif

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分