MM32W无线MCU系列产品应用笔记 —— 阻塞式例程

demi的头像
demi 发布于:周三, 11/06/2019 - 10:29 ,关键词:

本章我们将对软件架构进行简单的讲解。

阻塞式例程介绍

对于大部分的低功耗设备来说,CPU都是处在休眠模式中,只在接收到特定数据的时候被唤醒处理少量数据,这种应用场景比较适合阻塞方式运行,这种方式配置简单,CPU大部分时间都被蓝牙服务占用,在收到来自射频模块的IRQ信号时需要及时处理,因此,用户的代码不允许出现阻塞。

我们先看一下例程中的main函数:

int main(void)

{

unsigned long temp=0x800000;

SystemClk_HSEInit();               //系统时钟配置为48MHz

            

#ifdef USE_UART                    //目前只支持UART接收与发送AT指令

#ifdef USE_AT_CMD    //开启AT指令功能

SleepStop = 0x01;       //空闲时低功耗,0x00不休眠,0x01睡眠,0x02停机模式

#endif

#endif

            

#ifdef USE_UART                    //开启UART功能,修改全局宏定义改变UART和对应引脚

uart_initwBaudRate();               //波特率默认9600,可以修改uart.c中的BaudRate变量

#endif

            

#ifdef USE_I2C                        //开启I2C功能

IIC_Init(I2C1);               // I2C1,标准模式,SCL PB6 ,SDA PB7 ,SendDataFlag PA10

#endif

 

#ifdef USE_USB                      //开启USB功能

usb_test();                    //使用PA11、PA12,枚举为USB HID设备

#endif

 

//SysTick_Count每1ms加一,系统时钟改变时应调用SysTick_Config()函数

SysTick_Configuration();           

            

//启用SPI2,在芯片内部与射频模块通信,速度应不低于6Mhz

SPIM_Init(SPI2,/*0x06*/0x06); 

            

IRQ_RF();         //配置PB8的IRQ 功能处理射频模块信号,用于低功耗唤醒

            

while(temp--);                //延时,方便烧录程序

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,

}

对于蓝牙,必要的系统资源有:用于计时的Systick和与射频模块通信的SPI2,Systick使用SysTick_Count变量计时,也可以使用这个变量主动避开与IRQ处理任务的冲突;

目前程序支持RUN MODE,SLEEP MODE,STOP MODE模式,其中,在stop模式下MCU可以通过任意一个外部中断线唤醒,比如MM32W073NTB封装,在芯片设计上将IRQ与PB8共用一个GPIO口,在MM32W073PFB封装上,IRQ是独立的GPIO,需要用户在设计时将IRQ连接到任意一个GPIO口修改外部中断唤醒源即可实现stop唤醒模式;

例程中通过修改全局宏定义,可以启用UART、IIC和USB,目前都支持AT指令方式;

蓝牙的广播间隔由ble_run()中的参数决定,单位为0.625ms;

与中断式例程不同的地方:

① 蓝牙服务会定时调用接口函数McuGotoSleepAndWakeup();

② ble_run()是一个阻塞函数,后续程序将不会执行,中断模式中ble_run参数为0,且不是阻塞函数;

③ 中断式例程中蓝牙广播间隔由ble_run_interrupt_start()函数的参数决定,阻塞式例程中蓝牙广播间隔由ble_run()的参数决定;


图2 阻塞式程序流程

阻塞式程序流程如上图。实际使用中,蓝牙服务将定时调用UsrProcCallback()函数,在连接后允许时调用gatt_user_send_notify_data_callback()。两个函数的处理时间应尽可能短,不能影响IRQ信号的处理,否则可能出现蓝牙连接断开、无蓝牙广播等问题。

我们可以将用户程序放在callback.c的UsrProcCallback()函数中定时执行,如例程中的AT指令的处理CheckAtCmdInfo()函数,注意不要阻塞。可以将发送自身状态的程序放在gatt_user_send_notify_data_callback()函数中,同样不得阻塞。

来源:灵动MM32MCU

围观 14