工业控制 | 能源技术 | 汽车电子 | 通信网络 | 安防监控 | 智能电网 | 移动手持 | 无线技术 | 家用电器 | 数字广播 | 消费电子 | 应用软件 | 其他方案

电路设计->综合电路图->综合电路图->Silicon Labs SIM3L1xx UART0 与 PM8 唤醒编程指导

Silicon Labs SIM3L1xx UART0 与 PM8 唤醒编程指导

作者:angelazhang时间:2015-09-27

一、Precision32 SiM3L1xx MCU 简介:
      高性能模拟与混合信号 IC 领导厂商Silicon Laboratories (芯科实验室)推出业界基于ARM® Cortex™-M3 处理器的最低功耗单片机(MCU)系列产品和首款具有“功耗感知”功能的开发工具。Precision32 SiM3L1xx MCU 及开发环境利用创新的混合信号技术,使开发人员在3.6V 工作电压下,工作模式功耗降低到175μA/MHz,并且在启用实时时(RTC)的情况下,休眠模式功耗降低到250nA 以下。新型超低功耗混合信号MCU 是智能仪表、仪器监测、家庭自动化、无线安全、资产跟踪、个人医疗装置以及其他连接到物联网(IoT)的功耗敏感型应用的理想选择。


1、PM8 模式:
       SIM3L1xx 有多种工作模式,本文主要介绍PM8 模式。PM8 是一个低功耗的睡眠模式。详细的描述见下表:


在PM8 模式下,内置的LDO 模块被禁止,RTC0,UART0,LPTimer0,PORT Match,LCD 等模块是工作的,并且可以保留所有的RAM 数据。

2UART0 简介:
      UART0 是Silicon Labs MCU 里面为低功耗数据通信特别设计的。可以在PM8 模式下唤醒MCU 并实现数据通信。与PM8 相关的特性有以下:
     * 独立的16bit 波特率发生器
     * 在PM8 模式下可以使用RTC0 输出的时钟,此时RTC0 模块运行的时钟源可
以为外部32.768KHZ 的振荡器。
     * 在PM8 模式下,可支持的速率是9600bps, 4800bps, 2400bps or 1200bps
     * 可以作为PM8 模式的唤醒源。
     * 引脚描述:
     UART0 有专用端口I / O 引脚。当UART0 被启用,它是自动映射到相应的引脚,

 如表37.1 所示。

UART0_TX 和UART0_RX 引脚配置示例代码:
// UART PINS TO PROPER CONFIG (TX = PB1.2, RX = PB1.3)
SI32_PBSTD_A_set_pins_push_pull_output(SI32_PBSTD_1, 0x0000004);
SI32_PBSTD_A_set_pins_digital_input(SI32_PBSTD_1, 0x00000008);
SI32_PBSTD_A_write_pbskipen(SI32_PBSTD_1, 0x0000000C);
二、PM8 模式下UART0 编程介绍:
1、初始化UART0
//------------------------------------------------------------------
void gUART0_enter_async_rtc_config()
{
// ENABLE UART0 CLOCK
SI32_CLKCTRL_A_enable_apb_to_modules_0(SI32_CLKCTRL_0,
SI32_CLKCTRL_A_APBCLKG0_UART0);
SI32_CLKCTRL_A_enable_apb_to_modules_1(SI32_CLKCTRL_0,
SI32_CLKCTRL_A_APBCLKG1_MISC0);
// SETUP UART. BAUD RATE (APB = System Clock)
SI32_UART_B_enter_full_duplex_mode(SI32_UART_0);
// RTC Timer Clock Modes (9600 baud)
SI32_UART_B_select_rtc_clock_mode(SI32_UART_0);
SI32_UART_B_set_tx_baudrate(SI32_UART_0, 0x03);
SI32_UART_B_set_rx_baudrate(SI32_UART_0, 0x03);
// SETUP TX (8-bit, 1stop, no-parity)
SI32_UART_B_select_tx_data_length(SI32_UART_0, 8);
SI32_UART_B_enable_tx_start_bit(SI32_UART_0);
SI32_UART_B_enable_tx_stop_bit(SI32_UART_0);
SI32_UART_B_disable_tx_parity_bit(SI32_UART_0);
SI32_UART_B_select_tx_stop_bits(SI32_UART_0,
SI32_UART_B_CONFIG_TSTPMD_1_STOP_VALUE);
SI32_UART_B_disable_tx_signal_inversion(SI32_UART_0);
SI32_UART_B_select_tx_fifo_threshold_for_request_to_1(SI32_UART_0
);
SI32_UART_B_enable_tx_output(SI32_UART_0);
SI32_UART_B_enable_tx(SI32_UART_0);
// SETUP RX
SI32_UART_B_select_rx_data_length(SI32_UART_0, 8);
SI32_UART_B_enable_rx_start_bit(SI32_UART_0);
SI32_UART_B_enable_rx_stop_bit(SI32_UART_0);
SI32_UART_B_disable_rx_parity_bit(SI32_UART_0);
SI32_UART_B_select_rx_stop_bits(SI32_UART_0,
SI32_UART_B_CONFIG_TSTPMD_1_STOP_VALUE);
SI32_UART_B_disable_rx_signal_inversion(SI32_UART_0);
SI32_UART_B_select_rx_fifo_threshold_1(SI32_UART_0);
SI32_UART_B_enable_rx(SI32_UART_0);
//flush RX TX fifo
SI32_UART_B_flush_rx_fifo(SI32_UART_0);
SI32_UART_B_flush_tx_fifo(SI32_UART_0);
SI32_UART_B_enable_tx_complete_interrupt(SI32_UART_0);
SI32_UART_B_enable_rx_data_request_interrupt(SI32_UART_0);
NVIC_ClearPendingIRQ (UART0_IRQn);
NVIC_EnableIRQ(UART0_IRQn);
SI32_UART_B_write_clkdiv(SI32_UART_0,0);
}
2、UART0 中断响应函数:
以下程序是一个简单的回发所接收的数据。可以根据需要更改代码:
void UART0_IRQHandler(void)
{
uint8_t R_data;
NVIC_ClearPendingIRQ(UART0_IRQn);
//clear wakeup flags
SI32_PMU_A_clear_wakeup_flags(SI32_PMU_0);
if (SI32_UART_B_is_rx_data_request_interrupt_pending(SI32_UART_0))
{
//hardware will clear Rx request interrupt flag
R_data = SI32_UART_B_read_data_u8(SI32_UART_0);
SI32_UART_B_write_data_u8(SI32_UART_0, R_data);
}
if (SI32_UART_B_is_tx_complete(SI32_UART_0))
{
//must clear Tx complete interrupt flag by soft
SI32_UART_B_clear_tx_complete_interrupt(SI32_UART_0);
//flush rx fifo,prepare to receive next data
SI32_UART_B_flush_rx_fifo(SI32_UART_0);
SI32_UART_B_flush_tx_fifo(SI32_UART_0);
}
}


3、数据的接收与发送:
A 发送数据的流程:
1.往移位寄存器写入需要发送的数据,例如写入8bit 数据:
SI32_UART_B_write_data_u8(SI32_UART_0, R_data);
2.确保发送器没有被抑制(TINH = 0)
3.使能数据发送器(TEN = 1)
数据发送完毕会有一个发送完成的标志位 (TCPTI),这个标志位在中断响应完需
要软件清零。
B 数据接收流程:
接收数据的中断请求标志位(RDREQI)在接收FIFO 的数据个数大于等于FIFO
所设置的接收个数阀值(RFTH)时产生。这时可以从接收FIFO 中读取数据。接
收数据的中断启用通过设置接收数据请求中断使能标志位(RDREQIEN)1。接
收FIFO 填充中的条目的数量降到低于RFTH 设置时,会自动清除。


4、PM8 与 UART0 唤醒:
进入PM8模式前,配置UART0作为PM8的唤醒源,并使能UART0中断:
//enable UART0 wakeup
SI32_PMU_A_enable_uart0_wake_event(SI32_PMU_0);
NVIC_ClearPendingIRQ (UART0_IRQn);
NVIC_EnableIRQ(UART0_IRQn);
SI32_PMU_A_clear_wakeup_flags(SI32_PMU_0);


5、进入PM8 模式:
进入 PM8 模式之前配置好期望的设置,例如RTC 的设置,因为UART0 在PM8 模
式下需要使用RTC 的输出时钟。
void PowerMode_8(void)
{
SI32_CLKCTRL_A_enable_power_mode_8(SI32_CLKCTRL_0);
SI32_LDO_A_select_digital_bias_high(SI32_LDO_0);
SI32_LDO_A_select_memory_bias_high(SI32_LDO_0);
SI32_LDO_A_select_analog_bias_high(SI32_LDO_0);
// Enable the retention mode of RAM banks needed by the application
// Enable retention on all 32 kB of RAM
SI32_PMU_A_set_ram_retention_enable_mask(SI32_PMU_0, 0xFF);
// Set the pins in the lowest power configuration for this mode.
SI32_PBSTD_A_write_pins_high(SI32_PBSTD_1, 0x00F0);
// Set all LDOs to 1.8 V output.
SI32_LDO_A_write_control(SI32_LDO_0, 0x00343434);
//RTC Crystal Settings
SI32_RTC_B_disable_low_frequency_oscillator(SI32_RTC_0);
SI32_RTC_B_disable_low_frequency_oscillator_output(SI32_RTC_0);
SI32_RTC_B_enable_auto_gain_control(SI32_RTC_0);
SI32_RTC_B_disable_bias_doubler(SI32_RTC_0);
//Disable the SysTick timer.
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
SI32_PMU_A_clear_wakeup_flags(SI32_PMU_0);
// ENABLE INTERRUPTS
SI32_PMU_A_enable_uart0_wake_event(SI32_PMU_0);
NVIC_ClearPendingIRQ (UART0_IRQn);
NVIC_EnableIRQ(UART0_IRQn);
SI32_PMU_A_clear_wakeup_flags(SI32_PMU_0);
// Set the SLEEPDEEP bit in the core.
SCB->SCR = SCB_SCR_SLEEPDEEP_Msk; // set SLEEPDEEP
// Execute the DSB (Data Synchronization Barrier), ISB (Instruction
// Synchronization Barrier), and WFI (Wait for Interrupt) or WFE (Wait for
// Event) instructions. For SiM3L1xx devices, WFI and WFE have the same
// behavior
__DSB();
__ISB();
__WFI();
// Wake from PM8
// The watchdog timer is re-enabled after a PM8, so disable it again after
SI32_WDTIMER_A_stop_counter(SI32_WDTIMER_0);
// exiting PM8
SI32_PMU_A_disable_uart0_wake_event(SI32_PMU_0);
SI32_PMU_A_clear_wakeup_flags(SI32_PMU_0);
LDOConfigure();
}
以上程序是进入PM8 模式的代码,整个进入PM8 模式和退出PM8 模式的流程是:
1)、通过软件配置,使得MCU 进入PM8。
2)、UART0 在PM8 模式下保持工作,等待接收数据,如果有数据过来首先进入数
据接收中断响应函数。然后回到睡眠点,继续往下运行。
3)、在UART0唤醒MCU退出PM8模式需要特别注意,唤醒后需要马上关闭UART0
的事件唤醒功能SI32_PMU_A_disable_uart0_wake_event(SI32_PMU_0);
在需要进入PM8模式之前再次开启这个事件唤醒功能即可。
4)、在PM8模式下,看门狗是不工作的,但是无需为时钟失效的问题担心,因为这
款MCU具备RTC时钟失效检测,RTC时钟失效后,会自动切换到内部低功耗时钟,
并产生RTC时钟失效中断,可以保证MCU可靠的运行。


6、调试建议:
在调试PM8模式时,如果程序需要自动进入PM8模式,而非手动按键条件下进入。
这时候,如果没有调试好会出现进入睡眠不能唤醒的状态,也就是芯片一直处于PM8
模式,程序中却没有有效的唤醒源可以唤醒MCU。
建议:在main函数中,加入按键陷阱:
int main(void)
{
while (!SI32_PBSTD_A_read_pin(SI32_PBSTD_1, 4)); //pin 4
//add the app code here
While(1)
{
…………
}
}
1、由于代码会自动进入PM8模式,如果已经出现调试失败的时候,可以按住按键,
使得在重新下载代码的时候不会进入PM8模式,导致烧写代码失败而不能继续调试。
2、如果真的出现调试失败却不能再烧入程序的情况怎么办?这时候就要使用一个工
具强制删除芯片的代码。具体操作如下:
To fix this problem if it has already occurred:
1) Use the command line to navigate to
<C:\Silabs\Precision32_v1.0.1\Utilities\FlashProgrammer> (default install
location). This tool is also available for download at SiLabs.com
2) Run the following command: "si32flashutility.exe -e 2 -r 2" This willerase the MCU flash memory.
如果第二步未能成功擦除芯片flash代码,请尝试第三步:
3) Run the following command: "si32flashutility.exe -r 1 -e 2" This will
erase the MCU flash memory.
如果出现下图的界面,表明擦除成功:



标注:为了试验方便,图片中FlashProgrammer文件夹被拷贝到了C:\Silabs\目录下。
默认的路径是:C:\SiLabs\Precision32_v1.1.0\Utilities\FlashProgrammer
3、在测试PM8功耗时,请把仿真器从PCB板上移除。如果不移除会给测量带来超过
60uA的额外电流。



评论

技术专区