ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

51单片机实战教程(34 线缆摇摆测试机设计)

2022-01-30 00:03:00  阅读:168  来源: 互联网

标签:代码 51 34 单片机 按下 volatile 如下 printh txt


本文将讲解51单片机在线缆摇摆测试机中的应用,包含单片机程序及人机界面程序设计,将以本人以前做过的一个案子为例来做讲解。

公司外购一款线缆,进料检验时,需要做摇摆测试,以判定品质是否合格。公司当时没有摇摆测试机,也曾外让采购外购,但因价格比较高,体积比较大,且不太适合该线缆的测试而搁浅,最后决定自制。 

如果你以前没接触过线缆制造,也许对摇摆测试不是很了解,这里我就做些简单的介绍。我们常用的软线缆,如USB、HDMI、VGA线缆等。在使用过程中会受到弯曲,多次弯曲后可会能发生:外皮开裂,芯线断裂,连接器脱落、SR脱落、脱焊等问题。为将避免这些问题,需要在产品推向市场前做测试,看是否会发生这些问题,以便做针对性改善。通常的测试方法是:将线缆一端夹在一个轴为水平,可以正反旋转的转盘上;另一端悬挂指定质量的砝码;转盘在电机的带动下,按一定的速度与角度,反复正反转动规定的次数。由于测试时看起来是在摇摆,所以称它为摇摆测试,这个测试机也就是摇摆测试机。英文说法是“Cable flex test”,如HDMI标准中列出了“Cable flex”测试项,并指定了测试方法,如下:

设计方案确定  在明白了摇摆测试后,讲一下摇摆测试机的设计方案。这个摇摆测试机,搞得很简单。主要执行机构就是一个带减速器的57步进电机与固定在减速器输出轴上的样品装夹转盘。电机安装在一个铝型材的机架上。如下图:

电控部分:供电电源用的是24V/10A 的开关电源,步进驱动器是MC542G,控制采用STC IAP5W4K61S4单片机为主控的控制板,人机界面用的是7吋触摸(TJC8048K070_011R)。开关电源,步进驱动器,主板,及触摸屏一并装入一个仪表箱中,仪表箱由商家按图开孔。做好后的控制仪表箱如下图示:

 人机界面设计  这个人机界面比较简单就两个页面,一个是主界面,如下:

 另一个是输入键盘,如下:

主界面上控件只有两种,一种是文本控件与按钮控件。点击文本控件,即可弹出输入键盘页面实现输入设置,主页面背景使用色是PS做的图片。图片另存为一张图片在按钮部位做成不同的颜色,工作按钮按下切图。如下:

在主界面添加了三个变量,如下:

 前两个为数值型,最后一个为字符串。下面看一下t0~t4按下事件代码,t0按下事件代码如下:

mstrlen.val=3
kflag.val=0
printh A0
page keybdB0

t1按下事件代码如下:

mstrlen.val=3
kflag.val=1
printh A0
page keybdB0

 t2按下事件代码如下:

mstrlen.val=3
kflag.val=2
printh A0
page keybdB0

t3按下事件代码如下:

mstrlen.val=4
kflag.val=3
printh A0
page keybdB0

t4按下事件代码如下:

mstrlen.val=4
kflag.val=3
printh A0
page keybdB0

再看一下 主界面的按钮b0~b3,按下事件代码,b0按下事件代码如下:

mparameter.txt=t0.txt
mparameter.txt=mparameter.txt+t1.txt+t2.txt+t3.txt+t4.txt
printh A1

b1按下事件代码如下:

printh A2

b2按下事件代码如下:

printh A3

b3按下事件代码如下:

printh A4

再看一下键盘页面,键盘页面也是由两种控件组成,分别为文本控件与按钮控件,文本控件有两个

t0与show,t0用做背景,show用作输入显示。先看一下数字按牛的弹起事件代码(按下事件代码为空,没有按下事件代码),b1的弹起事件代码如下:

printh A0
strlen show.txt,sys0
if(sys0<page0.mstrlen.val)
{
  show.txt=show.txt+"1"
}

b2的弹起事件代码如下:

printh A0
strlen show.txt,sys0
if(sys0<page0.mstrlen.val)
{
  show.txt=show.txt+"2"
}

其他数字键的按钮的弹起事件代码,类似不再一一列举。

b10按钮(-)的作用是Back键的作用,弹起事件代码如下:

printh A0
show.txt=show.txt-1

b200按钮(DEL)的弹起事件代码如下:

printh A0
show.txt=""

b210按钮(OK)的弹起事件代码如下:

printh A0
if(page0.kflag.val==0)
{
  strlen show.txt,sys0
  if(sys0<page0.mstrlen.val)
  {
    page0.t0.txt="000"
    page0.t0.txt=page0.t0.txt-sys0
    page0.t0.txt=page0.t0.txt+show.txt
  }else
  {
    page0.t0.txt=show.txt
  }
}else if(page0.kflag.val==1)
{
  strlen show.txt,sys0
  if(sys0<page0.mstrlen.val)
  {
    page0.t1.txt="000"
    page0.t1.txt=page0.t1.txt-sys0
    page0.t1.txt=page0.t1.txt+show.txt
  }else
  {
    strlen show.txt,sys0
    if(sys0<page0.mstrlen.val)
    {
      page0.t1.txt="000"
      page0.t1.txt=page0.t1.txt-sys0
      page0.t1.txt=page0.t1.txt+show.txt
    }else
    {
      page0.t1.txt=show.txt
    }
  }
}else if(page0.kflag.val==2)
{
  strlen show.txt,sys0
  if(sys0<page0.mstrlen.val)
  {
    page0.t2.txt="000"
    page0.t2.txt=page0.t2.txt-sys0
    page0.t2.txt=page0.t2.txt+show.txt
  }else
  {
    page0.t2.txt=show.txt
  }
}else if(page0.kflag.val==3)
{
  strlen show.txt,sys0
  if(sys0<page0.mstrlen.val)
  {
    page0.t3.txt="0000"
    page0.t3.txt=page0.t3.txt-sys0
    page0.t3.txt=page0.t3.txt+show.txt
  }else
  {
    page0.t3.txt=show.txt
  }
}else if(page0.kflag.val==4)
{
  strlen show.txt,sys0
  if(sys0<page0.mstrlen.val)
  {
    page0.t4.txt="0000"
    page0.t4.txt=page0.t4.txt-sys0
    page0.t4.txt=page0.t4.txt+show.txt
  }else
  {
    page0.t4.txt=show.txt
  }
}
page page0

以上代码中 带printh 行才是与当片机通信的代码行。printh A0是向单片机发送0xA0(让单片机控制蜂鸣器,发出按键音),输入键盘上,除了printh A0,没有其他带printh的代码行。主界面上,按下确定按钮(b0),打包设置参数到mparameter.txt,并发送0xA1(更新设置数据指令);按下开始测试按钮(b1),发送0xA2(开始测试指令);按下暂停测试按钮(b2),发送0xA3(暂停测试指令);按下测试停止按钮(b3),发送0xA4(停止测试指令)。

单片机程序设计  单片机通过PWM模块发送占空比为50%的PWM脉冲给步进驱动器做步进脉冲,单片机Timer 0 做计数器,对脉冲进行计数,以控制反复摆动角度及换向时机。通过外部中断侦测可能出现线缆芯线断裂及电阻异常。单片机与触控屏通过Uart1 实现串口通信。

端口定义 代码如下:

#ifndef __MYPORT_H__
#define __MYPORT_H__

#include "stc15w4k.h"
#include "stc15w4kgpio.h"

#define MONITOR_PORT P2

sbit BUZZER = P4^7;					//buzzer control bit
sbit INT0_IN = P3^2;        //INT0 input pin, sample wire  broken detect
sbit puslePin = P4^4;
sbit motorEnable = P4^3;
sbit motorDirection = P4^2;


sbit T0_In = P3^4;					//T0 input pin for pusle counting
sbit RxD_2 = P3^6;						 //Usart1 RxD
sbit TxD_2 = P3^7;						 //Usart1 TxD

#endif

主程序头文件  main.h代码如下:

#ifndef __MAIN_H__
#define __MAIN_H__

#include "myport.h"
#include "stcpwm.h"
#include "stc15w4kgpio.h"
#include "stctimer.h"
#include "stcuart.h"
#include "delay.h"

Timer_TypeDef mTimerStruct;
//extern ui32 const FOSC; 
ui32 const FOSC = 30000000L; 
ui16 code Vbg_ROM _at_ 0xf3f7; //IAP15W4K61S4
volatile ui8 receiveDataFlag = 0;
volatile ui8 mRdata = 0;
volatile ui8 reFlag = 0;
ui32 const motorsetp = 12800; //64*200 ui16 PAngle = 90;
volatile ui16 nAngle = 90;
volatile ui16 PAngle = 90;
volatile ui32 pPusle = 2000;
volatile ui32 nPusle = 2000;
volatile ui8 mstr[18] = "";
volatile ui8 mstr1[5] ="";
volatile ui8 mstr2[10] ="";                                     
volatile ui8 mNbits = 0;
volatile ui16 speed = 60;
volatile ui32 pusleFr = 1600;
volatile ui32 targetConts = 500;
volatile ui16 rCounts = 0;
volatile ui8 runFalg = 0;
volatile ui8 cycleFlag = 1;
volatile ui8 finishFlag = 0;
volatile ui8 suspendFlag = 0;
volatile ui8 initData = 0;
ui8 const GRATION = 1;
ui8 const CALRaTIO = 5;


//UART1_TYPDEF mUART1_Struct;



//**************************************************
void SoundBuzzer();

//*******************************************************
void SendQuMark(); //send half double quotation mark

//***************************
void SendEndMark(); //Send end mark

#endif

主程序 main.c 代码如下:

//*****************************************************
void Usart1_Routine(void) interrupt 4
{
	if(!receiveDataFlag)
	{
		if(RI)
		{
			RI=0;
			mRdata = SBUF;
			reFlag = 1;
		}
	}
}
//End of Usart1_Routine

//*****************************************************
void Timer0Int() interrupt 1
{
	++cycleFlag;
	PWMCR &= 0x7F; //PWM disable
	switch(cycleFlag)
	{
		case 1:
			rCounts++;
			TR0 = 0;
			TL0 = 65536 - pPusle;
			TH0 = (65536 - pPusle) >> 8;
			TR0 = 1;
			break;	
		case 2:
			motorDirection = !motorDirection;
			TR0 = 0;
			TL0 = 65536 - pPusle;
			TH0 = (65536 - pPusle) >> 8;
			TR0 = 1;
			break;
		case 3:
			TR0 = 0;
			TL0 = 65536 - nPusle;
			TH0 = (65536 - nPusle) >> 8;
			TR0 = 1;
			break;
		case 4:
			motorDirection = !motorDirection;
			cycleFlag = 0;
			TR0 = 0;
			TL0 = 65536 - nPusle;
			TH0 = (65536 - nPusle) >> 8;
			TR0 = 1;
			break;
	}
	if(rCounts >= targetConts)
	{
		//runFalg = 0;
		finishFlag = 1;
		TR0 = 0;
	}
	else
		PWMCR |= 0x80; //PWM enable
}
//End of Timer0_Routine() interrupt 1

//*****************************************************
void Timer1Int() interrupt 3
{
	PWMCR &= 0x7F; //PWM disable
	TR1 = 0;
	SoundBuzzer();
}

void main()
{
	GPIOInit(0xFF, 0xFF,BI_IO);
	P0 =0xFF;
	P1 =0xFF;
	P2 =0xFF;
	P3 =0xFF;
	P4 =0xFF;
	P5 =0xFF;
	P6 =0xFF;
	P7 =0xFF;
	//**************************************
	EA = 1;
	
	GPIOInit(GPIO_P4, GPIO_PIN4, PP_OUT); //init P4.4 PP_OUT
	P_SW2 |= 1 << 7; //visit extend SRF enable

	Usart1Mode(0x01); //8bits variable baud rate
	Usart1MulComDisable(); //multip machine communitate disable
	Usart1ReceiveEnable();
	UsartBaudRateDouble(0); //without double baud rate
	Usart1BaudTimer(1);//selsct baud rate timer2
	Usart1BaudRateFreDivDis();
	Usart1Pin(0x01);//P3.6/RxD_2, P3.7/TxD_2
	GPIOInit(GPIO_P3, GPIO_PIN7, PP_OUT); //push_pull out
	Usart1IntEnable();//Usart1 interrupt enable
	Usart1BaudRate(9600);//configure Usart1 baud rate 9600
	PS = 1;
	Usart1ResetTi();//set TI to 0
	Usart1ResetRi();//set TI to 0
	TIMER_T2Start();//Timer2 start
	
	Timer_Initstruct(&mTimerStruct);
	mTimerStruct.nTimer = timer0;
	mTimerStruct.mWorkMode = _load16bit;
	mTimerStruct.CountEnable = 1; //work as counter
	mTimerStruct.IntEnable = 1;   //int enable
	Timer_Init(&mTimerStruct);

	SoundBuzzer();
	Delay100xms(5,8);
	SoundBuzzer();
	Delay100xms(5,8);
	SoundBuzzer();
	Delay100xms(5,8);
	motorEnable = 1;
	
	while(1)
	{
		if(reFlag)
		{
			reFlag = 0;
			switch(mRdata)
			{
				case 0xA0:
					SoundBuzzer();
					break;
				case 0xA1: //parameter configure ok
					if(!runFalg)
					{
						SoundBuzzer();
						//Delay10xms(2,8);
						
						memset(mstr,0, strlen(mstr));
						receiveDataFlag = 1;
						mNbits = 0;
						UART1_SendString("prints page0.mparameter.txt,0");
						SendEndMark();
						RI = 0;
						while(mNbits < 17)
						{
							while(!RI);
							RI = 0;
							mstr[mNbits] = SBUF;
							mNbits++;
						}
						receiveDataFlag = 0;
						mNbits = 0;
						UART1_SendString("page0.t7.txt=");
						SendQuMark();
						UART1_SendString(mstr);
						SendQuMark();
						SendEndMark();
						Delay100xms(10,8);
						
						
						//memset(mstr1, 0, strlen(mstr1));
						StringSub(mstr1, mstr, 0, 3);
						PAngle = atol(mstr1);
						UART1_SendString("page0.t0.txt=");
						SendQuMark();
						UART1_SendString(mstr1);
						SendQuMark();
						SendEndMark();
						
						//memset(mstr1, 0, strlen(mstr1));
						StringSub(mstr1, mstr, 3, 3);
						nAngle = atol(mstr1);
						UART1_SendString("page0.t1.txt=");
						SendQuMark();
						UART1_SendString(mstr1);
						SendQuMark();
						SendEndMark();
						
						
						//memset(mstr1, 0, strlen(mstr1));
						StringSub(mstr1, mstr, 6, 3);
						speed = atol(mstr1);
						UART1_SendString("page0.t2.txt=");
						SendQuMark();
						UART1_SendString(mstr1);
						SendQuMark();
						SendEndMark();
						
						//memset(mstr1, 0, strlen(mstr1));
						StringSub(mstr1, mstr, 14, 4);
						targetConts = atol(mstr1);
						UART1_SendString("page0.t4.txt=");
						SendQuMark();
						UART1_SendString(mstr1);
						SendQuMark();
						SendEndMark();
						
						
						pusleFr = (f32)motorsetp * speed /10800 * GRATION * (PAngle + nAngle);  //360*60/2=10800
						
						pPusle = (f32)motorsetp * PAngle * GRATION * CALRaTIO/ 720; 
						nPusle = (f32)motorsetp * nAngle * GRATION * CALRaTIO/ 720;
						
						LongtoString(pPusle,mstr2); //nAngle
						UART1_SendString("page0.t7.txt=");
						SendQuMark();
						UART1_SendString(mstr2);
						SendQuMark();
						SendEndMark();
						Delay100xms(10,8);
						
						LongtoString(nPusle,mstr2); //nAngle
						UART1_SendString("page0.t7.txt=");
						SendQuMark();
						UART1_SendString(mstr2);
						SendQuMark();
						SendEndMark();
						Delay100xms(10,8);
						
						UART1_SendString("page0.t7.txt=\"\"");
						SendEndMark();
					}
					
					
					
					break;
				case 0xA2: //start test
					SoundBuzzer();
					if(!runFalg)
					{
						runFalg = 1;
						initData = MONITOR_PORT;
						
						motorDirection = 1;
						//init timer0
						TF0 = 0;
						TR0 = 0;
						TL0 = 65536 - pPusle;
						TH0 = (65536 - pPusle) >> 8;
						TIMER_T0Start();
						motorEnable = 1;
						PWM_Out(PWM_CH4, pusleFr, 0, O2);
					}
					else 
					{
						if(suspendFlag)
						{
							PWMCR |= 0x80; //PWM enable
							suspendFlag = 0;
						}
						if(finishFlag == 1)
							runFalg = 0;
					}
					break;
				case 0xA3: //suspend test
					SoundBuzzer();
					PWMCR &= 0x7F; //PWM disable
					suspendFlag = 1;
					break;
				case 0xA4: //stop test
					SoundBuzzer();
					PWMCR &= 0x7F; //PWM disable
					TR0 = 0;
					suspendFlag = 0;
					finishFlag = 0;
					runFalg = 0;
					rCounts = 0;
					cycleFlag = 1;
					
					LongtoString(rCounts,mstr2); //nAngle
					UART1_SendString("page0.t6.txt=");
					SendQuMark();
					UART1_SendString(mstr2);
					SendQuMark();
					SendEndMark();
					break;
			}
			mRdata = 0;
		}
		if(runFalg)
		{
			if(initData <= MONITOR_PORT)
			{
				UART1_SendString("page0.t5.txt=");
				SendQuMark();
				UART1_SendString("测试中");
				SendQuMark();
			  SendEndMark();
				
				LongtoString(rCounts,mstr2); //nAngle
				UART1_SendString("page0.t6.txt=");
				SendQuMark();
				UART1_SendString(mstr2);
				SendQuMark();
			  SendEndMark();
			}
			else //Test Fail
			{
				PWMCR &= 0x7F; //PWM disable
				runFalg = 0;
				finishFlag = 2;
			}
			if(suspendFlag)
			{
				UART1_SendString("page0.t5.txt=");
				SendQuMark();
				UART1_SendString("暂停中");
				SendQuMark();
			  SendEndMark();
			}
		}
		else
		{
			switch(finishFlag)
			{
				case 0:
					UART1_SendString("page0.t5.txt=");
					SendQuMark();
					UART1_SendString("空闲");
					SendQuMark();
					SendEndMark();
					break;
				case 1:
					UART1_SendString("page0.t5.txt=");
					SendQuMark();
					UART1_SendString("测试完成,Pass!");
					SendQuMark();
					SendEndMark();
					break;
				case 2:
					UART1_SendString("page0.t5.txt=");
					SendQuMark();
					UART1_SendString("测试失败,Fail!");
					SendQuMark();
					SendEndMark();
					UART1_SendString("page0.t5.bco=63488");
					SendEndMark();
					break;
			}
		}
	}
}

//****************************************************/
void SoundBuzzer()
{
	BUZZER = 0;
	Delay100xms(3,8);
	BUZZER = 1;
}
//End of SoundBuzzer()

//*******************************************************
void SendQuMark() //send half double quotation mark
{
	ES = 0;
	Usart1SendByte(34);
	ES = 1;
}
//End of Usart1BaudRate(ui32 myBaudRate)

//***************************
void SendEndMark() //Send end mark
{
	ES = 0;
	Usart1SendByte(0xFF);
	Usart1SendByte(0xFF);
	Usart1SendByte(0xFF);
	ES = 1;
}
//End of SendEndMark()

上面代码中省去了,测试中线缆异常的处理代码。机器的运行效果如下图:

标签:代码,51,34,单片机,按下,volatile,如下,printh,txt
来源: https://blog.csdn.net/billliu66/article/details/122514543

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有