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