本文主要是關于CC1101的相關介紹,并著重對CC1101驅動在STM32F103的移植進行了詳盡的闡述。
淺談CC1101驅動在STM32F103的移植
首先明確:CC1101是通過SPI與MCU進行通信的。根據(jù)從TI官方上獲得CC1101驅動,直接先移植SPI部分,STM32F103提供了SPI1和SPI2兩條SPI總線,可自行選擇,對于SPI的移植,直接參考STM32開發(fā)板上關于通過SPI操作Flash示例代碼,對于SPI的配置與TI提供的驅動代碼里的SPI配置保持一致。SPI移植完成之后,接上CC1101射頻模塊,測試SPI是否能正常通信,主要通過向CC1101任意可讀可寫寄存器寫一個任意值,然后再讀出該寄存器里的值,通過串口打印出該值,通過以上操作判斷SPI是否正常通信,SPI移植是否成功。當然,這里使用到了串口,所以需要同時將串口的代碼實現(xiàn),同樣參考串口實例。
其次,當STM32與CC1101的SPI通信完成后,果斷開始CC1101后續(xù)驅動的移植。移植過程中,所有變量名、函數(shù)名與TI提供的驅動里的保持一致,當然CC1101寄存器配置也保持移植。對于移植初期,我并沒有太多的關心CC1101的時序問題,只關心怎么去移植,這也是自己的一個不好的習慣,所以初期移植的時候,對著TI提供的驅動代碼,TI代碼里有什么函數(shù),我也移植什么函數(shù);函數(shù)里有CS管腳的操作,也對應在操作在STM32下定義的CS管腳;TI里延時多長,我也跟著在STM32下延時相應的時間。整個驅動移植下來,關于CC1101的驅動函數(shù)也大多了然在心了。
最后,TI驅動里提供的是輪詢的方式收發(fā)數(shù)據(jù),對于初期來說,首先需要實現(xiàn)CC1101的工作,編譯調試移植到STM32上的CC1101驅動代碼,看見數(shù)據(jù)從接收端串口打印出的那瞬間,心情真心不錯基于STM32F103的CC1101驅動移植。
當然,輪詢的方式并不適合我在實際中應用,改用中斷方式接收數(shù)據(jù),且使用FIFO小于64BYTE,對于中斷接收,做如下總結:
方法一:配置寄存器IOCFGx.GDOx_CFG=0x06(可查看CC1101數(shù)據(jù)手冊通用引腳部分),以下降沿觸發(fā)中斷。
方法二:配置寄存器IOCFGx.GDOx_CFG=0x01,以上升降沿觸發(fā)中斷。
對于中斷的試用,具體可根據(jù)對IOCFGx.GDOx_CFG的配置實現(xiàn)。
本以為,這樣之后就完成了CC1101的驅動移植,最后才知道,自己菜得不行,移植的代碼只是純粹的數(shù)據(jù)收發(fā),當導師問道有無CCA、CS檢測等等,我就茫然了,恰好又是期末了,大牛導師最后自己去重新移植了有CCA檢測機制的驅動(主要參考TI官方提供的SimpliciTI代碼),心里真心難受基于STM32F103的CC1101驅動移植,好失敗,后期只對CC1101驅動進行了維護和改進。
關于在后期維護和改進中,主要解決兩個問題:
1.通信距離
測試參考SimpliciTI移植的CC1101驅動,其通信距離只有20幾米,能穿透一堵墻,無法滿足我們的需求,通過增加發(fā)射功率PA值,通信距離也不太明顯。查閱資料,通信距離與應用環(huán)境、通信速率、PA等有關,與是準備將它通信速率(TI提供的是空中速率為250K的),修改為10K的速率,開始以為純粹配置一下MDMCFG3 為10K就行,但最終是必須配置channel filter bandwidth 、frequency deviation等,這些配置均建議通過TI提供的SmartRF Studio 軟件進行配置。速率改變也必須注意CCA監(jiān)測過程中RSSI可用等待時間,RSSI可參考其TI提供的DN505文檔。最后,通過降低傳輸速率,將PA值設為10db,測試通信距離在空曠場地下可達到200多米,可穿透三堵墻,已經(jīng)滿足項目需要。但測試期間,修改后的10K速率驅動,經(jīng)常CCA檢測失敗,雖然通過DN505文檔修改了RSSI等待的時間,但依舊這樣,最終此問題糾結了我3天,最后突發(fā)奇想地去修改了調制解調方式為2-FSK后,CCA檢測正常運行,至今還是沒明白為什么會這樣。
2.關于GDO0的問題
由于項目中是定時發(fā)送數(shù)據(jù),接收端采用GDO0以中斷方式接收數(shù)據(jù),但在測試中發(fā)現(xiàn),終端正常運行不定時間后,中斷無法產(chǎn)生,調試為發(fā)現(xiàn)FIFO溢出等,通過去TI論壇上查找,發(fā)現(xiàn)有類似問題,但沒有徹底的解決方法,目前主要通過設置定時閾值,超過閾值未接收到數(shù)據(jù),就判定為GDO0中斷出現(xiàn)問題,便執(zhí)行FIFO刷新操作,然后終端又能繼續(xù)正常運行,
CC1101與STM32的低功耗
1.stm32低功耗
(1)進入stop模式
由于項目需要在睡眠時也保留RAM的數(shù)據(jù),顧考慮采用stop模式以減少STM32 的功耗,進入stop的方法很簡單,直接調用庫函數(shù)中的 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); 此處,我選擇了關閉電壓轉換器以進一步降低功耗,使用指令WFI進入,關于STOP進入方式的選擇,可參考前文提供的博客。
(2)STM32的喚醒
由于,應用中采用發(fā)送完數(shù)據(jù)變進入休眠,并定時喚醒發(fā)送,且STOP模式下RTC正常工作,所以在本應用中采用了RTC鬧鐘周期中斷喚醒,對于RTC的使用即配置可如下:
void RTC_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
#ifdef RCC_LSE
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
#else
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
#endif
RCC_RTCCLKCmd(ENABLE);
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_ALR, ENABLE);
RTC_WaitForLastTask();
RTC_Alarm_Interrupt(DISABLE);
}
以上,主要注意RTC時鐘的選擇,選擇RCC_LSE ,時間比較精確,但會產(chǎn)生相對長一點的喚醒時延選擇;RCC_LSI,時間則不那么準確,且功耗要多一點,但產(chǎn)生的喚醒時延較小,具體可查閱STM32使用手冊關于低功耗部分的介紹。
2.CC1101低功耗
(1)進入掉電模式
CC1101進入IDEL狀態(tài) 一》 使用掉電模式(SPWD)即可。
(2)喚醒
直接操作拉低CS管腳即可。
3.調試低功耗
前期調試,只分別測試了STM32和CC1101在休眠功能上的實現(xiàn),即是否能進入休眠以及是否能夠成功進行喚醒,未對實際功耗進行測試(由于硬件的特殊性)。
后期第一次測試STM32+CC1101整體模塊低功耗模式下功耗為4點幾mA,頓時就無語了關于STM32低功耗+CC1101低功耗;然后果斷挑斷模塊上的所有LED燈,再次測試,功耗直接降到1mA左右,此時雖然有所下降,但離手冊上的幾uA真不是一個檔次的,但對于菜鳥的我此時根本不知道怎么繼續(xù)減少功耗了,好吧,我只有去茫茫網(wǎng)絡中尋找低功耗的蛛絲馬跡了,果然在http://www.openedv.com/posts/list/18372.htm#116532里找到了希望,真心感謝博主的分享,于是趕緊把用到的SPI管腳以及串口管腳安裝博主提供的修改,并關閉所有不用的PIN,但最終測試功耗依然未降低,這就納悶了,為啥還是每降低呢關于STM32低功耗+CC1101低功耗,突然想起了不久前看過的STM32L系列低功耗的芯片,同時在有個低功耗經(jīng)驗師兄的提醒下,果斷參考了其官方提供的超低功耗代碼關于STM32低功耗+CC1101低功耗,并在自己的項目中進行如下操作:
在每次進入休眠前:
#關閉所有時鐘以及外設(如本項目中用到的串口、SPI、timer)
#將所有I/O口改為GPIO_Mode_AIN狀態(tài)
void DisableGPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure
;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC\
|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);
//Configure all GPIO port pins in Analog Input mode (floating input trigger OFF)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_Init(GPIOE, &GPIO_InitStructure);
//GPIOs Periph clock disable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC
|RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, DISABLE);
}
在每次喚醒后:
#開啟休眠前所關閉的對應時鐘以及外設
#初始化使用到的GPIO口
添加了如上的處理后,再次測試低功耗,終于讓我看見了uA級別的功耗關于STM32低功耗+CC1101低功耗,但功耗最低時在40uA左右,與根據(jù)芯片手冊提供的低功耗數(shù)據(jù)相比,還是有很大的距離,不過至此,通過軟件進一步實現(xiàn)低功耗,我已經(jīng)無法再想到其他的方法,外設該關的都已經(jīng)關掉,功耗在40uA左右,目前能想到的就是硬件上功耗降降低,
結語
關于CC1101的相關介紹就到這了,如有不足之處歡迎指正。
相關閱讀推薦:基于STM32驅動CC1101的程序分析-
芯片
+關注
關注
450文章
49616瀏覽量
417080 -
CC1101
+關注
關注
4文章
35瀏覽量
23017
發(fā)布評論請先 登錄
相關推薦
評論