三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)

非协议栈实现BLE广播(2.4G实现BLE广播)

现在的人啊,用协议栈用多了,BLE物理层是怎么广播都不知道了,且听我慢慢道来

这里实现的BLE广播包是基于上一章介绍的,我要通过2.4G来发出这个广播包
在这里插入图片描述

一.BLE的大小端,获取比特流
  • 例如,广播的接入地址是0x8e89bed6,原始数据却是0xd6be898e,意味着先发0xd6
  • 而0xd6又是怎么发送的呢,当然下先发6再发d,6 = 0110b ,d = 1101b。
  • 而其中的0xd(1101b)又是怎么发送的,当然是先发1->0->1->1。
    最后输出的顺序是,先发小端。
    在这里插入图片描述
二.BLE比特流的处理

在这里插入图片描述
发包:获取到比特流后->加密->CRC->白化->发到空中
收包:空中数据->反白化->CRC校验->获取到比特流

BLE的广播是不用加密的,所以我们可以省略这一步

三.设置2.4G广播包

BLE广播包如下,这里并没有把前导码和接入地址实现到2.4G包中,道理是一样,大家可以自己实现。
在这里插入图片描述
所以,这里实现的包结构应该是这样,包最大为42个字节。
在这里插入图片描述
最终包结构是
在这里插入图片描述

1.设置广播包相关变量

代码1

/*[ 包头|总长度        |MAC1|2|3|4|5|6|    长度|类型|广播类型|     长度|类型|名字|   |||||||||||||||]*/
static uint8_t _packet[42];
/*长度索引*/
static uint8_t _length = 0;
static uint8_t _dataFieldStartPoint = 0;
2.设置包头

代码2

void setPhone(uint8_t phone_type) {
	_packet[0] = phone_type;
}
setPhone(0x40);
3.设置MAC和Flag

代码3

void setMAC(uint8_t* address, uint8_t len) {
	_length = 2;
	_packet[_length++] = address[0];
	_packet[_length++] = address[1];
	_packet[_length++] = address[2];
	_packet[_length++] = address[3];
	_packet[_length++] = address[4];
	_packet[_length++] = address[5];
	_packet[_length++] = 2;    //flag length
	_packet[_length++] = 0x01; //data type
	_packet[_length++] = 0x06; //actual flag
}
uint8_t address[] = { 0x4f,0x21,0xc1,0x41,0x26,0x50 };
setMAC(address,6);
4.设置厂家信息

代码4,这里用了点C++,问题不大,相信大家能懂。
还记得CRC的介绍吗? CRC 的移位寄存器一定需要初值的, 对于广播通道的 CRC 移位
寄存器的初始值为 0x55555。 而对于数据通道下的 CRC 初始值则是由主机发送连接请求时将 CRC 移位寄存器的初始值发送给从机,之后就一直使用这个值作为连接状态下的 CRC 移位寄存器的初始值。所以这里先设置CRC为0x555555。

void setData(const void* data, uint8_t dataLen) {
	/*定位*/
	_dataFieldStartPoint = _dataFieldStartPoint == 0 ? _length : _dataFieldStartPoint;
	_length = _dataFieldStartPoint;

	const uint8_t* current = reinterpret_cast<const uint8_t*>(data);

	/*长度*/
	_packet[_length++] = dataLen + 1;
	/*类型*/
	_packet[_length++] = 0xFF;
	/*复制进来*/
	for (uint8_t i = 0; i < dataLen; i++) {
		_packet[_length++] = *(current);
		current++;
	}
	/*最后的CRC先补0x555555*/
	_packet[_length++] = 0x55;
	_packet[_length++] = 0x55;
	_packet[_length++] = 0x55;
}
	char data[] = {0x4c,0x00,0x10,0x02,0x07,0x08};
	setData(data, 6);
5.告一段落了

这里,我们实现了2.4G的广播包,我们对比一下。

	/*填充总长度  3个CRC 2个包头,所以减5*/
	_packet[1] = _length - 5;

干的漂亮。
在这里插入图片描述
在这里插入图片描述

四.进行CRC计算

大家要记得,BLE是CRC24,生成项是
PS:我是每学习一次CRC就忘一次,我记不牢。代码如下,拿走不谢,现在我就忘了为什么这样写了
在这里插入图片描述
代码5

/*进行CRC,以LFSR的方式进行CRC*/
void BLEcrc(const uint8_t* data, uint8_t dataLen, uint8_t* outputCRC) {
	// calculating the CRC based on a LFSR
	uint8_t i, temp, tempData;
	while (dataLen--) {
		tempData = *data++;
		for (i = 0; i < 8; i++, tempData >>= 1) {
			temp = outputCRC[0] >> 7;

			outputCRC[0] <<= 1;
			if (outputCRC[1] & 0x80) { outputCRC[0] |= 1; }
			outputCRC[1] <<= 1;
			if (outputCRC[2] & 0x80) { outputCRC[1] |= 1; }
			outputCRC[2] <<= 1;

			if (temp != (tempData & 1)) {
				outputCRC[2] ^= 0x5B;
				outputCRC[1] ^= 0x06;
			}
		}
	}
}
/*去掉CRC位*/
uint8_t i, dataLen = _length- 3; 
BLEcrc(_packet, dataLen, packet + dataLen);

到目前为止,我们组的包都是小端模式的,可是CRC可是大端的噢
代码6

uint8_t  reverseBits(uint8_t input) {
	uint8_t temp = 0;
	if (input & 0x80) temp |= 0x01;
	if (input & 0x40) temp |= 0x02;
	if (input & 0x20) temp |= 0x04;
	if (input & 0x10) temp |= 0x08;
	if (input & 0x08) temp |= 0x10;
	if (input & 0x04) temp |= 0x20;
	if (input & 0x02) temp |= 0x40;
	if (input & 0x01) temp |= 0x80;
	return temp;
}
	//CRC大小端转换
	for (i = 0; i < 3; i++, dataLen++)
		_packet[dataLen] = reverseBits(_packet[dataLen]);
五.白化

这里注意白化是不分广播状态或者是连接状态,它的移位寄存器的初始值为信道通道号,并且最高位一定置 1,也就是初始值的第7bit位一定是1。例如,广播通道 channel是37(0x25), 那么初始值就是 37。
代码7

uint8_t  bleWhitenStart(uint8_t chan) {
	//use left shifted one
	//最高位一定要是1
	return reverseBits(chan) | 2;
}
/*白化,LFSR的方式进行白化*/
void bleWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff) {
	// Implementing whitening with LFSR
	uint8_t  m;
	while (len--) {
		for (m = 1; m; m <<= 1) {
			if (whitenCoeff & 0x80) {
				whitenCoeff ^= 0x11;
				(*data) ^= m;
			}
			whitenCoeff <<= 1;
		}
		data++;
	}
}
bleWhiten(_packet, _length, bleWhitenStart(37));
六.获取正确的bit流,低位先发送

比如现在是0xd6,11010110B;现在就要变为01101011
代码8

	for (i = 0; i < len; i++)
		packet[i] = reverseBits(packet[i]);

大功告成,今晚吃鸡

空中的包是先发_packet[0],再发_packet[1]
先发_packet[0]的bit8,再发bit7。

什么?你问我要源代码?嘻嘻不给。我要留着去赚积分

  • 12
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值