LPUART(Low power universal asynchronous receiver transmitter,低功耗通用异步收发器),相比标准的UART,其功耗极低,支持在低功耗模式下运行,并且可以将MCU从低功耗模式唤醒。
上期介绍了MM32全新低功耗系列MM32L0130的LPUART外设,并实现了基本UART收发通信和使用LPUART唤醒MCU。本期介绍LPUART的高级应用,实现DMA收发实验、使用数据匹配寄存器匹配到指定字符后唤醒MCU。
1LPUART使用DMA
LPUART可以使用DMA来搬运数据,实现无需CPU参与的快速自动数据传输。硬件发出DMA请求与对应的DMA通道直连,也可以通过软件配置寄存器的方式触发DMA通道请求。LPUART的控制寄存器有对应的DMA使能位,如下图所示:
1.1 DMA中断
DMA的每个通道都有三种中断事件标志:DMA半传输、DMA传输完成和DMA传输出错。各通道单独的中断请求由这3种事件标志逻辑或起来。可以配置寄存器的对应位来使能这些中断:
1.2 LPUART使用DMA的配置步骤
1根据基本UART配置步骤配置LPUART
2使能LPUEN的DMAR与DMAT位激活DMA模式
3使能DMA时钟
4发送需要配置DMA的源地址(存储器地址)和目的地址(LPUTXD),传输的数据量以及DMA通道
5配置完发送后,只要TXFIFO为空,就会请求DMA发送
6接收需要配置DMA的源地址(LPURXD)和目的地址(存储器地址),传输的数据量以及DMA通道
7配置完接收后,只要RXFIFO有数据,即不为空,就会请求DMA接收
1.3 功能代码实现
下面例程实现了使用DMA发送和接收LPUART数据,发送和接收完成后进入中断,例程在基本UART收发实验的基础上完成。
a.申请例程所用到的TX和RX缓存、TX和RX完成标志:
uint8_tTX_Buffer[16],RX_Buffer[16]; uint8_tTX_Complete=0,RX_Complete=0;
b.配置NVIC:
NVIC_InitTypeDefNVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel=DMA1_Channel2_3_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority=2; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct);
c.配置DMA通道2为LPUART_TX:
voidLPUART_DMA_TX_Init(void) { DMA_InitTypeDefDMA_InitStruct; RCC_DMA_ClockCmd(DMA1,ENABLE); DMA_DeInit(DMA1_Channel2); DMA_StructInit(&DMA_InitStruct); //DMAtransferperipheraladdress DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)&LPUART1->LPUTXD; //DMAtransfermemoryaddress DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)TX_Buffer; //DMAtransferdirectionfromperipheraltomemory DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralDST; //DMAcachesize DMA_InitStruct.DMA_BufferSize=16; //Theperipheraladdressisforbiddentomovebackward DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //Thememoryaddressisshiftedbackward DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable; //Definetheperipheraldatawidthto8bits DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_Mode=DMA_Mode_Normal; DMA_InitStruct.DMA_Priority=DMA_Priority_Medium; //M2Mmodeisdisabled DMA_InitStruct.DMA_M2M=DMA_M2M_Disable; DMA_InitStruct.DMA_Auto_reload=DMA_Auto_Reload_Disable; DMA_Init(DMA1_Channel2,&DMA_InitStruct); DMA_SetChannelMuxSource(DMA1_Channel2,DMA1_MUX_LPUART1_TX); //EnableLPUART_DMA1_ChannelTransfercompleteinterrupt DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE); LPUART_TX_DMACmd(LPUART1,ENABLE); while((LPUART1->LPUEN&LPUART_LPUEN_DMAT)==0); //LPUART_DMA1_Channelenable DMA_Cmd(DMA1_Channel2,ENABLE); }
d.配置DMA通道3为LPUART_RX:
voidLPUART_DMA_RX_Init(void) { DMA_InitTypeDefDMA_InitStruct; RCC_DMA_ClockCmd(DMA1,ENABLE); DMA_DeInit(DMA1_Channel3); DMA_StructInit(&DMA_InitStruct); //DMAtransferperipheraladdress DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)&LPUART1->LPURXD; //DMAtransfermemoryaddress DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)RX_Buffer; //DMAtransferdirectionfromperipheraltomemory DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC; //DMAcachesize DMA_InitStruct.DMA_BufferSize=16; //Theperipheraladdressisforbiddentomovebackward DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //Thememoryaddressisshiftedbackward DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable; //Definetheperipheraldatawidthto8bits DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_Mode=DMA_Mode_Normal; DMA_InitStruct.DMA_Priority=DMA_Priority_Medium; //M2Mmodeisdisabled DMA_InitStruct.DMA_M2M=DMA_M2M_Disable; DMA_InitStruct.DMA_Auto_reload=DMA_Auto_Reload_Disable; DMA_Init(DMA1_Channel3,&DMA_InitStruct); DMA_SetChannelMuxSource(DMA1_Channel3,DMA1_MUX_LPUART1_RX); //EnableLPUART_DMA1_ChannelTransfercompleteinterrupt DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE); LPUART_RX_DMACmd(LPUART1,ENABLE); while((LPUART1->LPUEN&LPUART_LPUEN_DMAR)==0); //LPUART_DMA1_Channelenable DMA_Cmd(DMA1_Channel3,ENABLE); }
e.编写中断服务函数:
voidDMA1_Channel2_3_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC2)) { DMA_ClearITPendingBit(DMA1_IT_TC2); TX_Complete=1; } if(DMA_GetITStatus(DMA1_IT_TC3)) { DMA_ClearITPendingBit(DMA1_IT_TC3); RX_Complete=1; } }
f.编写实验样例:
voidLPUART_RxTx_DMA_Test(void) { uint8_ti; for(i=0;i< 16; i++) { TX_Buffer[i] = i; } LPUART_DMA_TX_Init(); LPUART_DMA_RX_Init(); while(1) { if(TX_Complete == 1) { TX_Complete = 0; DMA1_Channel3->CMAR=(uint32_t)RX_Buffer; DMA1_Channel3->CNDTR=16; DMA_Cmd(DMA1_Channel3,ENABLE); } if(RX_Complete==1) { RX_Complete=0; memcpy((void*)TX_Buffer,(void*)RX_Buffer,16); DMA1_Channel2->CMAR=(uint32_t)TX_Buffer; DMA1_Channel2->CNDTR=16; DMA_Cmd(DMA1_Channel2,ENABLE); } } }
g.在main函数中配置好LPUART和DMA后,调用实验函数LPUART_RxTx_DMA_Test,可以得到如下结果:
2使用数据匹配寄存器匹配到指定字符后唤醒MCU
为进一步降低系统功耗,MM32L0130系列的LPUART提供了一种接收到指定字符才能唤醒低功耗状态的MCU的功能。用于唤醒的指定字符,由数据匹配寄存器确定:
2.1接收中断配置寄存器
可以通过LPUART的LPUCON.RXEV寄存器配置唤醒事件为START位、一帧接收完成、一帧数据匹配或者RXD下降沿唤醒。
2.2 功能代码实现
匹配指定字符唤醒MCU功能,需要在上期讲解的LPUART唤醒低功耗模式中的MCU基础上修改中断事件配置、指定唤醒字符,具体代码如下:
a.配置LPUART接收中断事件为接收数据匹配成功:
LPUART_InitTypeDefinit_struct; init_struct.LPUART_Clock_Source=0; init_struct.LPUART_BaudRate=LPUART_Baudrate_9600; init_struct.LPUART_WordLength=LPUART_WordLength_8b; init_struct.LPUART_StopBits=LPUART_StopBits_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_RecvData_Mactched; LPUART_Init(LPUART1,&init_struct);
b.配置特定的唤醒字符:
LPUART_SetMatchData(LPUART1,‘5’);//指定字符’5’为唤醒字符
c.编写中断服务程序,判断接收匹配事件并清除标志:
voidLPUART1_IRQHandler() { if(LPUART_GetFlagStatus(LPUART1,LPUART_LPUSTA_START)) { LPUART_ClearFlagStatus(LPUART1,LPUART_LPUSTA_START); } if(LPUART_GetFlagStatus(LPUART1,LPUART_LPUSTA_MATCH)) {//判断接收中断匹配事件 LPUART_ClearFlagStatus(LPUART1,LPUART_LPUSTA_MATCH); } 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; } EXTI_ClearITPendingBit(EXTI_Line22); }
d.编写试验样例:
voidLPUART_Wakeup_Test(void) { uint8_ttemp,i; charstring1[]="LPUARTwakeupmcutest! "; charstring2[]="mcustop! "; charstring3[]="mcuwakeup! "; 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) { } }
e.在main函数配置好LPUART后,调用实验函数LPUART_Wakeup_Test,可以得到如下结果:
-
mcu
+关注
关注
146文章
16984浏览量
350293 -
收发器
+关注
关注
10文章
3393浏览量
105860 -
uart
+关注
关注
22文章
1227浏览量
101170 -
dma
+关注
关注
3文章
559浏览量
100420
原文标题:灵动微课堂 (第237讲)|基于MM32L0130的LPUART应用(2)
文章出处:【微信号:MindMotion-MMCU,微信公众号:灵动MM32MCU】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论