利用SaleaeLogic16 逻辑仪分析波形


前言

本例是通过SaleaeLogic16逻辑仪观察波形,对前几篇实验博客涉及的协议进行分析,旨在深刻的理解不同协议下的通讯方式的异同。

以下是涉及到的相关博客

UART协议:stm32之串口通信
I2C协议:AHT20温湿度采集(I2C协议)
SPI协议:玩转oled屏(基于SPI协议)

一、串口波形分析

本例使用到的是上一篇博客中的工程

基于C8T6核心板的ucOS文件移植

(一)keil虚拟波形仿真

首先在对应工程下点击新建文件

在这里插入图片描述

将以下内容复制进去并保存到对应的MDK-ARM中去

map 0x40000000, 0x40007FFF read write // APB1
map 0x40010000, 0x400157FF read write // APB2
map 0x40020000, 0x4007FFFF read write // AHB1
map 0x50000000, 0x50060BFF read write // AHB2
map 0x60000000, 0x60000FFF read write // AHB3
map 0xE0000000, 0xE00FFFFF read write // CORTEX-M4 internal peripherals

其中文件名后缀是.ini,保存类型一定要是All Files(*.*)类型

在这里插入图片描述

然后配置一些模拟仿真的参数

在这里插入图片描述
此外,还需要注意的一点是选择仿真的时钟频率与所选芯片型号是否对应,我这里是C8T6,对应外部晶振频率为8MHz

在这里插入图片描述

然后开始仿真,打开逻辑分析仪

在这里插入图片描述
设置需要显示的通道

在这里插入图片描述
点击全速运行,等待一段时间,观察波形
在这里插入图片描述

等待一段时间后,波形如下

在这里插入图片描述
我们可以看到,串口USART1_SR通道每隔2s都会有一个下降沿,我们把其展开,得到了下面的图形
在这里插入图片描述
这一整块就是我们每隔2s定时发送的数据,只不过由于数据量太小,而波特率太高,所以在2s的周期里才会表现的像一个冲击。
我们可计算以下发送这一数据所需要的时间
发送数据:hello uc/OS! 欢迎来到RTOS多任务环境!\r\n,总计约40个字节
波特率为115200bps
所需时间为(40*8)/115200 ,约为2.8ms
我们在后面逻辑分析仪对其分析的时候,会具体分析数据是怎么通过串口被发出去的。

(二)逻辑仪分析串口发送

在分析串口之前,我们首先观察以下串口的基本配置,这在下面的分析中也会用到
使用串口1、波特率为115200、停止位为1 bit、数据位为8 bit、无校验位等

具体配置如下

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

在这里插入图片描述

我们在逻辑分析仪器中可以看到,以下是一连串的密密麻麻的波形,我们把其展开分析
在这里插入图片描述

  • 计算大概的波特率

在这里插入图片描述
从逻辑分析仪中可以看到,传输一位数据大约需要8.7us
则1ms可传输约114.9425289个数据位
则1s的时间可传输114.9425289*1000114943bps
而理论速度应为115200bps

关于这部分的解释,有可能是因为SaleaeLogic16 逻辑仪设置的采样频率较低,遭成的误差

数据发送部分分析

在这里插入图片描述
对应字符的ASCII表
在这里插入图片描述
对比波形,可分析得到前两个数据发送的分别是’‘h’’, ‘‘e’’。需要注意的是
串口传输数据时先传送字符的低位,后传送字符的高位。即低位(LSB)在前,高位(MSB)在后。

串口通讯中是一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束,字符之间没有固定的时间间隔要求。停止位和空闲位都规定为高电平。

详情可参考
MSB与LSB

如果小伙伴们耐心下来去分析,可以发现这一系列密密麻麻的波形发送的正是我们想要发送的数据。

static  void  send_msg (void *p_arg)
{
  OS_ERR      err;

  (void)p_arg;

  BSP_Init();                                                 /* Initialize BSP functions                             */
  CPU_Init();

  Mem_Init();                                                 /* Initialize Memory Management Module                  */

#if OS_CFG_STAT_TASK_EN > 0u
  OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif

  CPU_IntDisMeasMaxCurReset();

  AppTaskCreate();                                            /* Create Application Tasks                             */

  AppObjCreate();                                             /* Create Application Objects                           */

  while (DEF_TRUE)
  {
			printf("hello uc/OS! 欢迎来到RTOS多任务环境!\r\n");
		  OSTimeDlyHMSM(0, 0, 2, 0,OS_OPT_TIME_HMSM_STRICT,&err);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

二、I2C协议

  • main函数
int main(void)
{	
	delay_init();     //延时初始化
	uart_init(115200);	 //串口初始化
	IIC_Init();
		while(1)
	{
		printf("温度湿度显示");
		read_AHT20_once();
		delay_ms(1500);

  }
}

  • read_AHT20_once函数
 void  read_AHT20_once(void)
{
	delay_ms(10);

	reset_AHT20();
	delay_ms(10);

	init_AHT20();
	delay_ms(10);

	startMeasure_AHT20();
	delay_ms(80);

	read_AHT20();
	delay_ms(5);
}

在这里插入图片描述

  1. AHT20复位
void  reset_AHT20(void)
{

	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("1");
	else printf("1-n-");
	I2C_WriteByte(0xBA);
	ack_status = Receive_ACK();
		if(ack_status) printf("2");
	else printf("2-n-");
	I2C_Stop();

	/*
	AHT20_OutData[0] = 0;
	AHT20_OutData[1] = 0;
	AHT20_OutData[2] = 0;
	AHT20_OutData[3] = 0;
	*/
}

在这里插入图片描述

  1. AHT20初始化
void  init_AHT20(void)
{
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("3");
	else printf("3-n-");	
	I2C_WriteByte(0xE1);
	ack_status = Receive_ACK();
	if(ack_status) printf("4");
	else printf("4-n-");
	I2C_WriteByte(0x08);
	ack_status = Receive_ACK();
	if(ack_status) printf("5");
	else printf("5-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("6");
	else printf("6-n-");
	I2C_Stop();
}

在这里插入图片描述

  1. 发送测量信号
void  startMeasure_AHT20(void)
{
	//------------
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("7");
	else printf("7-n-");
	I2C_WriteByte(0xAC);
	ack_status = Receive_ACK();
	if(ack_status) printf("8");
	else printf("8-n-");
	I2C_WriteByte(0x33);
	ack_status = Receive_ACK();
	if(ack_status) printf("9");
	else printf("9-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("10");
	else printf("10-n-");
	I2C_Stop();
}

在这里插入图片描述

  1. 读取数据
void read_AHT20(void)
{
	uint8_t   i;

	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}

	//-------------
	I2C_Start();

	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	readByte[0]= I2C_ReadByte();
	Send_ACK();

	readByte[1]= I2C_ReadByte();
	Send_ACK();

	readByte[2]= I2C_ReadByte();
	Send_ACK();

	readByte[3]= I2C_ReadByte();
	Send_ACK();

	readByte[4]= I2C_ReadByte();
	Send_ACK();

	readByte[5]= I2C_ReadByte();
	SendNot_Ack();
	//Send_ACK();

	I2C_Stop();

	//--------------
	if( (readByte[0] & 0x68) == 0x08 )
	{
		H1 = readByte[1];
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		H1 = H1>>4;

		H1 = (H1*1000)/1024/1024;

		T1 = readByte[3];
		T1 = T1 & 0x0000000F;
		T1 = (T1<<8) | readByte[4];
		T1 = (T1<<8) | readByte[5];

		T1 = (T1*2000)/1024/1024 - 500;

		AHT20_OutData[0] = (H1>>8) & 0x000000FF;
		AHT20_OutData[1] = H1 & 0x000000FF;

		AHT20_OutData[2] = (T1>>8) & 0x000000FF;
		AHT20_OutData[3] = T1 & 0x000000FF;
	}
	else
	{
		AHT20_OutData[0] = 0xFF;
		AHT20_OutData[1] = 0xFF;

		AHT20_OutData[2] = 0xFF;
		AHT20_OutData[3] = 0xFF;
		printf("lyy");

	}
	printf("\r\n");
	printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
	printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
	printf("\r\n");
}

在这里插入图片描述

小结
本例我在使用SaleaeLogic16 逻辑仪分析波形时,最小系统板并没有接AHT20传感器,所以在用逻辑仪分析波形时,观察得到的波形都是否定应答,与实际有一定出入;但是通过观察波形,分析起始、停止位、数据位等,可以更细致的了解I2C协议。


三、SPI协议

通道引脚
Channel 0片选控制信号
Channel 1数据/命令选择控制信号
Channel 2SPI时钟信号
Channel 3SPI数据信号
  • 发送命令信号
    在这里插入图片描述

  • 发送数据信号
    在这里插入图片描述

总结

关于这几种常用的协议,我在这里只是作了一个最简单的分析,由于编者能力有限,如有问题,望大家不吝指教!!!

关于本次分析所涉及到的工程与文件,我放到了这里提取码:negw,有需要自取

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值