IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> CAN/CANFD 总线负载率及计算(源码和工具) -> 正文阅读

[嵌入式]CAN/CANFD 总线负载率及计算(源码和工具)

CAN BUS的总线负载率是CAN总线架构协议设计时的一个重要的指标。一般建议负载率峰值不要高于80%,平均负载率不要超过50%。当然这只是一般建议,具体根据使用场景和系统设计而定。

负载率定义

关于CAN负载率的定义和计算,很多文章写得不求甚解,用帧数量来计算负载率是非常不正确的做法。

其实总线负载率的定义其实是非常简单明了的:

总线负载率=总线每秒上传输的实际bit数量/总线波特率*100%

BusLoad=\frac{bitstransferred}{bus bit rate}*100%

原理非常简单,波特率的定义就是每秒CAN总线上可以传输多少CAN数据bit,总线负载率自然就是总线实际传输的bit数量比上总线可以承载的最大bit数了。

例如,100K的总线波特率,总线上最大承载的数据量就是100K个bit。如果总线上实际传输了50K个bit位,那么负载率就是50%。

负载率计算

对于上面的计算公式,对于一个CAN总线而言,波特率一般都是已知的。计算负载率的关键就是通过CAN报文统计出总线上每秒传输的bit数量。那么就需要回到CAN的帧格式来计算实际发生的bit数。

1位起始位。 ?

11位标识符 ?

1位RTR ?

6位控制域 ?

0到64位数据字段 ?

15位CRC ?

位填充是可能的,在上面的每一个序列的5个连续位相同的水平。?最坏情况下大约是19位。 ?

3位分隔符,ack等。 ?

帧结束7位 ?

帧后的3位间隔域。 ?

如果软件需要精确计算负载率,无疑是比较麻烦的。因为对于软件层面,并感知不到除了标识符,控制域和数据域以外的其他bit,并且由于填充位的数量因数据不同而不同,软件做精确的bit位数量计算就比较耗费资源。

软件计算负载率

基于这样的情况,实际可以考虑3种方案

1. 按最少的填充位可能性来计算(忽略填充位)

? ? ? ? 忽略填充位显然会少统计很多bit数量,导致计算出的负载率比实际的偏低,但是每帧的bit数计算方式简单。

/* eff : 扩展帧标识 */
can_frame_length = (eff ? 67 : 47) + frame->len * 8;

2. 按最多的填充位的可能性来计算

? ? ? ? 按最多的填充位计算负载率,会导致计算出的负载率比实际的偏高,但是每帧的bit数计算方式也比较简单。

/* eff : 扩展帧标识 */
can_frame_length = (eff ? 80 : 55) + frame->len * 10;

3.依据每一帧数据,精确的计算出填充位的数量

这种方式是最精确的,但是由软件计算会比较复杂,开销较大,需要软件讲每一帧的bit按照二进制进行排列,然后按照CAN协议位填充的要求,遇到5个相同的bit就插入一个相反的填充位,也就是增加一个bit数。

static unsigned cfl_exact(struct can_frame *frame)
{
	uint8_t bitmap[16];
	unsigned start = 0, end;
	crc_t crc;
	uint16_t crc_be;
	uint8_t mask, lookfor;
	unsigned i, stuffed;
	const int8_t clz[32] = /* count of leading zeros in 5 bit numbers */
		{ 5, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

	/* Prepare bitmap */
	memset(bitmap, 0, sizeof(bitmap));
	if (frame->can_id & CAN_EFF_FLAG) {
		/* bit            7      0 7      0 7      0 7      0
		 * bitmap[0-3]   |.sBBBBBB BBBBBSIE EEEEEEEE EEEEEEEE| s = SOF, B = Base ID (11 bits), S = SRR, I = IDE, E = Extended ID (18 bits)
		 * bitmap[4-7]   |ER10DLC4 00000000 11111111 22222222| R = RTR, 0 = r0, 1 = r1, DLC4 = DLC, Data bytes
		 * bitmap[8-11]  |33333333 44444444 55555555 66666666| Data bytes
		 * bitmap[12-15] |77777777 ........ ........ ........| Data bytes
		 */
		bitmap[0] = (frame->can_id & CAN_EFF_MASK) >> 23;
		bitmap[1] = ((frame->can_id >> 18) & 0x3f) << 3 |
			    3 << 1	       	     	      	| /* SRR, IDE */
			    ((frame->can_id >> 17) & 0x01);
		bitmap[2] = (frame->can_id >> 9) & 0xff;
		bitmap[3] = (frame->can_id >> 1) & 0xff;
		bitmap[4] = (frame->can_id & 0x1) << 7              |
			    (!!(frame->can_id & CAN_RTR_FLAG)) << 6 |
			    0 << 4	      		       	    | /* r1, r0 */
			    (frame->can_dlc & 0xf);
		memcpy(&bitmap[5], &frame->data, frame->can_dlc);
		start = 1;
		end = 40 + 8*frame->can_dlc;
	} else {
		/* bit           7      0 7      0 7      0 7      0
		 * bitmap[0-3]  |.....sII IIIIIIII IRE0DLC4 00000000| s = SOF, I = ID (11 bits), R = RTR, E = IDE, DLC4 = DLC
		 * bitmap[4-7]  |11111111 22222222 33333333 44444444| Data bytes
		 * bitmap[8-11] |55555555 66666666 77777777 ........| Data bytes
		 */
		bitmap[0] = (frame->can_id & CAN_SFF_MASK) >> 9;
		bitmap[1] = (frame->can_id >> 1) & 0xff;
		bitmap[2] = ((frame->can_id << 7) & 0xff) |
			    (!!(frame->can_id & CAN_RTR_FLAG)) << 6 |
			    0 << 4 | /* IDE, r0 */
			    (frame->can_dlc & 0xf);
		memcpy(&bitmap[3], &frame->data, frame->can_dlc);
		start = 5;
		end = 24 + 8 * frame->can_dlc;
	}

	/* Calc and append CRC */
	crc = calc_bitmap_crc(bitmap, start, end);
	crc_be = htons(crc << 1);
	assert(end % 8 == 0);
	memcpy(bitmap + end / 8, &crc_be, 2);
	end += 15;

	/* Count stuffed bits */
	mask 	= 0x1f;
	lookfor = 0;
	i 	= start;
	stuffed = 0;
	while (i < end) {
		unsigned change;
		unsigned bits = (bitmap[i / 8] << 8 | bitmap[i / 8 + 1]) >> (16 - 5 - i % 8);
		lookfor = lookfor ? 0 : mask; /* We alternate between looking for a series of zeros or ones */
		change = (bits & mask) ^ lookfor; /* 1 indicates a change */
		if (change) { /* No bit was stuffed here */
			i += clz[change];
			mask = 0x1f; /* Next look for 5 same bits */
		} else {
			i += (mask == 0x1f) ? 5 : 4;
			if (i <= end) {
				stuffed++;
				mask = 0x1e; /* Next look for 4 bits (5th bit is the stuffed one) */
			}
		}
	}
	return end - start + stuffed +
		3 + 		/* CRC del, ACK, ACK del */
		7 +		/* EOF */
		3;		/* IFS */
}

软件计算负载率的缺陷

对于软件统计负载率,即使采用精确计算填充位的算法,由于以下原因仍然不能真实的反应总线的负载情况。

1. 对于CRC校验错误,或者格式错误的帧,软件层面一般不会接收到,也难以统计这部分错误帧产生的总线负载

硬件统计负载率

相比软件计算负载率,对需要精确计算总线负载的场合,更好的方案是用专业的硬件来统计发生的bit数量,并计算负载率。

测量CAN BUS总线负载率的工具和软件

Linux下使用canbusload?

canbusload 是linux CAN工具canutils的其中一个程序。它可以很方便的计算并刷新当前CAN总线上的负载率信息,并且提供了上述的3种软件算法进行统计(即忽略填充位,最大计算填充位,精确计算填充位)。

ubuser@ubuser-Lenovo-Product:/$ canbusload 

Usage: canbusload [options] <CAN interface>+
  (use CTRL-C to terminate canbusload)

Options: -t (show current time on the first line)
         -c (colorize lines)
         -b (show bargraph in 5% resolution)
         -r (redraw the terminal - similar to top)
         -i (ignore bitstuffing in bandwidth calculation)
         -e (exact calculation of stuffed bits)

Up to 16 CAN interfaces with mandatory bitrate can be specified on the 
commandline in the form: <ifname>@<bitrate>

The bitrate is mandatory as it is needed to know the CAN bus bitrate to
calcultate the bus load percentage based on the received CAN frames.
Due to the bitstuffing estimation the calculated busload may exceed 100%.
For each given interface the data is presented in one line which contains:

(interface) (received CAN frames) (used bits total) (used bits for payload)

Example:

user$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c

canbusload 2014-02-01 21:13:16 (worst case bitstuffing)
 can0@100000   805   74491  36656  74% |XXXXXXXXXXXXXX......|
 can1@500000   796   75140  37728  15% |XXX.................|
 can2@500000     0       0      0   0% |....................|
 can3@500000    47    4633   2424   0% |....................|

硬件工具

PEAK的PCAN PRO和PCAN FD,以及周立功的ZCANpro软件均支持总线负载率的显示。

开源的Busmaster也同样支持负载率统计,并且都支持负载率实时曲线绘制

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:23:57  更:2022-03-11 22:24:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:37:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码