百分表(千分表)与STM32通信方式和源码

文章详细介绍了如何使用STM32单片机通过MiniUSB接口与百分表/千分表进行通信,包括数据格式(28位串行,BCD码表示),接口定义,以及STM32的中断接收机制。代码示例展示了数据接收和BCD码到HEX的转换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

百分表(千分表)与STM32通信方式和源码

1、系统概述

市面上采集百分表/千分表测量仪的数据很多是通过转接线、集中器或蓝牙无线模块等,但在某些项目中使用并不方便,根据项目需求很多时候是单片机直接与百分表等仪表通信,如下图所示。
连接图

2、仪表接口及数据格式

2.1. 仪表接口

市面上采集百分表/千分表测量仪均采用Mini USB接口,其接口定义基本一致,如下图所示。
接口图

2.2数据格式

测量仪表采用主动输出方式,低位在前高位在后,其输出的数据是28位串行数据,即每个CLK时钟信号代表1bit,每bit的数值是0还是1则由DA决定,其输出时序图如下图所示。
时序图
测量仪表发送的数据按4位二进制数的BCD码表示一个10进制位。如测量仪表最低10进制位是9,则BCD码为0x9,其4位二进制就是1001,如测量仪表的10进制数是6,则BCD码为0x6,其4位二进制数位0110. 如果收到的数据是0x12345,则显示数据为12.345. 所有的28位时钟传递28位二进制数据,每四位二进制代表一个十进制的数据,24位代表6位十进制数据,第25位表示单位,如0表示公制,1则表示英制,第26位表示符号,如0表示正数,1则表示负数。

3、STM32通信

由于测量仪表是主动输出,故STM32的接口定义为输入接口。测量仪表每120ms向外发送一次数据,1秒最多发送8次数据,为了能够更准确地接收数据,采用外部中断方式进入接收。

3.1接口定义

#define METER_CLK_Pin			GPIO_Pin_5
#define METER_CLK_Port			GPIOB

#define METER_DATA_Pin			GPIO_Pin_4
#define METER_DATA_Port			GPIOB

#define METER_CLK_PinSource		GPIO_PinSource5
#define METER_CLK_PortSource	GPIO_PortSourceGPIOB
#define METER_CLK_EXTI_Line		EXTI_Line5
#define METER_CLD_VALUE()	GPIO_ReadInputDataBit(METER_CLK_Port,METER_CLK_Pin)
#define METER_DATA_VALUE()	GPIO_ReadInputDataBit(METER_DATA_Port,METER_DATA_Pin)

void Meter_Gpio_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);				//使能GPIOA和GPIOB时钟
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);			//PB3和PB4
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
		
	GPIO_InitStructure.GPIO_Pin = METER_CLK_Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_Out_PP;
	GPIO_Init(METER_CLK_Port, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = METER_DATA_Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IPU;
	GPIO_Init(METER_DATA_Port, &GPIO_InitStructure);
	
	/* EXTI line(PB5) mode config */
	GPIO_EXTILineConfig(METER_CLK_PortSource,METER_CLK_PinSource); 
	EXTI_InitStructure.EXTI_Line = METER_CLK_EXTI_Line;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 	//上升和下降沿中断
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}

3.2中断函数

//放中断函数中调用
void Meter_Rev_Data(void)
{
	if(Meter_Struct.RevTimer>100)
	{
		Meter_Struct.RevTimer = 0;
		//Meter_Struct.RevFlag = false;
		Meter_Struct.RevCount=0;
		Meter_Struct.RevValue = 0;
	}
	else
	{
		if(Meter_Struct.RevCount>=28)
		{
			Meter_Struct.NewValue = 0xFFFFFFFF;		//无效数据
			Meter_Struct.NewFlag = 2;
			return;
		}
	}
	if(METER_DATA_VALUE())
	{
		Meter_Struct.RevValue |= (0x01<<Meter_Struct.RevCount);
	}
	Meter_Struct.RevCount++;
	if(Meter_Struct.RevCount>=28)
	{
		Meter_Struct.NewValue = Meter_Struct.RevValue;
		Meter_Struct.NewFlag = 1;
	}
}

由于接收的是BCD码,并不方便使用,可将其转换为HEX方式,其转换代码如下。

/**********************************************************************
** 函数名称:uint8 BCDToHEX(uint8 BCD)
** 功能说明:将BCD码转换为10进制数据,如BCD码0x59(0101 1001)转换为10制进数59
** 入口参数:BCD待转换的数据
** 出口参数:转换后的数据															
**********************************************************************/
uint8_t BCDToHEX(uint8_t BCD)
{
	return((BCD & 0x0f) +((BCD & 0xf0)>>4)*10);	
}

在主函数中,可直接调用采集的数据,如下所示。

void Meter_Rev_NewPro(void)
{
	uint8_t i,temp[3];
	uint32_t Value;
	
	if(Meter_Struct.RevTimer>300)				//若超过300ms依然未收到脉冲信号,证明数据线未接或未开机
	{
		Meter_Struct.RevTimer = 0;
		Meter_Struct.NewValue = 0xFFFFFFFF;		//无效数据
		Meter_Struct.NewFlag = 3;
	}
	
	if(Meter_Struct.NewFlag==1)
	{
		Meter_Pro_Struct.NowBCDValue = Meter_Struct.NewValue;
		Meter_Struct.NewFlag = 0;
		
		Value = Meter_Pro_Struct.NowBCDValue&0x00FFFFFF;
		
		for(i=0;i<3;i++)
		{
			temp[i]=BCDToHEX(Value>>(i*8));
		}
		Meter_Pro_Struct.NowHexValue = temp[0]+temp[1]*100+temp[2]*10000;
		if((Meter_Pro_Struct.NowBCDValue>>24)&0x00000001)	//单位,1表示英制,0表示公制
		{
			Meter_Pro_Struct.NowHexValue =(float)Meter_Pro_Struct.NowHexValue*0.254;
		}
		if((Meter_Pro_Struct.NowBCDValue>>25)&0x00000001)	//符号,1表示负数,0表示正数
		{
			Meter_Pro_Struct.NowHexValue = 0-Meter_Pro_Struct.NowHexValue;	//负数
		}
		Meter_Pro_Struct.ErrFlag = false;
		//实际结果放大了1000倍,如公制1670=1.67mm
	}
	else if(Meter_Struct.NewFlag==2||Meter_Struct.NewFlag==3)			//数值无效
	{
		Meter_Pro_Struct.ErrFlag = true;
		Meter_Pro_Struct.NowHexValue = 0xFFFFFFFF;
	}
}

其完整的代码链接如下:
https://download.csdn.net/download/shujian123/87880737

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*参天大树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值