主函数如下: int main (void) { system_init(); edbg_usart_clock_init(); edbg_usart_pin_init(); edbg_usart_init(); system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY); while(1) { if (!rx_started) { usart_send_string("\r\n Device entered into standby sleep mode"); while(!SERCOM3->USART.INTFLAG.bit.TXC); system_sleep(); } while(rx_started); usart_send_string("\r\n Character received after wakeup : "); while(!SERCOM3->USART.INTFLAG.bit.DRE); SERCOM3->USART.DATA.reg = edbg_rx_data; } } · 。一但设定休眠模式为待机休眠模式,在whiel循环中布尔变量用来检查false状态,而函数usart_send_string用来在window终端打印消息。 。System_sleep函数将使设备进入到定义的休眠模式中。 。一但在PC终端键入一个字符,设备从休眠模式中唤醒并进入SERCOM3_Handler函数。 void SERCOM3_Handler() { if (SERCOM3->USART.INTFLAG.bit.RXS){ SERCOM3->USART.INTFLAG.bit.RXS = 1; rx_started = true; } if (SERCOM3->USART.INTFLAG.bit.RXC){ edbg_rx_data = SERCOM3->USART.DATA.reg; rx_started = false; } } 。在中断处理程序中,中断标志RXS状态-接收开始被检查。这个标志将被设置当在RxD线上检测出开始状态并且帧开始检测使能(CTRLB.SFDE是1). 。如果RXC标志被设置,布尔变量rx_started被设置为true 。现在RXC-接收完成标志被检查,一但从DATA寄存器读出被键入的字符到edbg_rx_data缓冲布尔变量rx_started被设为false。 。控制到达主函数的在rx_started缓冲键入值写入到DATA寄存器。现在它将被显示到PC终端上。 最终的在main.c文件中应用程序”SOF检测和唤醒配置”将如下: #include <asf.h> #define USART_BAUD_RATE 9600 #define USART_SAMPLE_NUM 16 #define SHIFT 32 uint8_t edbg_rx_data; volatile bool rx_started = false; /* Function prototype */ void edbg_usart_clock_init(void); void edbg_usart_pin_init(void); void edbg_usart_init(void); void usart_send_string(const char *str_buf); uint16_t calculate_baud_value(const uint32_t baudrate,const uint32_t peripheral_clock, uint8_t sample_num); /*edbg_usart handler*/ void SERCOM3_Handler() { if (SERCOM3->USART.INTFLAG.bit.RXS){ SERCOM3->USART.INTFLAG.bit.RXS = 1; rx_started = true; } if (SERCOM3->USART.INTFLAG.bit.RXC){ edbg_rx_data = SERCOM3->USART.DATA.reg; rx_started = false; } } /*Assigning pin to the alternate peripheral function*/ static inline void pin_set_peripheral_function(uint32_t pinmux) { uint8_t port = (uint8_t)((pinmux >> 16)/32); PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1; PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u))); PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u))); } /* * internal Calculate 64 bit division, ref can be found in */ static uint64_t long_division(uint64_t n, uint64_t d) { int32_t i; uint64_t q = 0, r = 0, bit_shift; for (i = 63; i >= 0; i--) { bit_shift = (uint64_t)1 << i; r = r << 1; if (n & bit_shift) { r |= 0x01; }
if (r >= d) { r = r - d; q |= bit_shift; } } return q; } /* * internal Calculate asynchronous baudrate value (UART) */ uint16_t calculate_baud_value( const uint32_t baudrate, const uint32_t peripheral_clock, uint8_t sample_num) { /* Temporary variables */ uint64_t ratio = 0; uint64_t scale = 0; uint64_t baud_calculated = 0; uint64_t temp1; /* Calculate the BAUD value */ temp1 = ((sample_num * (uint64_t)baudrate) << SHIFT); ratio = long_division(temp1, peripheral_clock); scale = ((uint64_t)1 << SHIFT) - ratio; baud_calculated = (65536 * scale) >> SHIFT; return baud_calculated; } /* EDBG UART(SERCOM3) bus and generic clock initialization */ void edbg_usart_clock_init(void) { struct system_gclk_chan_config gclk_chan_conf; uint32_t gclk_index = SERCOM3_GCLK_ID_CORE; /* Turn on module in PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_SERCOM3); /* Turn on Generic clock for USART */ system_gclk_chan_get_config_defaults(&gclk_chan_conf); //Default is generator 0. Other wise need to configure like below /* gclk_chan_conf.source_generator = GCLK_GENERATOR_1; */ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); } /* EDBG UART(SERCOM3) pin initialization */ void edbg_usart_pin_init(void) { /* PA22 and PA23 set into peripheral function C*/ pin_set_peripheral_function(PINMUX_PA22C_SERCOM3_PAD0); pin_set_peripheral_function(PINMUX_PA23C_SERCOM3_PAD1); } /* EDBG UART(SERCOM3) initialization */ void edbg_usart_init(void) { uint16_t baud_value; baud_value = calculate_baud_value(USART_BAUD_RATE,sys-tem_gclk_chan_get_hz(S /* By setting the DORD bit LSB is transmitted first and setting the RXPO bit as 1 cor-responding SERCOM PAD[1] will be used for data reception, PAD[0] will be used as TxD pin by setting TXPO bit as 0,16x over-sampling is selected by setting the SAMPR bit as 0, USART clock mode is selected as USART with internal clock by setting MODE bit into 1. */ SERCOM3->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_RXPO(0x1) | SERCOM_USART_CTRLA_TXPO(0x0) | SERCOM_USART_CTRLA_SAMPR(0x0)| SERCOM_USART_CTRLA_MODE_USART_INT_CLK ; /*baud register value corresponds to the device communication baud rate */ SERCOM3->USART.BAUD.reg = baud_value; /* 8-bits size is selected as character size by setting the bit CHSIZE as 0, TXEN bit and RXEN bits are set to enable the Transmitter and receiver*/ SERCOM3->USART.CTRLB.reg = SERCOM_USART_CTRLB_CHSIZE(0x0) | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_SFDE; /* synchronization busy */ while(SERCOM3->USART.SYNCBUSY.bit.CTRLB); /* SERCOM3 handler enabled */ system_interrupt_enable(SERCOM3_IRQn); /* receive complete interrupt,receive start interrupt set */ SERCOM3->USART.INTENSET.reg = SERCOM_USART_INTFLAG_RXC | SERCOM_USART_INTFLAG_RXS; /* SERCOM3 peripheral enabled */ SERCOM3->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; /* synchronization busy */ while(SERCOM3->USART.SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_ENABLE); } /* function used to print the character in the terminal */ void usart_send_string(const char *str_buf) { while (*str_buf != '\0') { while(!SERCOM3->USART.INTFLAG.bit.DRE); SERCOM3->USART.DATA.reg = *str_buf; str_buf++; } } int main (void) { system_init(); edbg_usart_clock_init(); edbg_usart_pin_init(); edbg_usart_init(); system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_2); while(1) { if (!rx_started) { usart_send_string("\r\n Device entered into standby sleep mode"); while(!SERCOM3->USART.INTFLAG.bit.TXC); system_sleep(); } while(rx_started); usart_send_string("\r\n Character received for wakeup : "); while(!SERCOM3->USART.INTFLAG.bit.DRE); SERCOM3->USART.DATA.reg = edbg_rx_data; } } 下图展示出SEROM_USART硬件握手应用的输出:
|