LPUART(Low power universal asynchronous receiver transmitter,低功耗通用異步收發(fā)器),相比標(biāo)準(zhǔn)的UART,其功耗極低,支持在低功耗模式下運(yùn)行,并且可以將MCU從低功耗模式喚醒。
本文介紹MM32全新低功耗系列MM32L0130的LPUART外設(shè),實(shí)現(xiàn)基本UART收發(fā)通信、通過UART中斷使MCU從低功耗模式中喚醒。
1 LPUART 簡介
1.1 LPUART功能框圖
1.2 LPUART功能特征
支持UART幀格式的全雙工異步數(shù)據(jù)收發(fā)。
支持輸入任意頻率的時(shí)鐘源,可配置為LSE/LSI/PCLK。
支持可編程的波特率數(shù)據(jù)傳輸,發(fā)送和接收時(shí)可采用3、4分頻交替,防止累計(jì)誤差。
可配置奇偶校驗(yàn)位、停止位。
可配置收發(fā)數(shù)據(jù)信號取反。
2 LPUART時(shí)鐘配置
LPUART時(shí)鐘源配置寄存器在RCC_CFGR2中的位0和位1,可配置LSE、LSI、PCLK作為時(shí)鐘源。
3 LPUART中斷與喚醒
支持的中斷源:
接收緩沖溢出
幀錯(cuò)誤
奇偶校驗(yàn)錯(cuò)誤
接收器檢測到下降沿
接收器完整接收 1byte 數(shù)據(jù)
接收器完整接收數(shù)據(jù)且與預(yù)設(shè)數(shù)據(jù)匹配
發(fā)送器數(shù)據(jù)完成發(fā)送
發(fā)送器緩沖空
支持低功耗模式下的喚醒源:
接收器檢測到下降沿喚醒
接收器檢測到起始位喚醒
接收器1字節(jié)接收完成喚醒
接收器1字節(jié)數(shù)據(jù)接收并匹配喚醒
4 接收和發(fā)送時(shí)序
由于LPUART工作時(shí)鐘不是波特率的整數(shù)倍,采用固定分頻系數(shù)的話會(huì)引入累計(jì)誤差,所以在接收和發(fā)送的時(shí)候采用3、4分頻交替進(jìn)行接收和發(fā)送,每個(gè)bit采樣一次,每個(gè)bit采用3分頻還是4分頻由MCTL寄存器控制,接收和發(fā)送時(shí)序圖如下:
當(dāng)LPUART工作時(shí)鐘配置為標(biāo)準(zhǔn)的32.768KHz時(shí),軟件可配置BREN為0,然后根據(jù)通信波特率調(diào)整調(diào)制寄存器MCTL,建議配置參數(shù)如下表:
5 LPUART寄存器概覽
6 LPUART實(shí)現(xiàn)普通UART功能配置步驟
- 開啟LPUART所選時(shí)鐘源
- 配置RCC_CFGR2寄存器選擇LPUART時(shí)鐘
- 配置 LPUBAUD 寄存器決定波特率
- 根據(jù)波特率選擇合適的調(diào)制參數(shù),配置 MCTL 寄存器
- 配置 LPUCON 寄存器,選擇幀格式、極性、中斷參數(shù)等
- 配置 LPUEN 寄存器打開發(fā)送、接收使能
7 發(fā)送和接收數(shù)據(jù)
發(fā)送數(shù)據(jù):
將待發(fā)送的數(shù)據(jù)寫入LPUTXD,當(dāng)發(fā)送完成時(shí),LPUSTA的TXE標(biāo)志位會(huì)被硬件置起,表示數(shù)據(jù)已傳入移位寄存器,發(fā)送 buffer為空。此時(shí)可往LPUTXD寫入下一個(gè)數(shù)據(jù)。軟件向發(fā)送buffer寫數(shù)據(jù)時(shí)TXE標(biāo)志位自動(dòng)清零。
接收數(shù)據(jù):
當(dāng)接收一個(gè)完整幀時(shí),LPUSTA的RXF標(biāo)志位置起,表示已完整接收數(shù)據(jù),此時(shí)軟件可讀取LPURXD讀出接收到的數(shù)據(jù)。軟件讀LPUDATA寄存器時(shí),RXF標(biāo)志位自動(dòng)清零。
8 LPUART功能實(shí)現(xiàn)代碼
首先編寫基礎(chǔ)UART的代碼,通過輪詢的方式發(fā)送和接收數(shù)據(jù)。然后添加中斷代碼,實(shí)現(xiàn)通過LPUART將MCU從低功耗模式喚醒。
8.1 基于LSE時(shí)鐘的基礎(chǔ)UART功能實(shí)現(xiàn)代碼
a.
開啟BKP、LSE時(shí)鐘,待LSE時(shí)鐘穩(wěn)定,使能LPUART時(shí)鐘:
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結(jié)構(gòu)體參數(shù):
LPUART_InitTypeDef init_struct;
init_struct.LPUART_Clock_Source = 0; //時(shí)鐘源選擇
init_struct.LPUART_BaudRate = LPUART_Baudrate_9600; //波特率選擇9600
init_struct.LPUART_WordLength = LPUART_WordLength_8b; //8位數(shù)據(jù)位
init_struct.LPUART_StopBits = LPUART_StopBits_1; //1位停止位
init_struct.LPUART_Parity = LPUART_Parity_No; //沒有校驗(yàn)位
init_struct.LPUART_MDU_Value = 0x952; //波特率調(diào)制控制寄存器
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.
設(shè)置LPUART引腳復(fù)用,例程復(fù)用到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ā)送函數(shù):
void Output_Byte(LPUART_TypeDef* lpuart, uint8_t dat)
{
LPUART_SendData(lpuart, dat);
while(!LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_TXE));
}
e.
編寫輪詢接收函數(shù):
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.
編寫實(shí)驗(yàn)樣例:
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函數(shù)中配置好LPUART后,調(diào)用LPUART_TxRx_Test函數(shù),可得到如下實(shí)驗(yàn)結(jié)果:
8.2 在上述基本LPUART配置的基礎(chǔ)上增加中斷配置代碼,實(shí)現(xiàn)喚醒低功耗模式中的MCU
a.
開啟SYSCFG、PWR時(shí)鐘:
RCC_APB2PeriphClockCmd(RCC_APB2ENR_SYSCFG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
b.
EXTI模塊可以產(chǎn)生中斷請求,用來喚醒低功耗模式中的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.
清除接收標(biāo)志并打開接收中斷:
LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
LPUART_ITConfig(LPUART1, LPUART_LPUCON_RXIE, ENABLE);
e.
定義RX緩存,然后編寫中斷服務(wù)函數(shù):
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.
編寫實(shí)驗(yàn)樣例:
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函數(shù)中配置好LPUART后,調(diào)用實(shí)驗(yàn)函數(shù)LPUART_Wakeup_Test,可以的到如下結(jié)果:
-
寄存器
+關(guān)注
關(guān)注
31文章
5357瀏覽量
120641 -
接收器
+關(guān)注
關(guān)注
14文章
2473瀏覽量
71988 -
RCC
+關(guān)注
關(guān)注
0文章
93瀏覽量
26962 -
UART接口
+關(guān)注
關(guān)注
0文章
124瀏覽量
15315 -
MCU芯片
+關(guān)注
關(guān)注
3文章
253瀏覽量
11549
發(fā)布評論請先 登錄
相關(guān)推薦
評論