sx1276-board.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2013 Semtech
  8. Description: SX1276 driver specific target board functions implementation
  9. License: Revised BSD License, see LICENSE.TXT file include in the project
  10. Maintainer: Miguel Luis and Gregory Cristian
  11. */
  12. #include "radio.h"
  13. #include "sx1276.h"
  14. #include "sx1276-board.h"
  15. #include "delay.h"
  16. #include "stdio.h"
  17. //复位脚
  18. #define SX1278_RST_PIN_INDEX GPIO_Pin_11
  19. #define SX1278_RST_PIN_GROUP GPIOB
  20. //SPI引脚
  21. #define SX1278_CS_PIN_INDEX GPIO_Pin_12
  22. #define SX1278_CS_PIN_GROUP GPIOB
  23. #define SX1278_SCK_PIN_INDEX GPIO_Pin_13
  24. #define SX1278_SCK_PIN_GROUP GPIOB
  25. #define SX1278_MISO_PIN_INDEX GPIO_Pin_14
  26. #define SX1278_MISO_PIN_GROUP GPIOB
  27. #define SX1278_MOSI_PIN_INDEX GPIO_Pin_15
  28. #define SX1278_MOSI_PIN_GROUP GPIOB
  29. //DIO0引脚(这里修改了需要手动修改中断初始化和中断函数)
  30. #define SX1278_DIO0_PIN_INDEX GPIO_Pin_6
  31. #define SX1278_DIO0_PIN_GROUP GPIOG
  32. //DIO1引脚(这里修改了需要手动修改中断初始化和中断函数)
  33. //#define SX1278_DIO1_PIN_INDEX GPIO_Pin_1
  34. //#define SX1278_DIO1_PIN_GROUP GPIOB
  35. /*!
  36. * Radio driver structure initialization
  37. */
  38. const struct Radio_s Radio =
  39. {
  40. SX1276Init,
  41. SX1276GetStatus,
  42. SX1276SetModem,
  43. SX1276SetChannel,
  44. SX1276IsChannelFree,
  45. SX1276Random,
  46. SX1276SetRxConfig,
  47. SX1276SetTxConfig,
  48. SX1276CheckRfFrequency,
  49. SX1276GetTimeOnAir,
  50. SX1276Send,
  51. SX1276SetSleep,
  52. SX1276SetStby,
  53. SX1276SetRx,
  54. SX1276StartCad,
  55. SX1276ReadRssi,
  56. SX1276Write,
  57. SX1276Read,
  58. SX1276WriteBuffer,
  59. SX1276ReadBuffer,
  60. SX1276SetMaxPayloadLength
  61. };
  62. /*!
  63. * Antenna switch GPIO pins objects
  64. */
  65. /* 我们的RA-01/02模组的天线切换开关由硬件自动控制,不需要软件控制
  66. Gpio_t AntSwitchLf;
  67. Gpio_t AntSwitchHf;*/
  68. /*!
  69. * Tx and Rx timers
  70. */
  71. /*TimerEvent_t TxTimeoutTimer;
  72. TimerEvent_t RxTimeoutTimer;
  73. TimerEvent_t RxTimeoutSyncWord;*/
  74. //实现ms级延时
  75. //delayMs:延时的ms数
  76. void SX1276DelayMs(uint32_t delayMs){
  77. delay_ms(delayMs);
  78. }
  79. //定时器初始化(RX,TX,SyncWord定时完成后都需要调用 SX1276OnTimeoutIrq() 函数)
  80. void SX1276TimerInit(void){
  81. }
  82. void TIM2_Int_Init(u16 arr,u16 psc)
  83. {
  84. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  85. NVIC_InitTypeDef NVIC_InitStructure;
  86. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
  87. TIM2->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
  88. //定时器TIM3初始化
  89. TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
  90. TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
  91. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  92. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
  93. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
  94. TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
  95. //中断优先级NVIC设置
  96. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中断
  97. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
  98. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级3级
  99. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  100. NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
  101. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  102. TIM_Cmd(TIM2, ENABLE); //启动TIM
  103. }
  104. void TIM3_Int_Init(u16 arr,u16 psc)
  105. {
  106. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  107. NVIC_InitTypeDef NVIC_InitStructure;
  108. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
  109. TIM3->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
  110. //定时器TIM3初始化
  111. TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
  112. TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
  113. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  114. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
  115. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
  116. TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
  117. //中断优先级NVIC设置
  118. NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
  119. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
  120. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
  121. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  122. NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
  123. TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  124. TIM_Cmd(TIM3, ENABLE); //启动TIM
  125. }
  126. void TIM4_Int_Init(u16 arr,u16 psc)
  127. {
  128. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  129. NVIC_InitTypeDef NVIC_InitStructure;
  130. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
  131. TIM4->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
  132. //定时器TIM3初始化
  133. TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
  134. TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
  135. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  136. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
  137. TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
  138. TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
  139. //中断优先级NVIC设置
  140. NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM3中断
  141. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
  142. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级3级
  143. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  144. NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
  145. TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
  146. TIM_Cmd(TIM4, ENABLE); //启动TIM
  147. }
  148. //定时器3中断服务程序
  149. void TIM3_IRQHandler(void) //TIM3中断
  150. {
  151. if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
  152. {
  153. TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
  154. TIM_Cmd(TIM3, DISABLE); //失能TIMx
  155. SX1276OnTimeoutIrq(); //发生中断后需要调用 SX1276OnTimeoutIrq 函数
  156. //printf("\r\ntimer irq\r\n");
  157. }
  158. }
  159. //开启 tx 超时定时器,定时timeoutMs 毫秒
  160. void SX1276TxTimeoutTimerStart( uint32_t timeoutMs ){
  161. //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  162. TIM3_Int_Init((timeoutMs * 10) -1,(12000-1));//10Khz的计数频率,计数到10次为1ms
  163. }
  164. //关闭 tx 超时定时器
  165. void SX1276TxTimeoutTimerStop(void){
  166. ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  167. TIM_Cmd(TIM3, DISABLE); //失能TIMx
  168. }
  169. //开启 RX 超时定时器,定时timeoutMs 毫秒
  170. void SX1276RxTimeoutTimerStart( uint32_t timeoutMs ){
  171. //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  172. TIM3_Int_Init((timeoutMs * 10) -1,7199);//10Khz的计数频率,计数到10次为1ms
  173. }
  174. //关闭 RX 超时定时器
  175. void SX1276RxTimeoutTimerStop(void){
  176. ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  177. TIM_Cmd(TIM3, DISABLE); //失能TIMx
  178. }
  179. //开启 SyncWord 超时定时器,定时timeoutMs 毫秒
  180. void SX1276SyncWordTimeoutTimerStart( uint32_t timeoutMs ){
  181. //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  182. TIM3_Int_Init((timeoutMs * 10) -1,7199);//10Khz的计数频率,计数到10次为1ms
  183. }
  184. //关闭 SyncWord 超时定时器
  185. void SX1276SyncWordTimeoutTimerStop(void){
  186. ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
  187. TIM_Cmd(TIM3, DISABLE); //失能TIMx
  188. }
  189. //初始化SPI(cs低使能,极性SPI_CPOL_High,相位SPI_CPHA_2Edge,SPI_FirstBit_MSB)和Rst脚
  190. void SX1276IoInit( void )
  191. {
  192. GPIO_InitTypeDef GPIO_InitStructure;
  193. SPI_InitTypeDef SPI_InitStructure;
  194. //初始化一个gpio用来控制spi1的cs
  195. RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  196. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
  197. GPIO_InitStructure.GPIO_Pin = SX1278_CS_PIN_INDEX;
  198. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
  199. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  200. GPIO_Init(SX1278_CS_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
  201. //SPI的初始化
  202. RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//SPI时钟使能
  203. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
  204. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  205. GPIO_InitStructure.GPIO_Pin = SX1278_SCK_PIN_INDEX|SX1278_MISO_PIN_INDEX|SX1278_MOSI_PIN_INDEX;
  206. GPIO_Init(SX1278_SCK_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
  207. //配置SPI
  208. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
  209. SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
  210. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
  211. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //设置时钟极性(串行同步时钟的空闲状态为高电平还是低电平)
  212. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //设置相位(串行同步时钟的第几个跳变沿(上升或下降)数据被采样)
  213. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:设置为软件控制(SSI控制)
  214. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //定义波特率预分频的值:波特率预分频值为256(256是最低,可以设置完成之后调整速度,如果速度过快导致通信失败再调小)
  215. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  216. SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式(CRC校验相关)
  217. SPI_Init(SPI1,&SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
  218. SPI_Cmd(SPI1,ENABLE); //使能SPI外设
  219. }
  220. DioIrqHandler **g_irqHandlers;
  221. //初始化DIO(上升沿)中断,将 DIO0~5 的GPIO中断函数调用 irqHandlers[0]~irqHandlers[5]
  222. void SX1276IoIrqInit( DioIrqHandler **irqHandlers )
  223. {
  224. EXTI_InitTypeDef EXTI_InitStructure;
  225. NVIC_InitTypeDef NVIC_InitStructure;
  226. GPIO_InitTypeDef GPIO_InitStructure;
  227. g_irqHandlers=irqHandlers;
  228. //初始化DIO0
  229. // 使能外部IO时钟
  230. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
  231. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  232. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
  233. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
  234. GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
  235. GPIO_InitStructure.GPIO_Pin = SX1278_DIO0_PIN_INDEX;
  236. GPIO_Init(SX1278_DIO0_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
  237. //配置中断
  238. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG,EXTI_PinSource6);//设置映射线关系(这里的 GPIO_PortSourceGPIOX 刚好是0-5,所以直接用pinName/16表示,GPIO_PinSourceXX刚好是0-15,所以用pinName%16表示了)
  239. EXTI_InitStructure.EXTI_Line=EXTI_Line6; //中断线u8_pinNum
  240. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//外部中断
  241. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升降沿触发
  242. EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能中断
  243. EXTI_Init(&EXTI_InitStructure);//配置中断
  244. //配置中断优先级
  245. NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中断XX
  246. //stm32f103c8例子中这个优先级对应抢占优先级2子优先级3
  247. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先级
  248. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级
  249. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
  250. NVIC_Init(&NVIC_InitStructure); //配置优先级
  251. EXTI_ClearITPendingBit(EXTI_Line6);//清除中断标志位
  252. }
  253. #if 0
  254. //外部中断线0中断处理函数,这里需要回调对应的函数
  255. void EXTI0_IRQHandler(void){
  256. g_irqHandlers[0]();
  257. EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位
  258. }
  259. //外部中断线1中断处理函数,这里需要回调对应的函数
  260. void EXTI1_IRQHandler(void){
  261. g_irqHandlers[1]();
  262. EXTI_ClearITPendingBit(EXTI_Line1);//清除中断标志位
  263. }
  264. #endif
  265. //处理DIO tx中断或者Rx中断数据
  266. void EXTI6_IRQHandler(void)
  267. {
  268. g_irqHandlers[0]();
  269. EXTI_ClearITPendingBit(EXTI_Line6);//清除中断标志位
  270. }
  271. //将SPI、DIO0~5和Rst脚的中断去初始化
  272. void SX1276IoDeInit( void )
  273. {
  274. //这里省略去初始化的功能了
  275. }
  276. //判断频率是否合法
  277. //如果不限制频率可以直接return true
  278. bool SX1276CheckRfFrequency( uint32_t frequency )
  279. {
  280. // Implement check. Currently all frequencies are supported
  281. return true;
  282. }
  283. /**
  284. * 硬复位
  285. * 将rst引脚拉低1ms,然后将复位脚设置为无上下拉的输入模式
  286. */
  287. void SX1276Reset( void )
  288. {
  289. GPIO_InitTypeDef GPIO_InitStructure;
  290. RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能指定端口时钟(这里是为了方便ABC全开了)
  291. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
  292. GPIO_InitStructure.GPIO_Pin = SX1278_RST_PIN_INDEX;
  293. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
  294. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  295. GPIO_Init(SX1278_RST_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
  296. GPIO_ResetBits(SX1278_RST_PIN_GROUP,SX1278_RST_PIN_INDEX); //输出低电平
  297. delay_ms(1);
  298. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//浮空输入
  299. GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
  300. GPIO_Init(SX1278_RST_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
  301. delay_ms(6);
  302. }
  303. /**
  304. * 设置SPI的片选脚的电平(低电平使能,高电平取消)
  305. * lev:true的时候高电平,false的时候低电平
  306. */
  307. void Sx1276SetNSS(bool lev )
  308. {
  309. if(lev){
  310. GPIO_SetBits(SX1278_CS_PIN_GROUP,SX1278_CS_PIN_INDEX); //输出高电平
  311. }else{
  312. GPIO_ResetBits(SX1278_CS_PIN_GROUP,SX1278_CS_PIN_INDEX); //输出低电平
  313. }
  314. }
  315. /**
  316. * SPI读写函数,data是发送的数据,返回值是接收到的数据
  317. */
  318. uint8_t Sx1276SpiInOut(uint16_t data )
  319. {
  320. //完成SPI的读写功能
  321. uint16_t retry=0;
  322. while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){//检查指定的SPI标志位设置与否:发送缓存空标志位(缓冲区空了就可以拷贝数据了)
  323. if((retry++)>2000){
  324. //超时了
  325. return 0xff;
  326. }
  327. }
  328. SPI_I2S_SendData(SPI1, data); //通过外设SPIx发送一个数据
  329. retry=0;
  330. while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){ //检查指定的SPI标志位设置与否:接受缓存非空标志位(非空了就表示接收数据完成了)
  331. if((retry++)>2000){
  332. //超时了
  333. return 0xff;
  334. }
  335. }
  336. return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
  337. }