MM32W無(wú)線MCU系列產(chǎn)品應(yīng)用筆記 —— 阻塞式例程
在上一章節(jié),我們了解了MM32W0系列藍(lán)牙模塊的中斷式例程,也使用AT指令對(duì)模塊進(jìn)行了簡(jiǎn)單的操作。下面我們將對(duì)軟件架構(gòu)進(jìn)行簡(jiǎn)單的講解。阻塞式例程介紹
對(duì)于大部分的低功耗設(shè)備來(lái)說(shuō),CPU都是處在休眠模式中,只在接收到特定數(shù)據(jù)的時(shí)候被喚醒處理少量數(shù)據(jù),這種應(yīng)用場(chǎng)景比較適合阻塞方式運(yùn)行,這種方式配置簡(jiǎn)單,CPU大部分時(shí)間都被藍(lán)牙服務(wù)占用,在收到來(lái)自射頻模塊的IRQ信號(hào)時(shí)需要及時(shí)處理,因此,用戶(hù)的代碼不允許出現(xiàn)阻塞。
我們先看一下例程中的main函數(shù):
int main(void){
unsigned long temp=0x800000;
SystemClk_HSEInit(); //系統(tǒng)時(shí)鐘配置為48MHz
#ifdef USE_UART //目前只支持UART接收與發(fā)送AT指令
#ifdef USE_AT_CMD //開(kāi)啟AT指令功能
SleepStop = 0x01; //空閑時(shí)低功耗,0x00不休眠,0x01睡眠,0x02停機(jī)模式
#endif
#endif
#ifdef USE_UART //開(kāi)啟UART功能,修改全局宏定義改變UART和對(duì)應(yīng)引腳
uart_initwBaudRate(); //波特率默認(rèn)9600,可以修改uart.c中的BaudRate變量
#endif
#ifdef USE_I2C //開(kāi)啟I2C功能
IIC_Init(I2C1); // I2C1,標(biāo)準(zhǔn)模式,SCL PB6 ,SDA PB7 ,SendDataFlag PA10
#endif
#ifdef USE_USB //開(kāi)啟USB功能
usb_test(); //使用PA11、PA12,枚舉為USB HID設(shè)備
#endif
//SysTick_Count每1ms加一,系統(tǒng)時(shí)鐘改變時(shí)應(yīng)調(diào)用SysTick_Config()函數(shù)
SysTick_Configuration();
//啟用SPI2,在芯片內(nèi)部與射頻模塊通信,速度應(yīng)不低于6Mhz
SPIM_Init(SPI2,/*0x06*/0x06);
IRQ_RF(); //配置PB8的IRQ 功能處理射頻模塊信號(hào),用于低功耗喚醒
while(temp--); //延時(shí),方便燒錄程序
radio_initBle(0x48, &ble_mac_addr); //初始化射頻模塊(3dBm),并獲取MAC地址
printf("\r\nMAC:%02x-%02x-%02x-%02x-%02x-%02x\r\n", ble_mac_addr[5],ble_mac_addr[4],ble_mac_addr[3],ble_mac_addr[2],ble_mac_addr[1],ble_mac_addr[0]);
ble_run(160*2); //廣播間隔320*0.625=200 ms,
}
對(duì)于藍(lán)牙,必要的系統(tǒng)資源有:用于計(jì)時(shí)的Systick和與射頻模塊通信的SPI2,Systick使用SysTick_Count變量計(jì)時(shí),也可以使用這個(gè)變量主動(dòng)避開(kāi)與IRQ處理任務(wù)的沖突;
目前程序支持RUN MODE,SLEEP MODE,STOP MODE模式,其中,在stop模式下MCU可以通過(guò)任意一個(gè)外部中斷線喚醒,比如MM32W073NTB封裝,在芯片設(shè)計(jì)上將IRQ與PB8共用一個(gè)GPIO口,在MM32W073PFB封裝上,IRQ是獨(dú)立的GPIO,需要用戶(hù)在設(shè)計(jì)時(shí)將IRQ連接到任意一個(gè)GPIO口修改外部中斷喚醒源即可實(shí)現(xiàn)stop喚醒模式;
例程中通過(guò)修改全局宏定義,可以啟用UART、IIC和USB,目前都支持AT指令方式;
藍(lán)牙的廣播間隔由ble_run()中的參數(shù)決定,單位為0.625ms;
與中斷式例程不同的地方:
① 藍(lán)牙服務(wù)會(huì)定時(shí)調(diào)用接口函數(shù)McuGotoSleepAndWakeup();
② ble_run()是一個(gè)阻塞函數(shù),后續(xù)程序?qū)⒉粫?huì)執(zhí)行,中斷模式中ble_run參數(shù)為0,且不是阻塞函數(shù);
③ 中斷式例程中藍(lán)牙廣播間隔由ble_run_interrupt_start()函數(shù)的參數(shù)決定,阻塞式例程中藍(lán)牙廣播間隔由ble_run()的參數(shù)決定;
圖1 阻塞式程序流程
阻塞式程序流程如上圖。實(shí)際使用中,藍(lán)牙服務(wù)將定時(shí)調(diào)用UsrProcCallback()函數(shù),在連接后允許時(shí)調(diào)用gatt_user_send_notify_data_callback()。兩個(gè)函數(shù)的處理時(shí)間應(yīng)盡可能短,不能影響IRQ信號(hào)的處理,否則可能出現(xiàn)藍(lán)牙連接斷開(kāi)、無(wú)藍(lán)牙廣播等問(wèn)題。
我們可以將用戶(hù)程序放在callback.c的UsrProcCallback()函數(shù)中定時(shí)執(zhí)行,如例程中的AT指令的處理CheckAtCmdInfo()函數(shù),注意不要阻塞?梢詫l(fā)送自身狀態(tài)的程序放在gatt_user_send_notify_data_callback()函數(shù)中,同樣不得阻塞。
如需要了解更多靈動(dòng)微MCU產(chǎn)品,請(qǐng)聯(lián)系靈動(dòng)微核心代理商-穎特新科技
編輯:ls 最后修改時(shí)間:2022-06-07