计算模拟I2C的传输速率

在编写I2C器件的驱动时,经常会看到手册中提及该器件的最高传输速率,如:


而在配置寄存器实现I2C中也是需要配置I2C的传输速率,如:


但模拟I2C的速率该如何计算?

首先一般I2C速率的单位是kbit/s,I2C传输速率的定义:每秒传输的比特位数。
先把代码贴出来(这里的代码在之前的日志中贴出来过):

#define I2C_DELAY()  I2CSysCtlDelay(30)	//!<I2C速率约为237Kb/s(若为40,则速率约为178Kb/s)


/*
 * @brief  SysCtlDelay
 * @param  ulCount 延时值,必须大于0
 * @retval (3/(120M))s = 40MHz
 */
void I2CSysCtlDelay(unsigned long ulCount)
{
	
   __asm("    subs    r0, #1\n"
         "    bne.n   I2CSysCtlDelay\n"
         "    bx      lr");
   
}

/*!
 *  @brief	I2C1起始信号
 *  @param	none
 *  @return	none
 *  @note	数据:D  时钟:C  高:H  低:L  输出:O  输入:I  延时:_
 *  @note	DOCO_DHCH_DL__CL
 */
void I2C1_Start(void)
{
    I2C1_SDA_OUT(); 
    I2C1_SCL_OUT(); 
    I2C_DELAY();
    I2C1_SDA_H();  
    I2C1_SCL_H(); 
    I2C_DELAY();  
    I2C1_SDA_L();
    I2C_DELAY();
    I2C_DELAY();
    I2C1_SCL_L();
}

/*!
 *  @brief	I2C1结束信号
 *  @param	none
 *  @return	none
 *  @note	数据:D  时钟:C  高:H  低:L  输出:O  输入:I  延时:_
 *  @note	DOCO_DLCL_CH___DH__
 */
void I2C1_Stop(void)
{
    I2C1_SDA_OUT(); 
    I2C1_SCL_OUT();
    I2C1_SDA_L();  
    I2C1_SCL_L(); 
    I2C_DELAY();
    I2C1_SCL_H();
    I2C_DELAY();  
    I2C_DELAY();
    I2C_DELAY();
    I2C1_SDA_H();
    I2C_DELAY();
    I2C_DELAY();
}

/*!
 *  @brief	主机向I2C1总线发送一个字节
 *  @param	data:数据
 *  @return	0:失败  1:成功
 *  @note	数据:D  时钟:C  高:H  低:L  输出:O  输入:I  延时:_  读取:R
 *  @note	(_DH/L_CH__CL)*8_DHDI_CH_DR_CL_DO
 */
uint8 I2C1_Send_byte(uint8 data)
{
	uint8 k;
	for(k=0;k<8;k++){//!<发送8bit数据
		I2C_DELAY();
		if(data&0x80){
			I2C1_SDA_H();
		}else{
			I2C1_SDA_L();
		}
		data=data<<1;
		I2C_DELAY();
		I2C1_SCL_H();
		I2C_DELAY();
		I2C_DELAY();
		I2C1_SCL_L();
	}
	I2C_DELAY();//!<延时读取ACK响应
	I2C1_SDA_H();
  
	I2C1_SDA_IN();//!<设为输入
	I2C_DELAY();
	I2C1_SCL_H();   
	I2C_DELAY();
  
	k=I2C1_SDA_READ();//读取ACK/NACK
	I2C_DELAY();
	I2C1_SCL_L();
	I2C_DELAY();
	I2C1_SDA_OUT();
	if(k){ NACK响应
		return 0;
	}
	return 1;
} 
我们计算的方法是:首先计算模拟I2C发送一个字节所需要多长时间,之后除以8,以算出发送一位需要多长时间。

 由于寄存器操作的时间可忽略不计,故主要计算其中的延时时间。
在开始信号 start()中,含有 4个delay,设1个delay占用的时间为n(之后再计算),则一个start()占用4n。
在停止信号stop()中,含有 6个delay,则一个stop()占用6n。
发送一个字节中有 8* 4n+5n,占用37n。

一般最简单的I2C时序是,开始->发送一个字节->结束,故发送一个字节的总时间为47n. 

然后准备计算n,一个delay函数执行一次需要三个时钟周期,当前使用的时钟为120M,故执行一个delay占用[1/(40M)]s,
所以 
I2CSysCtlDelay(30)所占用3/4 us.

综上,发送一个字节所需要 35.25us=141/4 us,1bit需要141/32 us,所以I2C的发送速率为32/141 Mbit/s
≈227kbit/s
同理可以算出接收速率,然后选一个较小值,就可以当做当前模拟I2C的速率,注意这里的值也是大致的值,做参考。

另外若不清楚当前使用的时钟是否确为120M,可以使用以下简单暴力的方法哦:

在main函数中,采用点灯计时:

while(1)
{
    I2CSysCtlDelay(1000*10000);
    LED_ON();
    I2CSysCtlDelay(1000*10000);
    LED_OFF(); 
} 


通过计时,LED灯亮灭十下约为5s。
故函数执行一次,所用的时间为5/10/(1000*10000*2)  = 1/(40M) s
 所以时钟周期为 1/(40M)/3 = 1/(120M)s,所以时钟频率为120M


  • 20
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 CSMA/CD 协议碰撞检测的 C 语言编程模拟示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX_BACKOFF 10 // 最大重传次数 #define SLOT_TIME 1 // 最小时间槽长度 #define PROP_DELAY 2 // 传播延迟 int main() { srand(time(NULL)); // 初始化随机数种子 int num_stations; // 站点数量 printf("请输入站点数量:"); scanf("%d", &num_stations); int collisions = 0; // 碰撞次数 int backoff_counts[num_stations]; // 各站点的退避计数器 int collision_detected = 0; // 是否检测到碰撞 for (int i = 0; i < num_stations; i++) { backoff_counts[i] = 0; // 初始化退避计数器 } do { int channel_busy = 0; // 是否检测到信道忙碌 for (int i = 0; i < num_stations; i++) { if (backoff_counts[i] == 0) { // 退避计数器为0时,尝试发送数据帧 printf("站点 %d 尝试发送数据帧\n", i); if (channel_busy) { // 检测到信道忙碌,发生碰撞 printf("碰撞发生!\n"); collisions++; backoff_counts[i] = rand() % MAX_BACKOFF + 1; // 生成随机退避计数器 collision_detected = 1; } else { // 未检测到信道忙碌,发送数据帧并等待传输完成 printf("数据帧发送成功\n"); channel_busy = 1; collision_detected = 0; } } else { // 退避计数器不为0时,将计数器减1 backoff_counts[i]--; } } if (collision_detected) { // 检测到碰撞,等待随机时间后重传 int backoff_time = (rand() % (1 << backoff_counts[0])) * SLOT_TIME + PROP_DELAY; // 计算重传等待时间 printf("等待 %d 个时间槽后重传\n", backoff_time); for (int i = 0; i < backoff_time; i++) { printf("."); sleep(SLOT_TIME); } printf("\n"); } else { // 未检测到碰撞,等待数据传输完成 sleep(PROP_DELAY); } } while (collisions < 10); // 重复执行直到发生10次碰撞 printf("发生了 %d 次碰撞\n", collisions); return 0; } ``` 这个程序模拟一个简单的 CSMA/CD 网络,通过随机生成退避计数器来模拟碰撞后的重传等待时间。程序中的 sleep 函数用于模拟数据帧的传输时间和传播延迟。注意,这个程序只是一个简单的模拟,实际的 CSMA/CD 网络还需要考虑更多的因素,比如信道长度、传输速率等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值