蓝牙主从机通信(BLE5.0)+CUBEMX+STM32L0+LPUSART

项目需求,无线通信+低功耗

一、STM32CUBEMX配置LL库函数LPUSART

1、LPUSART基本配置

在这里插入图片描述

2、LPUSART中断使能

在这里插入图片描述
串口中断优先级可以简单粗暴的(不是懒)设为最高0。如下
在这里插入图片描述

3、LPUSART-生成代码
void MX_LPUART1_UART_Init(void)
{
  LL_LPUART_InitTypeDef LPUART_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPUART1);

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC);
  /**LPUART1 GPIO Configuration
  PC10   ------> LPUART1_TX
  PC11   ------> LPUART1_RX
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* LPUART1 interrupt Init */
  NVIC_SetPriority(RNG_LPUART1_IRQn, 0);
  NVIC_EnableIRQ(RNG_LPUART1_IRQn);

  LPUART_InitStruct.BaudRate = 256000;
  LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
  LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
  LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
  LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
  LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
  LL_LPUART_Init(LPUART1, &LPUART_InitStruct);

}
4、LPUSART用户添加代码

除了调用生成的初始化函数,还需以下操作

LL_LPUART_EnableIT_RXNE(LPUART1); //启用 检测到接收非空 中断
LL_LPUART_EnableIT_IDLE(LPUART1); //启用 检测到空闲 中断

//使能LPUART1		
LL_LPUART_Enable(LPUART1);
//查询LPUART1初始化
while(!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))||(!(LL_LPUART_IsActiveFlag_REACK(LPUART1))))
{}

二、蓝牙引脚定义

在这里插入图片描述

1、将SEL1与SEL0接地/拉低,以选择串口通信模式

在这里插入图片描述

2、CUBEMX引脚初始化

(打糊的)引脚对应真正使用的原理图
在这里插入图片描述
User Label项是用户为引脚设置的名称,会在main.h生成相应的宏定义(这功能真令人舒适)。如下(只是例子)
在这里插入图片描述

3、GPIO-生成代码
  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = BleINT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BleINT_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin */
  GPIO_InitStruct.Pin = BleWakeup_Pin|BleRST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = BleState_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BleState_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = BleCtrl_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(BleCtrl_GPIO_Port, &GPIO_InitStruct);

三、LPUSART发送字符串函数

接下来,单片机与蓝牙的通信全仰仗这个函数啦

//串口LPUART1发送字符串
void LpuartSendBuf(unsigned char* buf,unsigned char len)
{
	unsigned char i;
	for(i=0;i<len;i++) /* 循环直到发送结束 */
	{
		LL_LPUART_TransmitData8(LPUART1, (uint8_t)buf[i]);		
//		while(!LL_LPUART_IsActiveFlag_TXE(LPUART1)) {} //1:数据传输到移位寄存器 (当发送数据寄存器(LPUART_TDR)的内容已传输到移位寄存器时)
		while(!LL_LPUART_IsActiveFlag_TC(LPUART1)) {} //1:传送已完成(如果已完成对包含数据的帧的发送并且TXE置1)
	}		
}

四、LPUSART中断处理(收/发数据)函数

uint8_t ReceiveData=0; //数据处理
uint8_t p_LPUart_Rx=0;
uint8_t LPUart_Buffer[35]={0}; //串口接收缓冲

void RNG_LPUART1_IRQHandler(void) //全局中断
{
	if(LL_LPUART_IsActiveFlag_RXNE(LPUART1)) //==1:已准备好读取接收到的数据
	{	
		 LPUart_Buffer[p_LPUart_Rx]=LL_LPUART_ReceiveData8(LPUART1); //接收数据并自动清RXNE标志位
		 p_LPUart_Rx++;		 
	}
	
	if(LL_LPUART_IsActiveFlag_IDLE(LPUART1)) //==1:检测到空闲线路
	{
		LL_LPUART_ClearFlag_IDLE(LPUART1); //清除检测到空闲线路标志位

		p_LPUart_Rx=0;			
		//数据处理	
        //注:蓝牙主从机通信实验:互发数组,有3个uint8_t类型的元素
        //uint8_t Send[3]={0xAA,0x01,0xBB};		
        if(LPUart_Buffer[0]==0xAA) //判断帧头
		{			
			if(LPUart_Buffer[2]==0xBB) //判断帧尾
			{			
			  ReceiveData=LPUart_Buffer[1]; //接收数据
	        }         
		}
	}
}

//清空缓冲区
void clean_rebuff(void)
{
	uint16_t i = 36;
	while(i)
	LPUart_Buffer[--i]=0;
}

五、蓝牙-单片机通信

1、此蓝牙的通信基于CC2640 R2透传规格书,在我上传的资源中有原版(当然是中文啦)。

单片机向蓝牙写数据 时序:
在这里插入图片描述

2、测试程序

单片机与蓝牙的命令通信均采用AT指令。指令执行成功,蓝牙会给单片机回应以"AT+OK"为开头的字符串。

#define WAKEUP_CRL() LL_GPIO_ResetOutputPin(BleWakeup_GPIO_Port, BleWakeup_Pin);
#define WAKEUP_SET()  LL_GPIO_SetOutputPin(BleWakeup_GPIO_Port, BleWakeup_Pin);
#define RST_CRL() LL_GPIO_ResetOutputPin(BleRST_GPIO_Port, BleRST_Pin);
#define RST_SET()  LL_GPIO_SetOutputPin(BleRST_GPIO_Port, BleRST_Pin);

//简简单单的 测试函数
u8 blue (void)
{
	WAKEUP_CRL();
	LL_mDelay(1);	
		
	//注:蓝牙会将被写入的数据发送出去。
	BLE_LpUartWrite((u8*)"AT\r\n",strlen("AT\r\n"));
	LL_mDelay(100);
	WAKEUP_SET();
	LL_mDelay(1);
	
	//AT+OK
	if(LPUart_Buffer[3]==0x4F) //0x4F对应"O"			
	{
	   if(LPUart_Buffer[4]==0x4B) //0x4B对应"K"
	   {	
		  clean_rebuff();			
		  return 1;
	   }
	}
	else
	{
		clean_rebuff();
		return 0;
	}
}

灵活运用:按照测试函数的时序来即可,对照透传书更换相应AT指令即可。

六、蓝牙主机-蓝牙从机通信

BleState=1,模块处于断开状态,BleState=0模块处于连接状态。
单片机读(蓝牙接收到的)数据 时序:

接下来看接收数据流程图:
在这里插入图片描述
程序(包括接收和发送):

uint8_t Send[3]={0xAA,0x01,0xBB};

void BLE_LpUartWrite(unsigned char *str,unsigned char len)
{
	LpuartSendBuf(str,len);
}

while(1)
{
	if(!LL_GPIO_IsInputPinSet(BleState_GPIO_Port,BleState_Pin)) //蓝牙已连接
	{      
		if(!LL_GPIO_IsInputPinSet(BleINT_GPIO_Port,BleINT_Pin)) //有数据到来
		{
			WAKEUP_CRL(); //接收数据
		}
						
	    if(sendtime>=3) //3s 每3秒发送一次数据
	    {							
		   BLE_LpUartWrite(Send,3);//发送数据
		   clean_rebuff();	
		   sendtime=0; //重置:发送数据计时
		}
	    relinktimestop_clear=0;										
	}
	else //蓝牙未连接
	{
		if(relinktime>=3) //3s
		{			  	
			clean_rebuff();		    							
			blue_sca_link_mac(); //指定从机MAC地址连接
			LL_mDelay(100);
            relinktime=0; //重置:重连计时											
	   }
	}
}

七、完了

内容太多,先就这了,差不多了

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值