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

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

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

这里实现的BLE广播包是基于上一章介绍的,我要通过2.4G来发出这个广播包
三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)_第1张图片

一.BLE的大小端,获取比特流

  • 例如,广播的接入地址是0x8e89bed6,原始数据却是0xd6be898e,意味着先发0xd6
  • 而0xd6又是怎么发送的呢,当然下先发6再发d,6 = 0110b ,d = 1101b。
  • 而其中的0xd(1101b)又是怎么发送的,当然是先发1->0->1->1。
    最后输出的顺序是,先发小端。
    三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)_第2张图片

二.BLE比特流的处理

三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)_第3张图片
发包:获取到比特流后->加密->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(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;

干的漂亮。
三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)_第4张图片
三.非协议栈实现BLE蓝牙广播(2.4G实现BLE广播)_第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。

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

你可能感兴趣的:(BLE)