⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ussensor.c

📁 DIY一个属于你的超声波测距传感器程序的构思和设计
💻 C
📖 第 1 页 / 共 3 页
字号:
						
						break;
					}
				
					case (AUTO_MEASURE + READ_BACK_DATA):
					{
						// 自动测量模式下被动数据返回处理
						g_bTxdFinish = TRUE;												// 因无需数据返回,所以建立数据返回结束标志
						g_ucWorkStat = WAIT_FINISH;									// 转换到等待数据返回结束状态
						break;
					}

					case (SINGLE_MEASURE + NOPROC_BACK):
					{
						// 返回指定次数的数据,不作处理
						backMeaData(NOPROC_BACK);						
						break;
					}
					
					case (SINGLE_MEASURE + MID_BACK):
					{
						// 去除最大最小值后返回
						if(g_ucModePara<3)
						{
							g_ucWorkMode = SINGLE_MEASURE + NOPROC_BACK;	// 如果测量次数小于 3 ,则按照不处理模式返回
						}
						else
						{
							sortLastData(g_ucModePara);
							backMeaData(MID_BACK);
						}
						break;
					}

					case (SINGLE_MEASURE + MEAN_BACK):
					{
						// 返回平均值
						backMeaData(MEAN_BACK);
						break;
					}

					case (SINGLE_MEASURE + MID_MEAN_BACK):
					{
						if(g_ucModePara < 4)
						{
							g_ucWorkMode = SINGLE_MEASURE + MID_BACK;		// 如果测量次数小于 4 ,则按照去除最大最小值模式返回
						}
						else
						{
							sortLastData(g_ucModePara);
							backMeaData(MID_MEAN_BACK);
						}
						break;
					}

					default:break;				
				}
				break;
			}
			
			case WAIT_FINISH:
			{
				if(g_bTxdFinish)															// 等待数据返回结束
				{
					g_bTxdFinish = FALSE;
					g_ucWorkStat = WAIT_START;									// 开始新一轮测量过程
				}
				break;
			}
			
			default:break;
		}																									// 工作状态处理部分结束	
	}
}

/********** 函数 **************/

/********************************************/
/*名称:	 init_hardware											*/
/*用途:  硬件初始化函数      								*/
/*说明:	 初始化所有相关的硬件状态						*/
/********************************************/

void init_hardware(void)
{
	
	/* 初始化系统时钟 */
	CLK_DIV = CLKDIV1_C;
	
	/* 初始化I/O口*/
	P1M0 = P1M0_C;
	P1M1 = P1M1_C;
	
	P3M0 = P3M0_C;
	P3M1 = P3M1_C;
	
	g_bSend_Ctrl = SEND_INVALID;									// 超声波输出驱动无效
	g_bUltraSonicDrvValid = FALSE;
	
	g_bCut_Off = CUT_OFF_INVALID;									// 回波抑制无效
	g_b852Inhibit = DIS852OUT;										// 禁止 852 输出
	
	/* 初始化定时器 */
	
	TMOD = T0MODE1|T1MODE2;		// Timer0工作在模式1 ,16位定时,Timer1 工作在模式 2 ,8位重加载,作为波特率发生器;
	AUXR = AUXR&CLR_T0X12_C;	// Timer0 工作在12分频
	
	TCON = INT1_DOWN;					// 定义中断1 的触发方式 
		
	TH0 = TIME1msH_C;
	TL0 = TIME1msH_C;
	TR0 = TRUE;
	
	/* 初始化中断 */
	
	IE = EnT0_C|EnINT1_C;				// 允许 Timer0、INT1、PCA 中断
	
	IPH = NOIP_C;													// 此处不设优先级,有各功能模块自身设定
	IP = NOIP_C;					
	
	/* 看门狗初始化程序 */	
	WDT_CONTR = Watchdog_C;								// 设置 WDT 分频
	
	/* 初始化UART  */
	init_SIO(B_19200);
	IE = IE|EnUART_C;											// 允许 UART 中断

	/* 初始化PCA */
	CMOD = FOSCdiv2_C|EnCF_C;							// PCA 时钟源为 Fosc/2 , 允许 count 溢出中断 CF。休眠时 PCA 工作
	
	CCAPM1 = EnCMP_C|EnMAT_C|EnCCFI_C;		// PCA 的模块 1 用于控制脉冲发送和增益变化,计时器模式,比较、匹配中断

	
	IE = IE|EnPCALVD_C;										// 初始化PCA中断

	CL = 0;
	CH = 0;
	CCON = CCON&STOPPCA_C;								// 上电时 PCA 停止待命	
}

/********************************************/
/*名称:	init_var														*/
/*用途: 变量初始化		      								*/
/*说明:	初始化全局变量											*/
/********************************************/

void init_var(void)
{
	// WDT参数初始化
	g_b1msFlag=FALSE;
	gc_uiWdtCnt=WDTTIME_C;
	
	/* 状态初始化 */
	g_ucWorkStat = WAIT_START;
	
	g_b1msFlag = FALSE;
	gc_uc10msCnt = 10;
	
	g_ucWorkDispStat = NORMAL;
	gc_uiWorkDispTimeCnt = ga_uiWorkDispTime[g_ucWorkDispStat];
	gc_ucWorkDispNumCnt = ga_ucWorkDispNum[g_ucWorkDispStat];
	
	
	/* 初始化UART 部分变量 */
	gi_ucSavePtr = 0;
	gi_ucGetPtr = 0;
	
	g_bNewData = FALSE;
	g_bStartRcv = FALSE;
	g_bTxdFinish = FALSE;
	
	ga_ucTxdBuf[0] = 0x55;										// 因为发送缓冲区暂不作他用,所以先存好,以减少代码
	ga_ucTxdBuf[1] = 0xAA;										// 帧头, 
	ga_ucTxdBuf[3] = MY_ADDR;									// 自己的地址作为发送方地址送出
		
	/* 初始化超声波检测、计算部分变量 */
	g_ucWorkMode = STOP_MEASURE;
	g_ucModePara = 0;
	gc_ucMeaPeriodCnt = 0;
	gc_ucMeaTimesCnt = 0;
	gc_ucGapAtSingleMea = 0;
	
	gi_ucDataSavePtr = 0;
	
	g_bGainCtrl = FALSE;
}


/********************************************/
/*名称:	feed_watchdog												*/
/*用途: 喂狗程序		      									*/
/*说明:	请参照STC12C5410的喂狗方法说明			*/
/********************************************/

void feed_watchdog(void)
{
	WDT_CONTR = CLRWDT_C;
} 

/********************************************/
/* 名称:init_SIO														*/
/* 用途:初始化串口, 												*/
/* 参数: 波特率 , 模式固定为:1 							*/
/* 		1 START 8 DATA 1 STOP 								*/
/********************************************/

void init_SIO(unsigned char baud)
{
	// 波特率表
	unsigned char	code	TH_Baud[5]={B4800_C,B9600_C,B19200_C,B38400_C,B57600_C};
	
	AUXR = AUXR|SET_T1X12_C;
	TH1 = TH_Baud[baud];
	TL1 = TH_Baud[baud];
	TR1 = TRUE;
	
	SCON	=	UART_MODE1_C|EN_RCV_C;	// 8 位模式( MODE 1)
}

/********************************************/
/*名称:	dataFrame_OK												*/
/*用途: 检测接收缓冲区数据,     						*/
/*说明:	如果收到正确的数据帧则返回真				*/
/********************************************/

bit dataFrame_OK(void)
{
	unsigned char i,j,k;
	bit flag;
	
	flag = FALSE;
	
	while(gi_ucGetPtr != gi_ucSavePtr)
	{
		if(g_bStartRcv == FALSE)
		{
			/*  检测帧头 0x55 0xAA MY_ADDR */
			k = 0;			
			
			i = (gi_ucGetPtr - 5)&(MaxRcvByte_C-1);			
			if(ga_ucRcvBuf[i]==0x55)
			{
				k++;
			}
			
			i = (gi_ucGetPtr - 4)&(MaxRcvByte_C-1);			
			if(ga_ucRcvBuf[i]==0xAA)
			{
				k++;
			}
			
			i = (gi_ucGetPtr - 3)&(MaxRcvByte_C-1);			
			if(ga_ucRcvBuf[i]==MY_ADDR)
			{
				k++;
			}
			
			if(k == 3)
			{
				//帧头正确,启动数据区接收 
				g_bStartRcv=TRUE;	
				i=(gi_ucGetPtr-1)&(MaxRcvByte_C-1);						
				gc_ucDataLen = ga_ucRcvBuf[i];
				gi_ucStartPtr = gi_ucGetPtr;
				gi_ucEndPtr= (gi_ucGetPtr + gc_ucDataLen)&(MaxRcvByte_C-1); 
			}
		}
		else
		{
			//开始接收数据处理
			if(gi_ucGetPtr==gi_ucEndPtr)
			{
				/* 数据帧接收完 */
				g_bStartRcv=FALSE;
			
				j=gi_ucStartPtr;	
				k= 0;
				for(i=0;i<gc_ucDataLen;i++)
				{
					// 计算CS
					k +=ga_ucRcvBuf[j];		
					j=(j+1)&(MaxRcvByte_C-1);
				}
			
				// 取校验和
				k = ~k;
				if(k==ga_ucRcvBuf[j])
				{
					flag = TRUE;							// 数据校验正确
				}
			}
		}
		gi_ucGetPtr=(gi_ucGetPtr+1)&(MaxRcvByte_C-1);		
	}	
	return (flag);
}																					

/********************************************/
/*名称:	do_Command													*/
/*用途: 根据收到的数据帧命令做相应处理			*/
/********************************************/

void do_Command(void)
{
	unsigned char ucCommand,i,j,k,sum,n;
	
	union
	{
		unsigned int all;
		unsigned char b[2];
	}uitemp;
	
	unsigned char idata *ucI_Ptr;
	unsigned char xdata *ucX_Ptr;
	unsigned char code	*ucC_Ptr;

	ucCommand = ga_ucRcvBuf[gi_ucStartPtr]; 			// 取出数据帧中的命令
	
	switch (ucCommand)
	{
		case READ_MEMORY:
		{
			// 读内存数据处理
			i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);		
			uitemp.b[1] = ga_ucRcvBuf[i];								// 取读数据地址, 注意 C51 中的多字节数据与PC中相反
			i =(i+1)&(MaxRcvByte_C-1);
			uitemp.b[0] = ga_ucRcvBuf[i];
			i =(i+1)&(MaxRcvByte_C-1);
			n = ga_ucRcvBuf[i];													// 取读数据长度
			if(n>(MaxTxdByte_C - 10))
			{
				n = (MaxTxdByte_C - 10);									// 受发送缓冲区限制,减 10 个字节对应: 
																									//	帧头2 设备地址2 长度1 命令1 数据地址2 字节数1 .... 校验和1 
			}
			
			i = (gi_ucStartPtr-2)&(MaxRcvByte_C-1);			// 取发送方地址
			ga_ucTxdBuf[2] = ga_ucRcvBuf[i];						// 作为接收方地址发送
			ga_ucTxdBuf[4] = n + 4;											// 帧长
			ga_ucTxdBuf[5] = READ_MEMORY;								// 返回命令
			ga_ucTxdBuf[6] = uitemp.b[1];								// 将要读数据的地址和长度返回
			ga_ucTxdBuf[7] = uitemp.b[0];
			ga_ucTxdBuf[8] = n;
			sum = ga_ucTxdBuf[5]+ga_ucTxdBuf[6]+ga_ucTxdBuf[7]+ga_ucTxdBuf[8];

			i = 9;																			// 数据区起始指针
			
			if(uitemp.b[0] == 0x00)
			{
				// 如果高地址为 0 ,则读IDATA内容
				ucI_Ptr = uitemp.b[1];										
				for(j=0;j<n;j++)
				{
					ga_ucTxdBuf[i] = *ucI_Ptr;
					sum += ga_ucTxdBuf[i];
					i++;
					ucI_Ptr++;
				}
			}

			if(uitemp.b[0] == 0x01)											// 注:此段程序对2052无效,暂时保留
			{
				// 如果高地址为“0x01”,则读XDATA内容
				ucX_Ptr = uitemp.b[1];										// 因为只有256字节的XDATA,所以只取低字节。
				for(j=0;j<n;j++)
				{
					ga_ucTxdBuf[i] = *ucX_Ptr;
					sum += ga_ucTxdBuf[i];
					i++;
					ucX_Ptr++;
				}
			}

			// 读 SFR 暂不支持,读者可以思考一下如何添加? 
			
			if(uitemp.b[0] >= 0x80)
			{
				// 如果高地址大于“0x80”,则读code(程序区)内容
				ucC_Ptr = uitemp.all - 0x8000;								
				for(j=0;j<n;j++)
				{
					ga_ucTxdBuf[i] = *ucC_Ptr;		// 注意,此功能将使你的程序泄密 :P
					sum += ga_ucTxdBuf[i];
					i++;
					ucC_Ptr++;
				}
			}
			
			ga_ucTxdBuf[i] = ~sum;						// 校验和
				
			gc_ucTxdCnt = i+1;								// 发送字节计数
			gi_ucTxdPtr = 0;									// 发送指针
			SBUF = ga_ucTxdBuf[0];						// 启动发送
			
			break;
		}
		
		case WRITE_MEMORY:
		{
			// 写内存数据处理
			i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);		
			uitemp.b[1] = ga_ucRcvBuf[i];								// 取读数据地址
			i =(i+1)&(MaxRcvByte_C-1);
			uitemp.b[0] = ga_ucRcvBuf[i];
			i =(i+1)&(MaxRcvByte_C-1);
			n = ga_ucRcvBuf[i];													// 取读数据长度
			i =(i+1)&(MaxRcvByte_C-1);									// 数据区起始指针
			
			j = 0;																			// 返回实际写的字节数
			
			if(uitemp.b[0] == 0x00)
			{
				// 如果高地址为 0 ,则写IDATA内容
				ucI_Ptr = uitemp.b[1];										
				for(j=0;j<n;j++)
				{
					*ucI_Ptr = ga_ucRcvBuf[i];							// 注意,此功能会导致程序崩溃 :(
					i = (i+1)&(MaxRcvByte_C-1);						
					ucI_Ptr++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -