LPUART(Low power universal asynchronous receiver transmitter,低功耗通用異步收發(fā)器),相比標準的UART,其功耗極低,支持在低功耗模式下運行,并且可以將MCU從低功耗模式喚醒。
本文介紹MM32全新低功耗系列MM32L0130的LPUART外設,實現基本UART收發(fā)通信、通過UART中斷使MCU從低功耗模式中喚醒。
1 LPUART 簡介
1.1 LPUART功能框圖
1.2 LPUART功能特征
支持UART幀格式的全雙工異步數據收發(fā)。
支持輸入任意頻率的時鐘源,可配置為LSE/LSI/PCLK。
支持可編程的波特率數據傳輸,發(fā)送和接收時可采用3、4分頻交替,防止累計誤差。
可配置奇偶校驗位、停止位。
可配置收發(fā)數據信號取反。
2 LPUART時鐘配置
LPUART時鐘源配置寄存器在RCC_CFGR2中的位0和位1,可配置LSE、LSI、PCLK作為時鐘源。
3 LPUART中斷與喚醒
支持的中斷源:
接收緩沖溢出
幀錯誤
奇偶校驗錯誤
接收器檢測到下降沿
接收器完整接收 1byte 數據
接收器完整接收數據且與預設數據匹配
發(fā)送器數據完成發(fā)送
發(fā)送器緩沖空
支持低功耗模式下的喚醒源:
接收器檢測到下降沿喚醒
接收器檢測到起始位喚醒
接收器1字節(jié)接收完成喚醒
接收器1字節(jié)數據接收并匹配喚醒
4 接收和發(fā)送時序
由于LPUART工作時鐘不是波特率的整數倍,采用固定分頻系數的話會引入累計誤差,所以在接收和發(fā)送的時候采用3、4分頻交替進行接收和發(fā)送,每個bit采樣一次,每個bit采用3分頻還是4分頻由MCTL寄存器控制,接收和發(fā)送時序圖如下:
當LPUART工作時鐘配置為標準的32.768KHz時,軟件可配置BREN為0,然后根據通信波特率調整調制寄存器MCTL,建議配置參數如下表:
5 LPUART寄存器概覽
6 LPUART實現普通UART功能配置步驟
- 開啟LPUART所選時鐘源
- 配置RCC_CFGR2寄存器選擇LPUART時鐘
- 配置 LPUBAUD 寄存器決定波特率
- 根據波特率選擇合適的調制參數,配置 MCTL 寄存器
- 配置 LPUCON 寄存器,選擇幀格式、極性、中斷參數等
- 配置 LPUEN 寄存器打開發(fā)送、接收使能
7 發(fā)送和接收數據
發(fā)送數據:
將待發(fā)送的數據寫入LPUTXD,當發(fā)送完成時,LPUSTA的TXE標志位會被硬件置起,表示數據已傳入移位寄存器,發(fā)送 buffer為空。此時可往LPUTXD寫入下一個數據。軟件向發(fā)送buffer寫數據時TXE標志位自動清零。
接收數據:
當接收一個完整幀時,LPUSTA的RXF標志位置起,表示已完整接收數據,此時軟件可讀取LPURXD讀出接收到的數據。軟件讀LPUDATA寄存器時,RXF標志位自動清零。
8 LPUART功能實現代碼
首先編寫基礎UART的代碼,通過輪詢的方式發(fā)送和接收數據。然后添加中斷代碼,實現通過LPUART將MCU從低功耗模式喚醒。
8.1 基于LSE時鐘的基礎UART功能實現代碼
a.
開啟BKP、LSE時鐘,待LSE時鐘穩(wěn)定,使能LPUART時鐘:
RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON);
DELAY_Ms(100);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {;}
RCC_APB2PeriphClockCmd(RCC_APB2ENR_LPUART1, ENABLE);
b.
配置LPUART的LPUART_InitTypeDef結構體參數:
LPUART_InitTypeDef init_struct;
init_struct.LPUART_Clock_Source = 0; //時鐘源選擇
init_struct.LPUART_BaudRate = LPUART_Baudrate_9600; //波特率選擇9600
init_struct.LPUART_WordLength = LPUART_WordLength_8b; //8位數據位
init_struct.LPUART_StopBits = LPUART_StopBits_1; //1位停止位
init_struct.LPUART_Parity = LPUART_Parity_No; //沒有校驗位
init_struct.LPUART_MDU_Value = 0x952; //波特率調制控制寄存器
init_struct.LPUART_NEDET_Source = LPUART_NegativeDectect_Source2;//下降沿采樣使能
init_struct.LPUART_RecvEventCfg = LPUART_RecvEvent_Start_Bit;//中斷檢測模式
LPUART_Init(LPUART1, &init_struct);
LPUART_Cmd(LPUART1, ENABLE);
c.
設置LPUART引腳復用,例程復用到PA4、PA5:
GPIO_InitTypeDef GPIO_InitStruct;
RCC_GPIO_ClockCmd(GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_3);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_3);
//LPUART1_TX GPIOA.4
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//LPUART1_RX GPIOA.5
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
d.
編寫發(fā)送函數:
void Output_Byte(LPUART_TypeDef* lpuart, uint8_t dat)
{
LPUART_SendData(lpuart, dat);
while(!LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_TXE));
}
e.
編寫輪詢接收函數:
uint8_t Input_Byte(LPUART_TypeDef* lpuart)
{
uint8_t temp;
while(1) {
if(LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_RXF)) {
//read LPUART_LPUSTA_RXF bit and clear
temp = (uint8_t)LPUART_ReceiveData(lpuart);
break;
}
}
if(temp == 0xd) {
return 0;
}
return temp;
}
f.
編寫實驗樣例:
void LPUART_TxRx_Test(void)
{
uint8_t temp, i;
char string[] = "LPUART polling test!\\r\\n";
for(i = 0; i < strlen(string); i++)
{
Output_Byte(LPUART1, string[i]);
}
while(1)
{
temp = Input_Byte(LPUART1);
if(temp != 0)
{
Output_Byte(LPUART1, temp);
}
}
}
g.
在main函數中配置好LPUART后,調用LPUART_TxRx_Test函數,可得到如下實驗結果:
8.2 在上述基本LPUART配置的基礎上增加中斷配置代碼,實現喚醒低功耗模式中的MCU
a.
開啟SYSCFG、PWR時鐘:
RCC_APB2PeriphClockCmd(RCC_APB2ENR_SYSCFG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
b.
EXTI模塊可以產生中斷請求,用來喚醒低功耗模式中的MCU,LPUART連接到EXTI22,使能EXTI22:
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_StructInit(&EXTI_InitStruct);
EXTI_InitStruct.EXTI_Line = EXTI_Line22;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
c.
配置NVIC:
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = LPUART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPriority = 1;
NVIC_Init( &NVIC_InitStruct);
d.
清除接收標志并打開接收中斷:
LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
LPUART_ITConfig(LPUART1, LPUART_LPUCON_RXIE, ENABLE);
e.
定義RX緩存,然后編寫中斷服務函數:
char rxDataBuf[10], cnt = 0;
uint8_t cnt_flag = 0;
void LPUART1_IRQHandler()
{
if(LPUART_GetFlagStatus(LPUART1, LPUART_LPUSTA_START))
{
LPUART_ClearFlagStatus(LPUART1, LPUART_LPUSTA_START);
}
if(LPUART_GetITStatus(LPUART1, LPUART_LPUIF_RXIF) == SET)
{
LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
rxDataBuf[cnt] = LPUART_ReceiveData(LPUART1);
if(++cnt >= 10)
{
cnt_flag = 1;
cnt = 0;
}
}
}
f.
編寫實驗樣例:
void LPUART_Wakeup_Test(void)
{
uint8_t temp, i;
char string1[] = "LPUART wakeup mcu test!\\r\\n";
char string2[] = "mcu stop!\\r\\n";
char string3[] = "mcu wakeup!\\r\\n";
for(i = 0; i < strlen(string1); i++)
{
Output_Byte(LPUART1, string1[i]);
}
DELAY_Ms(20);
for(i = 0; i < strlen(string2); i++)
{
Output_Byte(LPUART1, string2[i]);
}
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);//休眠
for(i = 0; i < strlen(string3); i++)
{
Output_Byte(LPUART1, string3[i]);
}
while(1)
{
}
}
g.
在main函數中配置好LPUART后,調用實驗函數LPUART_Wakeup_Test,可以的到如下結果:
-
寄存器
+關注
關注
31文章
5295瀏覽量
119838 -
接收器
+關注
關注
14文章
2454瀏覽量
71753 -
RCC
+關注
關注
0文章
93瀏覽量
26877 -
UART接口
+關注
關注
0文章
124瀏覽量
15256 -
MCU芯片
+關注
關注
3文章
246瀏覽量
11357
發(fā)布評論請先 登錄
相關推薦
評論