123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- / _____) _ | |
- ( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
- (______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- Description: SX1276 driver specific target board functions implementation
- License: Revised BSD License, see LICENSE.TXT file include in the project
- Maintainer: Miguel Luis and Gregory Cristian
- */
- #include "radio.h"
- #include "sx1276.h"
- #include "sx1276-board.h"
- #include "delay.h"
- #include "stdio.h"
- //复位脚
- #define SX1278_RST_PIN_INDEX GPIO_Pin_11
- #define SX1278_RST_PIN_GROUP GPIOB
- //SPI引脚
- #define SX1278_CS_PIN_INDEX GPIO_Pin_12
- #define SX1278_CS_PIN_GROUP GPIOB
- #define SX1278_SCK_PIN_INDEX GPIO_Pin_13
- #define SX1278_SCK_PIN_GROUP GPIOB
- #define SX1278_MISO_PIN_INDEX GPIO_Pin_14
- #define SX1278_MISO_PIN_GROUP GPIOB
- #define SX1278_MOSI_PIN_INDEX GPIO_Pin_15
- #define SX1278_MOSI_PIN_GROUP GPIOB
- //DIO0引脚(这里修改了需要手动修改中断初始化和中断函数)
- #define SX1278_DIO0_PIN_INDEX GPIO_Pin_6
- #define SX1278_DIO0_PIN_GROUP GPIOG
- //DIO1引脚(这里修改了需要手动修改中断初始化和中断函数)
- //#define SX1278_DIO1_PIN_INDEX GPIO_Pin_1
- //#define SX1278_DIO1_PIN_GROUP GPIOB
- /*!
- * Radio driver structure initialization
- */
- const struct Radio_s Radio =
- {
- SX1276Init,
- SX1276GetStatus,
- SX1276SetModem,
- SX1276SetChannel,
- SX1276IsChannelFree,
- SX1276Random,
- SX1276SetRxConfig,
- SX1276SetTxConfig,
- SX1276CheckRfFrequency,
- SX1276GetTimeOnAir,
- SX1276Send,
- SX1276SetSleep,
- SX1276SetStby,
- SX1276SetRx,
- SX1276StartCad,
- SX1276ReadRssi,
- SX1276Write,
- SX1276Read,
- SX1276WriteBuffer,
- SX1276ReadBuffer,
- SX1276SetMaxPayloadLength
- };
- /*!
- * Antenna switch GPIO pins objects
- */
- /* 我们的RA-01/02模组的天线切换开关由硬件自动控制,不需要软件控制
- Gpio_t AntSwitchLf;
- Gpio_t AntSwitchHf;*/
- /*!
- * Tx and Rx timers
- */
- /*TimerEvent_t TxTimeoutTimer;
- TimerEvent_t RxTimeoutTimer;
- TimerEvent_t RxTimeoutSyncWord;*/
- //实现ms级延时
- //delayMs:延时的ms数
- void SX1276DelayMs(uint32_t delayMs){
- delay_ms(delayMs);
- }
- //定时器初始化(RX,TX,SyncWord定时完成后都需要调用 SX1276OnTimeoutIrq() 函数)
- void SX1276TimerInit(void){
- }
- void TIM2_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
- TIM2->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
-
- //定时器TIM3初始化
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
-
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
-
- //中断优先级NVIC设置
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- TIM_Cmd(TIM2, ENABLE); //启动TIM
- }
- void TIM3_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
- TIM3->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
-
- //定时器TIM3初始化
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
-
- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
-
- //中断优先级NVIC设置
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
-
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
- TIM_Cmd(TIM3, ENABLE); //启动TIM
- }
- void TIM4_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
- TIM4->CR1 |= TIM_CR1_URS; //如果不设置这个会导致定时器启动的时候立即进入中断
-
- //定时器TIM3初始化
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
-
- TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
-
- //中断优先级NVIC设置
- NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
-
- TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
- TIM_Cmd(TIM4, ENABLE); //启动TIM
- }
- //定时器3中断服务程序
- void TIM3_IRQHandler(void) //TIM3中断
- {
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
- {
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
- TIM_Cmd(TIM3, DISABLE); //失能TIMx
- SX1276OnTimeoutIrq(); //发生中断后需要调用 SX1276OnTimeoutIrq 函数
- //printf("\r\ntimer irq\r\n");
- }
- }
- //开启 tx 超时定时器,定时timeoutMs 毫秒
- void SX1276TxTimeoutTimerStart( uint32_t timeoutMs ){
- //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM3_Int_Init((timeoutMs * 10) -1,(12000-1));//10Khz的计数频率,计数到10次为1ms
- }
- //关闭 tx 超时定时器
- void SX1276TxTimeoutTimerStop(void){
- ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM_Cmd(TIM3, DISABLE); //失能TIMx
- }
- //开启 RX 超时定时器,定时timeoutMs 毫秒
- void SX1276RxTimeoutTimerStart( uint32_t timeoutMs ){
- //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM3_Int_Init((timeoutMs * 10) -1,7199);//10Khz的计数频率,计数到10次为1ms
- }
- //关闭 RX 超时定时器
- void SX1276RxTimeoutTimerStop(void){
- ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM_Cmd(TIM3, DISABLE); //失能TIMx
- }
- //开启 SyncWord 超时定时器,定时timeoutMs 毫秒
- void SX1276SyncWordTimeoutTimerStart( uint32_t timeoutMs ){
- //这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM3_Int_Init((timeoutMs * 10) -1,7199);//10Khz的计数频率,计数到10次为1ms
- }
- //关闭 SyncWord 超时定时器
- void SX1276SyncWordTimeoutTimerStop(void){
- ///这里简化使用了一个定时器,实际工程中最好使用独立的3个定时器,或者使用软件定时器
- TIM_Cmd(TIM3, DISABLE); //失能TIMx
- }
- //初始化SPI(cs低使能,极性SPI_CPOL_High,相位SPI_CPHA_2Edge,SPI_FirstBit_MSB)和Rst脚
- void SX1276IoInit( void )
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- SPI_InitTypeDef SPI_InitStructure;
-
- //初始化一个gpio用来控制spi1的cs
- RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
- GPIO_InitStructure.GPIO_Pin = SX1278_CS_PIN_INDEX;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_Init(SX1278_CS_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
- //SPI的初始化
- RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//SPI时钟使能
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_Pin = SX1278_SCK_PIN_INDEX|SX1278_MISO_PIN_INDEX|SX1278_MOSI_PIN_INDEX;
- GPIO_Init(SX1278_SCK_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
- //配置SPI
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //设置时钟极性(串行同步时钟的空闲状态为高电平还是低电平)
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //设置相位(串行同步时钟的第几个跳变沿(上升或下降)数据被采样)
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:设置为软件控制(SSI控制)
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //定义波特率预分频的值:波特率预分频值为256(256是最低,可以设置完成之后调整速度,如果速度过快导致通信失败再调小)
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式(CRC校验相关)
- SPI_Init(SPI1,&SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
-
- SPI_Cmd(SPI1,ENABLE); //使能SPI外设
- }
- DioIrqHandler **g_irqHandlers;
- //初始化DIO(上升沿)中断,将 DIO0~5 的GPIO中断函数调用 irqHandlers[0]~irqHandlers[5]
- void SX1276IoIrqInit( DioIrqHandler **irqHandlers )
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
-
- g_irqHandlers=irqHandlers;
- //初始化DIO0
- // 使能外部IO时钟
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
- GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
- GPIO_InitStructure.GPIO_Pin = SX1278_DIO0_PIN_INDEX;
- GPIO_Init(SX1278_DIO0_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
-
- //配置中断
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG,EXTI_PinSource6);//设置映射线关系(这里的 GPIO_PortSourceGPIOX 刚好是0-5,所以直接用pinName/16表示,GPIO_PinSourceXX刚好是0-15,所以用pinName%16表示了)
- EXTI_InitStructure.EXTI_Line=EXTI_Line6; //中断线u8_pinNum
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//外部中断
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升降沿触发
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能中断
- EXTI_Init(&EXTI_InitStructure);//配置中断
- //配置中断优先级
- NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中断XX
- //stm32f103c8例子中这个优先级对应抢占优先级2子优先级3
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
- NVIC_Init(&NVIC_InitStructure); //配置优先级
-
- EXTI_ClearITPendingBit(EXTI_Line6);//清除中断标志位
- }
- #if 0
- //外部中断线0中断处理函数,这里需要回调对应的函数
- void EXTI0_IRQHandler(void){
- g_irqHandlers[0]();
- EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位
- }
- //外部中断线1中断处理函数,这里需要回调对应的函数
- void EXTI1_IRQHandler(void){
- g_irqHandlers[1]();
- EXTI_ClearITPendingBit(EXTI_Line1);//清除中断标志位
- }
- #endif
- //处理DIO tx中断或者Rx中断数据
- void EXTI6_IRQHandler(void)
- {
- g_irqHandlers[0]();
- EXTI_ClearITPendingBit(EXTI_Line6);//清除中断标志位
- }
- //将SPI、DIO0~5和Rst脚的中断去初始化
- void SX1276IoDeInit( void )
- {
- //这里省略去初始化的功能了
- }
- //判断频率是否合法
- //如果不限制频率可以直接return true
- bool SX1276CheckRfFrequency( uint32_t frequency )
- {
- // Implement check. Currently all frequencies are supported
- return true;
- }
- /**
- * 硬复位
- * 将rst引脚拉低1ms,然后将复位脚设置为无上下拉的输入模式
- */
- void SX1276Reset( void )
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能指定端口时钟(这里是为了方便ABC全开了)
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz,这里不用传参,直接写死用最大速度50MHZ
- GPIO_InitStructure.GPIO_Pin = SX1278_RST_PIN_INDEX;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //设置为推挽输出
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_Init(SX1278_RST_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
- GPIO_ResetBits(SX1278_RST_PIN_GROUP,SX1278_RST_PIN_INDEX); //输出低电平
- delay_ms(1);
-
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//浮空输入
- GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
- GPIO_Init(SX1278_RST_PIN_GROUP, &GPIO_InitStructure); //初始化GPIO
- delay_ms(6);
- }
- /**
- * 设置SPI的片选脚的电平(低电平使能,高电平取消)
- * lev:true的时候高电平,false的时候低电平
- */
- void Sx1276SetNSS(bool lev )
- {
- if(lev){
- GPIO_SetBits(SX1278_CS_PIN_GROUP,SX1278_CS_PIN_INDEX); //输出高电平
- }else{
- GPIO_ResetBits(SX1278_CS_PIN_GROUP,SX1278_CS_PIN_INDEX); //输出低电平
- }
- }
- /**
- * SPI读写函数,data是发送的数据,返回值是接收到的数据
- */
- uint8_t Sx1276SpiInOut(uint16_t data )
- {
- //完成SPI的读写功能
- uint16_t retry=0;
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){//检查指定的SPI标志位设置与否:发送缓存空标志位(缓冲区空了就可以拷贝数据了)
- if((retry++)>2000){
- //超时了
- return 0xff;
- }
- }
- SPI_I2S_SendData(SPI1, data); //通过外设SPIx发送一个数据
- retry=0;
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){ //检查指定的SPI标志位设置与否:接受缓存非空标志位(非空了就表示接收数据完成了)
- if((retry++)>2000){
- //超时了
- return 0xff;
- }
- }
- return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
- }
|