七、低功耗串口
首先,先看官方例程中的LP串口配置。
void LPUart_Init(void)
{
LPUART_SInitTypeDef init_para;
RCC_PERCLK_SetableEx(LPUFCKEN, ENABLE); //LPUART功能时钟使能
RCC_PERCLK_SetableEx(LPUARTCKEN, ENABLE); //LPUART寄存器总线时钟使能
GPIO_PF4AFSEL_PF4AFS_Set(GPIO_PF4AFSEL_PF4AFS_LPUART_TX);//PF4选择LPUART_TX
//LPUART IO 配置
AltFunIO(GPIOF, GPIO_Pin_3, 2); //PF3 LPUART RX 除匹配接收假如外部没有上拉电阻建议配置上拉电阻
AltFunIO(GPIOF, GPIO_Pin_4, 0); //PF4 LPUART TX
/*NVIC中断配置*/
NVIC_DisableIRQ(LPUART_IRQn);
NVIC_SetPriority(LPUART_IRQn,2);//中断优先级配置
NVIC_EnableIRQ(LPUART_IRQn);
//UART初始化配置
init_para.BaudRate = 9600; //波特率
init_para.DataBit = Eight8Bit; //数据位数
init_para.ParityBit = EVEN; //奇偶校验
init_para.StopBit = OneBit; //停止位
LPUART_SInit(&init_para); //初始化uart(接收中断使用的是接收数据匹配)
}
void LPUART_SInit(LPUART_SInitTypeDef* para)
{
LPUART_InitTypeDef para2;
para2.RXEV =LPUART_LPUCON_RXEV_MATCH; //接收中断事件配置
para2.TCIE = DISABLE; //发送完成中断使能
para2.TXIE = DISABLE; //发送buffer空中断使能
para2.RXIE = DISABLE; //接收中断使能
para2.TXPOL = DISABLE; //数据发送极性取反使能
para2.RXPOL = DISABLE; //数据接收极性取反控制
para2.NEDET = DISABLE; //下降沿检测使能
para2.ERRIE = DISABLE; //错误中断使能
LPUART_Init(¶2);
}
在LPUART_SInit(&init_para);函数里面的接收中断事件配置:是接收数据匹配成功。意思是从上位机或者串口发送的数据,必须得有设置的匹配字节才能接收,该匹配的字节可以通过LPUART_COMPARE_Write(0x33);//写数据匹配寄存器
随意设置。接收中断事件配置的设置又关系到串口中断函数的判断。
初始化完成,测试低功耗串口,通过发送数据测试串口是否通讯成功。
void Test_LPUart(void)
{
LPUART_LPUEN_RXEN_Setable(ENABLE); //打开接收使能
LPUART_LPUEN_TXEN_Setable(ENABLE); //打开发送使能
//中断发送数组
LPUARTOp.TxBuf = TestTxData;
LPUARTOp.TxLen = 12;
LPUARTOp.TxOpc = 1;
//清除发送中断标志
LPUART_LPUIF_TXIF_Clr();
LPUART_LPUIF_TC_IF_Clr();
LPUART_LPUCON_TCIE_Setable(ENABLE); //使能发送中断
LPUART_LPUTXD_Write(LPUARTOp.TxBuf[0]);//启动第一个数据的发送
TicksDelayMs(10, NULL );//软件延时
LPUART_LPUCON_TCIE_Setable(DISABLE); //禁止发送中断
LPUART_COMPARE_Write(0x33);//写数据匹配寄存器
LPUART_LPUCON_RXIE_Setable(ENABLE);//使能接收中断
}
在这里需要注意的有几点:其一是发送完成需要使能接收中断,不然接收不到数据;其二是如果有禁止中断指令,那上一句的软件延时时间一定要大于发送的数组长度,最好是不要禁止发送中断。其三是注意发送的长度,当接收或者发送不是预想中的长度时,看是否设置的发送长度与想发送的数组一致。
以下是低功耗串口中断函数:
void LPUART_IRQHandler(void)
{
uint08 tmp08;
//接收中断处理
if((ENABLE == LPUART_LPUCON_RXIE_Getable())
&&(SET == LPUART_LPUSTA_MATCH_Chk()))//接收数据匹配中断
{
tmp08 = LPUART_LPURXD_Read();
LPUART_LPUSTA_MATCH_Clr(); //清除数据匹配标志
}
//发送中断处理
if((ENABLE == LPUART_LPUCON_TCIE_Getable())
&&(SET == LPUART_LPUIF_TC_IF_Chk()))
{
//发送指定长度的数据
if(LPUARTOp.TxOpc < LPUARTOp.TxLen)
{
LPUART_LPUTXD_Write(LPUARTOp.TxBuf[LPUARTOp.TxOpc]); //发送一个数据
}
//清除发送中断标志
LPUART_LPUIF_TC_IF_Clr();
LPUARTOp.TxOpc++;
}
}
当在初始化中设置的数据匹配,中断中判断的是LPUART_LPUSTA_MATCH_Chk(),且接收完一个字节就清除匹配标志,那只能接收一个字节,并且每次都必须是匹配字节。
if((ENABLE == LPUART_LPUCON_RXIE_Getable())
&&(SET == LPUART_LPUSTA_MATCH_Chk()))//接收数据匹配中断
{
tmp08 = LPUART_LPURXD_Read();
BUFFER[i]=tmp08;
i++;
LPUART_LPUSTA_MATCH_Clr(); //清除数据匹配标志
}
//发送中断处理
.......
}
当在初始化中设置的数据匹配,中断中判断的是LPUART_LPUIF_RXIF_Chk();如果在接收到每个字节后清除接收中断标志 :LPUART_LPUIF_RXIF_Clr(); 到接收完一定长度的字节后清除匹配标志:LPUART_LPUSTA_MATCH_Clr(); 那就能一个字节一个字节的接收到一定长度的数据。代码见下(具体中断里的代码怎么写根据自己的需求):
void LPUART_IRQHandler(void)
{
uint08 tmp08;
//接收中断处理
if((ENABLE == LPUART_LPUCON_RXIE_Getable())
&&(SET == LPUART_LPUIF_RXIF_Chk()))
{
tmp08 = LPUART_LPURXD_Read();
BUFFER[i]=tmp08;
i++;
if(i==3)
{
i=0;
flag=1;
LPUART_LPUSTA_MATCH_Clr(); //清除数据匹配标志
}
LPUART_LPUIF_RXIF_Clr(); //清除接收中断标志
}
//发送中断处理
if((ENABLE == LPUART_LPUCON_TCIE_Getable())
&&(SET == LPUART_LPUIF_TC_IF_Chk()))
{
//发送指定长度的数据
if(LPUARTOp.TxOpc < LPUARTOp.TxLen)
{
LPUART_LPUTXD_Write(LPUARTOp.TxBuf[LPUARTOp.TxOpc]); //发送一个数据
}
//清除发送中断标志
LPUART_LPUIF_TC_IF_Clr();
LPUARTOp.TxOpc++;
}
}
如果在LPUART_SInit(&init_para);函数里面的接收中断事件配置是:LPUART_LPUCON_RXEV_1BYTE,则在低功耗下,任何字节都可以进行唤醒。发送给串口的数据也不需要特定字节。代码如下:
void LPUART_IRQHandler(void)
{
uint08 tmp08=0; //从寄存器中读取到的值
if((ENABLE == LPUART_LPUCON_RXIE_Getable())
&&((SET == LPUART_LPUIF_RXIF_Chk()))) //接收完成中断标志位检测函数
{
tmp08 = LPUART_LPURXD_Read();
readLPchar=tmp08;
LPComcheckflag=1;
//只接收不处理
if(LPComcheckflag==1)
{
ReFromComputer[LPnum]=readLPchar;
LPnum++;
}
if(((LPnum == ReFromComputer[2] + 4))&&(LPComcheckflag==1)) //普通模式下:2*帧头+1*数据长度+x*数据内容+校验。 说明接收完成。
{
LPComcheckflag=0; //进入接收标志清零
}
}
LPUART_LPUIF_RXIF_Clr(); //清除接收中断标志 接收完成中断标志位清0函数
}
//发送中断处理
if((ENABLE == LPUART_LPUCON_TCIE_Getable())
&&(SET == LPUART_LPUIF_TC_IF_Chk()))
{
if(LPUARTOp.LPTxOpc < LPUARTOp.LPTxLen) //发送指定长度的数据
{
LPUART_LPUTXD_Write(LPUARTOp.LPTxBuf[LPUARTOp.LPTxOpc]); //发送一个数据
}
//清除发送中断标志
LPUART_LPUIF_TC_IF_Clr();
LPUARTOp.LPTxOpc++;
}
}
我所使用到的低功耗串口大概就是这两种,且它在低功耗下最高只支持9600。有什么问题可以通过提问完善。