A7139 无线模块驱动(STM32)增加FIFO扩展模式的底层代码

发布者:SparklingMoon最新更新时间:2024-06-07 来源: elecfans关键字:A7139  无线模块驱动 手机看文章 扫描二维码
随时随地手机看文章

  A7139 拥有电磁波唤醒以及10mW的发射功率,非常容易实现长距离通信,目前测试有障碍物可以轻松达到300m以上。


  通过几天的调试,目前可以发送任意大小的数据包,大小为1-16KB,全部使用中断收发,效率极高。


  增加波特率设置2Kbps-100Kbps任意设置

  增加通信信道设置0-255

  增加发送功率设置0-7

  #include “SYSTEM.H”

  #include “GPIO_INIT.H”

  #include “a7139.H”

  #include “LED.H”

  //晶振寄存器,用于设置晶振以及PAGE地址

  //用于缓存寄存器7的值

  static u16 A7139_CRYSTAL_REG = 0x18;

  //单包数据发送超时时间

  #define A7139_SEND_TIME_OUT 5 //单位10ms

  //基础频率,设置频率范围为420.500MHZ~452.375MHZ ,频道差为125KHZ

  #define A7139_BASE_FRE 420.5f

  //调试开关

  #define A7193_DBUG 1

  #if A7193_DBUG

  #include “system.h”

  #define A7193_debug(format,。。。) uart_printf(format,##__VA_ARGS__)

  #else

  #define A7193_debug(format,。。。) /

  /

  #endif //A7193_DBUG

  vu8 IntCnt = 0;

  //寄存器配置

  typedef struct

  {

  u16 SCLOCK; //系统时钟寄存器

  u16 PLL1; //PLL1

  u16 PLL2; //PLL2

  u16 PLL3; //PLL3

  u16 PLL4; //PLL4

  u16 PLL5; //PLL5

  u16 PLL6; //PLL6

  u16 CRYSTAL; //晶振设置

  u16 PREG8S; //寄存器组,由CRYSTAL控制切换

  u16 PREG9S; //寄存器组,由CRYSTAL控制切换

  u16 RX1; //接收设置1

  u16 RX2; //接收设置2

  u16 ADC; //ADC

  u16 PIN; //PIN

  u16 CALIB; //Calibration

  u16 MODE; //模式控制

  } A7139_CONFIG_YPTE;

  const u16 A7139Config[]=

  {

  0x0021, //SYSTEM CLOCK register,

  0x0A21, //PLL1 register,

  0xDA05, //PLL2 register, 433.301MHz

  0x0000, //PLL3 register,

  0x0A20, //PLL4 register,

  0x0024, //PLL5 register,

  0x0000, //PLL6 register,

  0x0001, //CRYSTAL register,

  0x0000, //PAGEA,

  0x0000, //PAGEB,

  0x18D4, //RX1 register, IFBW=100KHz, ETH=1

  0x7009, //RX2 register, by preamble

  0x4400, //ADC register,

  0x0800, //PIN CONTROL register, Use Strobe CMD

  0x4845, //CALIBRATION register,

  0x20C0 //MODE CONTROL register, Use FIFO mode

  };

  const u16 A7139Config_PageA[]=

  {

  0xF706, //TX1 register, Fdev = 37.5kHz

  0x0000, //WOR1 register,

  0xF800, //WOR2 register,

  0x1107, //RFI register, Enable Tx Ramp up/down

  0x0170, //PM register,

  0x0201, //RTH register,

  0x400F, //AGC1 register,

  0x2AC0, //AGC2 register,

  0x0041, //GIO register GIO1-》WTR GIO2-》WTR

  0xD281, //CKO register

  0x0004, //VCB register,

  0x0A21, //CHG1 register, 430MHz

  0x0022, //CHG2 register, 435MHz

  0x003F, //FIFO register, FEP=63+1=64bytes

  0x1507, //CODE register, Preamble=4bytes, ID=4bytes

  0x0000 //WCAL register,

  };

  const u16 A7139Config_PageB[]=

  {

  0x0337, //TX2 register,

  0x8400, //IF1 register, Enable Auto-IF, IF=200KHz

  0x0000, //IF2 register, 频率偏移为0

  0x0000, //ACK register,

  0x0000 //ART register,

  };

  //GPIO1功能设置

  #define A7139_SetGIO_WTR() A7139_WritePageA(A7139_REG8_GPIO, 0x0041) //WTR模式,单包收发提示

  #define A7139_SetGIO_FPF() A7139_WritePageA(A7139_REG8_GPIO, 0x0035) //FPF模式,多包收发状态提示

  #define A7139_SetGIO_NULL() A7139_WritePageA(A7139_REG8_GPIO, 0x0000) //关闭GPIO1指示

  //发送数据结构

  typedef struct

  {

  u8 *pSendData; //发送数据缓冲区指针

  u16 SendLen; //需要发送数据长度

  u16 TranLen; //已经发送数据长度

  bool isSendOK; //发送完成

  bool isSendError;//发送失败

  }A7139_SEND_TYPE;

  volatile A7139_SEND_TYPE SendConfig; //发送数据的信息

  //接收数据结构

  typedef struct

  {

  u8 *pRevData; //接收数据缓冲区指针

  u16 RevLen; //需要接收数据长度

  u16 TranLen; //已经接收数据长度

  u16 RevBuffSize;//接收缓冲区大小

  bool isRevOK; //接收完成

  bool isRevError;//接收失败

  }A7139_REV_TYPE;

  volatile A7139_REV_TYPE RevConfig; //发送数据的信息

  //收发模式记录,用于中断处理发送或接收模式

  static bool isSendMode = FALSE; //默认为接收模式

  #define A7139_SendMode(x) (isSendMode=x)

  /*命令选择

  地址格式

  BIT7 BIT6-BIT4 BIT3-BIT0

  R/W Command Address

  0:写 000 读写控制寄存器

  1:读 010 读写ID

  100 读写FIFO

  110 复位FIFO

  111 RF复位

  */

  void A7139_SetBaseFreq(float RfFreq); //基础频率设置

  bool A7139_Cali(void); //频率校准

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

  * 函数 : void A7139_SetTrafficRate(u8 Rate)

  * 功能 : A7139设置通信速率,单位Kbps

  * 参数 : Rate:通信速率,单位Kbps

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 说明 : 用于设置通信速率

  范围2-100Kbps

  设置系统时钟2分频,设置为12.8MHZ后如果IFBW设置过小会导致初始化时自动校准失败

  如果设置为50会出现校准失败

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

  void A7139_SetTrafficRate(u8 Rate)

  {

  u16 SDR;

  if(Rate 《 2) Rate = 2;

  if(Rate 》 100) Rate = 100;

  //IFBW设置 DMOS=1 64分频 ETH=1 CSC=0 FCSCK=12.8MHZ

  if(Rate 《= 50) //IFBW=100KHZ

  {

  A7139_WriteReg(A7139_RX1, 0x18D0 | (1《《2));

  }

  else //IFBW=100KHZ

  {

  A7139_WriteReg(A7139_RX1, 0x18D0 | (1《《2));

  }

  SDR = 100/Rate;

  SDR -= 1; //计算波特率分频值

  A7139_WriteReg(A7139_SCLOCK,0x0021|(SDR《《9)); //CSC=1 GRC=1 SDR

  }

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

  * 函数 : void A7139_SetChannel(u8 Channel)

  * 功能 : A7139设置通信信道

  * 参数 : Channel:通信信道0-255

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 说明 : 用于设置通信频道

  Channel*0.125/0.0125,最小频率偏差为12.5KHZ,设置通道间隔为125KHZ(最少为100KHZ)

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

  void A7139_SetChannel(u8 Channel)

  {

  A7139_WritePageB(A7139_REG9_IF2,Channel*10);

  }

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

  * 函数 : void A7139_SetTxPowerSupply(u8 PowerSupply)

  * 功能 : 设置A7139发射功率

  * 参数 : PowerSupply:功率等级0-7

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 说明 : 用于设置发射功率

  由于不同频率下TX驱动电流与PA驱动电流并不相同,因此按照文档设置

  目前只支持433频段设置,其它频段请按照文档进行设置。

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

  void A7139_SetTxPowerSupply(u8 PowerSupply)

  {

  if(PowerSupply》6)PowerSupply=6; //最大功率为6

  if(PowerSupply == 0)

  {

  A7139_WritePageB(A7139_REG9_TX2, 0x0300); //功率最小-34dBm,PAC=0,TDC=0,TBG=增益

  }

  else

  {

  A7139_WritePageB(A7139_REG9_TX2, 0x0300|(1《《5)|(1《《3)|PowerSupply); //PAC=1,TDC=1,TBG=增益

  }

  }

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

  * 函数 : bool A7139_Init(u8 Channel, u16 RfID, u8 PowerSupply, u8 Rate)

  * 功能 : A7139初始化

  * 参数 : Channel:通信信道0-80,RfID:RF ID,PowerSupply:发射功率0-7;Rate:通信波特率2-100Kbps

  * 返回 : TRUE:成功;FALSE:失败

  * 依赖 : 底层宏定义

  * 说明 : RF_ID:用于区分网络

  2-100Kbps频率间隔至少为100KHZ,150~200KHZ频道间隔必须大于200KHZ

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

  bool A7139_Init(u8 Channel, u16 RfID, u8 PowerSupply, u8 Rate)

  {

  u32 ID;

  u32 temp;

  if(Rate 《 2) Rate = 2;

  if(Rate 》 100) Rate = 100;

  A7139_DisableInt(); //关闭中断

  A7139_DisableNVIC(); //关闭总中断

  A7139_IO_INIT(); //初始化IO

  A7139_CS_H();

  A7139_CLK_L();

  A7139_DIO_H();

  ID = RfID;

  ID 《《= 16;

  ID |= RfID;

  A7193_debug(“[RF]频率:%dKHz, 通信速率:%dKbps, RFID:%X!rn”,(u32)(A7139_BASE_FRE*1000+Channel*0.125*1000),Rate, ID);

  A7139_CRYSTAL_REG = 0x0001;

  A7139_SoftReset(); //软复位

  if(A7139_ReadID() != 0)

  {

  A7139_SoftReset(); //软复位

  }

  A7139_DelayMS(1);

  A7139_Config(); //初始化寄存器

  A7139_SetBaseFreq(A7139_BASE_FRE); //设置基础频率

  A7139_SetChannel(Channel); //设置信道

  A7139_SetTrafficRate(Rate); //设置通信速率

  A7139_WriteID(ID); //写入ID

  temp = A7139_ReadID(); //读取用户ID

  if(temp != ID)

  {

  A7193_debug(“A7139 初始化失败,芯片检测错误!rn”);

  return FALSE;

  }

  A7193_debug(“A7139 用户ID:%Xt硬件ID:%Xrn”,ID, A7139_ReadDeverID());

  A7139_DelayMS(5);

  if(A7139_Cali()==FALSE) //校准

  {

  A7193_debug(“A7139 初始化失败,校准失败!rn”);

  return FALSE;

  }

  A7193_debug(“A7139 初始化成功!rn”);

  A7139_SetTxPowerSupply(PowerSupply); //设置发射功率

  A7139_EnableInt(); //开启上升沿触发中断

  return TRUE;

  }

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

  * 函数 : void A7139_WriteByte(u8 data)

  * 功能 : A7139写一字节

  * 参数 : data:需要写入的数据

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 说明 : 不带片选,最底层写入1B

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

  void A7139_WriteByte(u8 data)

  {

  u8 i;

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

  {

  if(data & 0x80)

  {

  A7139_DIO_H();

  }

  else

  {

  A7139_DIO_L();

  }

  nop;nop;

  A7139_CLK_H();

  data 《《= 1;

  nop;nop;

  A7139_CLK_L();

  }

  }

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

  * 函数 : u8 A7139_ReadByte(void)

  * 功能 : A7139读取一字节

  * 参数 : 无

  * 返回 : 读取的数据

  * 依赖 : 底层宏定义

  * 说明 : 不带片选,最底层读取1B

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

  u8 A7139_ReadByte(void)

  {

  u8 i;

  u8 data = 0;

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

  {

  A7139_CLK_H();

  data 《《= 1;

  if(A7139_DIO_IN())

  {

  data |= 1;

  }

  nop;

  A7139_CLK_L();

  nop;nop;nop;

  }

  return data;

  }

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

  * 函数 : u16 A7139_ReadReg(A7139_CREG RegAddr)

  * 功能 : 读取控制寄存器

  * 参数 : RegAddr:寄存器地址

  * 返回 : 寄存器值

  * 依赖 : 底层宏定义

  * 说明 :

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

  u16 A7139_ReadReg(A7139_CREG RegAddr)

  {

  u16 data;

  RegAddr &= 0x0f; //地址限制为BIT0-BIT3

  RegAddr |= A7139_RCR_CMD; //读命令

  A7139_CS_L();

  A7139_OutMode();

  A7139_WriteByte(RegAddr);

  A7139_InMode(); //输入

  data = A7139_ReadByte();

  data 《《= 8;

  data |= A7139_ReadByte();

  A7139_CS_H();

  return data;

  }

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

  * 函数 : void A7139_WriteReg(u8 RegAddr, u16 data)

  * 功能 : 写入控制寄存器

  * 参数 : RegAddr:寄存器地址,data:要写入的值

  * 返回 : 无

  * 依赖 : 底层宏定义

  * 说明 :

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

  void A7139_WriteReg(A7139_CREG RegAddr, u16 data)

  {

  RegAddr &= 0x0f; //地址限制为BIT0-BIT3

  RegAddr |= A7139_WCR_CMD; //写命令

  A7139_CS_L();

  A7139_OutMode();

  A7139_WriteByte(RegAddr);

  A7139_WriteByte(data》》8);

  A7139_WriteByte(data);

  A7139_CS_H();

  }

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

  * 函数 : u16 A7139_ReadPageA(A7139_PAGE_A RegAddr)

  * 功能 : 读取控制寄存器组寄存器A

  * 参数 : RegAddr:寄存器组地址

  * 返回 : 寄存器值

  * 依赖 : 底层宏定义

  * 说明 : 寄存器组8

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

[1] [2] [3] [4]
关键字:A7139  无线模块驱动 引用地址:A7139 无线模块驱动(STM32)增加FIFO扩展模式的底层代码

上一篇:STM32F407V芯片断电的时候FLASH被异常改写的解决方案
下一篇:Cortex-M3的STM32微控制器处理先进电机控制方法

推荐阅读最新更新时间:2026-03-05 11:33

Mini2440 NRF24L01无线模块驱动
为了和jihuaLi 完成智能家居系统,我移植了这个驱动,不管写的如何,总结一下是很有必要的。 NRF24L01使用SPI总线与主机通信,没有SPI端口的设备可以使用IO口进行模拟。 关于SPI: SPI是一种四线串行总线, SCLK: 串行时钟线 MOSI: 总线主机输出/ 从机输入 MISO: 总线主机输入/ 从机输出; SS: 从机使能 数据传输方式 通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿
[单片机]
Mini2440 NRF24L01<font color='red'>无线模块</font><font color='red'>驱动</font>
STM32外设开发中5个常见陷阱与规避方法
STM32作为嵌入式开发领域的热门微控制器,功能丰富,几乎能胜任所有常见控制任务,诸如GPIO、定时器、通信接口等外设一应俱全。然而,正因其强大的功能,开发中遭遇陷阱的几率也相应增加,不少初学者甚至经验丰富的开发者常在外设配置上耗费大量时间,调试许久仍难以解决问题。本文总结了5个STM32外设使用中最易出错的技巧,助你规避常见误区,提升开发效率。 1. GPIO 配置别忘了上拉/下拉 很多初学者在读取按键、外部或中断输入时,会发现输入状态总是不稳定,甚至出现抖动或误触发。这通常是因为 GPIO 输入口浮空造成的。 常见坑: 输入引脚未配置上拉/下拉,导致状态随机波动。 上拉/下拉和外部电路冲突,影响可靠性。
[嵌入式]
如何用 STM32 FLASH 实现等效 100 万次擦写的 EEPROM 功能?
在单片机开发中, 数据存储 是一个绕不开的话题。EEPROM因其非易失性存储特性,常用于保存配置参数等数据。 然而,EEPROM的擦写次数通常有限,以STM32为例,STM32L0、STM32L4自带的EEPROM一般 10万次 左右,而很多单片机并不内置EEPROM,这时候,利用单片机的FLASH存储器来模拟EEPROM就成为了一个高性价比的解决方案,但,FLASH的擦写次数一般在 1万次 左右,这个我们可以通过ST的官方数据手册看到: 1万次,在很多场景下并不够。 今天,老宇哥跟大家一起探讨,如何用单片机FLA
[嵌入式]
如何用 <font color='red'>STM32</font> FLASH 实现等效 100 万次擦写的 EEPROM 功能?
STM32驱动WS2811实现渐变色、跑马灯
一、WS2811简介 输出端口耐压12V 芯片内置稳压管,24V以下电源端只需串电阻IC到VDD脚,无需外加稳压管 灰度调节电路(256级灰度可调) 内置信号整形电路,任何一个IC收到信号后经过波形整形后在输出,保证线路波形畸变不会累加 内置上电复位和掉电复位电路 PWM控制端能够实现256级调节,扫描频率不低于400HZ/S 串行接口级联,一根信号线DI完成数据的接收与解码 任意两点传输距离不超过2米无需增加任何电路 当刷新速率30帧/秒时,低速模式级联数不小于512点,高速模式下不小于1024点 数据发送速度可达与400Kbps与800Kbps两种模式 二、通讯协议 数据协议采用单线归零码的通讯方式,
[单片机]
<font color='red'>STM32</font><font color='red'>驱动</font>WS2811实现渐变色、跑马灯
一起用MATLAB玩STM32(测试模型搭建)
之前已经发布两篇文章,分别是软件安装、软件设置。这一篇将详述测试模型搭建过程。 创建Similink空白页之后,先在模型库中找到与STM32的接口模块,如下图: Matlab2021b模型库 将输入输出模块拖入到新建的Simulink模块中: 模块搭建 对它们的配置如下: 模块配置 注意:这里的配置端口与开发板原理图一一对应。 之后仿真在Hardware页面进行。配置stop Time为inf。然后点击Monitor Tune。 StopTime时间配置 待nucleo板的通信灯开始闪烁,表明程序在正常下载。同时matlab也不报错,表明一切正常,之后,就可以通过修改matlab的程序,控制led灯。查看输入的按键
[单片机]
深夜!我偷偷的把室友的STM32换成了GD32
一、什么是GD32 GD32是由北京兆易创新开发的国产32位MCU,基于Arm Cortex- M3/M23/M4内核以及RISC-V内核的32位通用微控制器,与STM32相比,CPU主频更高,内存更多,外设更丰富。其众多产品是以STM32芯片为模板,基于STM32的底层寄存器地址进行正向研发,部分产品可以直接PIN TO PIN替代STM32的芯片,部分型号可以直接以STM32的程序做部分修改后直接烧入进GD32中运行,例如GD32E103、GD32F10x、GD32F30x都是和STM32F10x系列是完全PIN TO PIN兼容的,内部地址寄存器完全兼容,唯一区别只是内核不同,但在使用外设时影响不会很大。 一个大胆的想法
[单片机]
STM32输入捕获
输入捕获是处理器捕获外部输入信号的功能,基于定时器抓取输入信号指定触发方式之间的长度。具体有下面三种触发情况: 1、 上升沿触发 2、 下降沿触发 3、 上下都触发 当触发条件发生后,捕获比较寄存器锁定当前的计数值,如果开启了中断或者DMA,就可以通过中断或DMA及时获得数据进行处理。有时可能遇到上一次触发的标志还没清除,下次触发就发生了,此时会将over-capture标志置位,对于可能出现over-capture的情况,建议先读取数据再清除标志,避免在读取标志后及读取数据前这段时间错过over-capture。 配置输入捕获的步骤: 1. 打开定时器和对应输入引脚的时钟 2. 配置引脚为对应的复用功能 3.
[单片机]
I2C、IIC通讯(填坑作,MPU6050数据读取,STM32主控,附源码)
上图的VCC 接 3.3V,GND接地,SCL和SDA分别接上单片机引脚,并加上上拉电阻,AD0接地。 代码链接:https://pan.baidu.com/s/1AvuMYvgX8Xy8g81S0Ay5Yg 提取码:sce0 初始化单片机引脚,并置1 程序里引脚的变化顺序还有延时的位置一定不要错。 IIC起始信号;SDA置零,等待,SCL置零 写入一次数据,IIC每次写入的数据长度都是8Bit,写入顺序是从最高位写到最低位。 SCL置0,SDA存放数据的最高位,数据左移1位,等待,SCL置1,数据起效,等待。 右移7位:1000 0000会变成0000 0001。(0X80 0X01) 左移1位:1101 000
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved