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

📄 motor_side.c

📁 汽车侧滑台检测仪表.用的单片机是PIC16F877A. 产品经过市场检验
💻 C
字号:
/**************************************************************************************************
*
* 说明:	在按键中有DEMA_KEY,C_Z_KEY 是高有效
*       CH_KEY按键是低有效
**************************************************************************************************/
#include <pic.h>				//包含系统头文件
#include "motor_side.h"			//包含项目头文件

#define true	1				//真
#define false	0				//假

 bank1 short dema_value[3];			//标定数据
unsigned char command = 0; 			//接收到的命令		
unsigned char send_data[7] = {'*',0x02,0x03,0x04,0x05};	//要送的数据
const unsigned char ASCII[12] = {'0','1','2','3','4','5','6','7','8','9','-','+'};		//ASCII字模

/***************************************************************************************************
* 延时
***************************************************************************************************/
void delay(unsigned short i,unsigned short j)		//根据不同的参数,实现不同时段的延时
{
	unsigned short k;

	for(; i > 0; i--){
		k = j;
		for(; k > 0; k--){
			asm("nop");
			asm("nop");
			asm("nop");
			asm("nop");
		}
	}
}

/**************************************************************************************************
* 函数名称: 	void SendDataToComputer(*Ptr,Number)
* 功能: 		向上位机发送数据
* 入口参数: 	*Ptr 指向要发送数据的指针	Number 要发送的数据个数
* 出口参数: 	无	
* 全局变量: 	无	
* 调用模块: 	无
* 设计者: 	饶阳胜
* 日期: 		05-2-28
**************************************************************************************************/
void SendComputer(unsigned char*Ptr,unsigned char Number)
{
	unsigned char i;					//要发送的数据个数
	
	for (i = 0; i < Number; i++){
		while(TRMT == 0);				//等待发送器为空
		TXREG = *Ptr++;					//将要发送的数据装载到发数寄存器中
	}
}

/*********************************************************************************************
* 函数名称: 	unsigned short adc_read(unsigned char channel)
* 功能: 		对某一通道进行AD转换
* 入口参数: 	channel	  转换的通道号
* 出口参数: 	result	  1次AD转换的结果	
* 全局变量: 	无
* 调用模块: 	adc_delay
* 设计者: 	饶阳胜
* 日期: 		05-3-1
*********************************************************************************************/
unsigned short adc_read(unsigned char channel)
{
	unsigned short result = 0;

	ADCON0 = (channel << 3) + 0x81;		//使能AD,32倍外部转换时钟
	delay(1,5);							//延时,等待采样完成
	ADIF = 0;
	ADGO = 1;							//开始转换	
	while(ADIF == 0)
		continue;						// 等待转换完成
	result = (ADRESH << 8) + ADRESL;
	return(result);
}

/**********************************************************************************************
* 函数名称: 	unsigned short ad_average(unsigned char channel)
* 功能: 		求AD转换平均值
* 入口参数: 	channel     	通道号
* 出口参数: 	result	  		转换后的平均值
* 全局变量: 	无
* 调用模块: 	adc_read
* 设计者: 	饶阳胜
* 日期: 		05-3-1
**********************************************************************************************/
unsigned short ad_adverage(unsigned char channel)
{
	unsigned long Summation = 0;					//和变量
	unsigned short i;								//次数变量

	for(i = 0; i < 4096; i++){
		Summation += adc_read(channel);				//调用AD转换函数
	}
	return (unsigned short)(Summation >> 12);
}

/***********************************************************************************************
* File: key_release.c
* 功能: 等待按键松开
* 说明: 按键有以下几个: DEMA_KEY	标定按键
*					 C_Z_KEY	清0按键
*					 CH_KEY		校验按键		
***********************************************************************************************/
void key_release()
{
	while(1){
		while(1){								//等待按键松开
			if(DEMA_KEY == 0 && C_Z_KEY == 0 && CH_KEY == 1) break;
		}
		delay(8,250);
		if(DEMA_KEY == 0 && C_Z_KEY  == 0 && CH_KEY == 1) break;
	}
}

/***********************************************************************************************
* File: dema.c
* 功能: 标定
***********************************************************************************************/
void side_dema()
{
	unsigned char i,value_of_ad;
	unsigned short dema_point[3] = {0xbbb0,0xbba5,0xbbb5};				//3个标定点
    unsigned short change_result;										//当前AD转换值	
	unsigned long x1,x2;

	for(i = 0; i < 3; i++){
		key_release();
		point = 0;
		display(dema_point[i]);											//显示标定点,0、-5、5
		delay(900,500);													//延时2秒钟
		while(1){			
			change_result = ad_adverage(1);								//调用AD转换,取得当前AD值
			x1 = 0x1388;
			x2 = 0x3ff;
			change_result = x1 * change_result / x2;
			change_result = change_result / 1000 << 12 | ((change_result % 1000) / 100 << 8) | \
						((change_result) % 100 / 10 << 4) | (change_result % 10);
			point = 0;			
			display(change_result);
			if(DEMA_KEY == 1){
				delay(8,250);
				if(DEMA_KEY == 1){
					break;
				}
			}
		}
		dema_value[i] = ad_adverage(1);								//读取当前AD值到标定寄存器中
		key_release();
	}	
	for(i = 0; i < 3; i++){											//将数据写入EEPROM中
		value_of_ad = (dema_value[i] >> 8) & 0xff;	//取得高位AD值
		eeprom_write(i * 2,value_of_ad);			//写入EEPROM
		delay(8,250);								//调延时
		value_of_ad = dema_value[i] & 0xff;			//取得低位AD值
		eeprom_write(i * 2 + 1, value_of_ad);
		delay(8,250);
	}
	point = 1;
	display(0xbb00);
}

/***************************************************************************************************
* File: clear_zer0()
* 功能: 校正0点
***************************************************************************************************/
void clear_zer0()
{
	short change_result;							//
	unsigned char i,value_of_ad;					//

	key_release();									//等待按键松开
	change_result = ad_adverage(1);					//取得当前AD值
	change_result -= dema_value[0];					//取得当前AD值与标定0点之间的差值
	for(i = 0; i < 3; i++){							//调整各个标定点
		dema_value[i] += change_result;
	}
	for(i = 0; i < 3; i++){							//将数据写入EEPROM中
		value_of_ad = (dema_value[i] >> 8) & 0xff;	//取得高位AD值
		eeprom_write(i * 2,value_of_ad);			//写入EEPROM
		delay(8,250);								//调延时
		value_of_ad = dema_value[i] & 0xff;			//取得低位AD值
		eeprom_write(i * 2 + 1, value_of_ad);
		delay(8,250);
	}
	point = 0;
	display(0x1111);								//显示“1111”表示清0操作成功
	delay(1000,500);	
	point = 1;
	display(0xbb00);
}

/***************************************************************************************************
* File: count_side(unsiged short change_result)
* 功能: 计算轮偏值
***************************************************************************************************/
unsigned short count_side(unsigned short change_result)
{
	unsigned short sideslip;

	if(change_result >= dema_value[0]){
		sideslip = 0x1f4 * (unsigned long)(change_result - dema_value[0]) / (dema_value[2] - dema_value[0]);
		sideslip = sideslip / 1000 << 12 | ((sideslip % 1000) / 100 << 8) | \
						((sideslip) % 100 / 10 << 4) | (sideslip % 10);
		sideslip = sideslip >> 4;
		sideslip &= 0x0fff;
		sideslip |= 0xb000;
		return sideslip;
	}else{					
		sideslip = 0x1f4 * (unsigned long)(dema_value[0] - change_result) / (dema_value[0] - dema_value[1]);
		sideslip = sideslip / 1000 << 12 | ((sideslip % 1000) / 100 << 8) | \
					((sideslip) % 100 / 10 << 4) | (sideslip % 10);		
		sideslip = sideslip >> 4;
		sideslip &= 0x0fff;
		sideslip |= 0xa000;
		return sideslip;
	}
} 


/***************************************************************************************************
* File: check.c
* 功能: 校验
***************************************************************************************************/
void check()
{
	unsigned short i;

	key_release();									//等待按键松开
	while(1){
		i = count_side(ad_adverage(1));				// 得到轮偏值
		/*
			将实时轮偏值发送给上位机
		*/
		send_data[0] = '*';	
		send_data[1] = ASCII[i >> 12 & 0x0f];
		send_data[2] = ASCII[i >> 8 & 0x0f];
		send_data[3] = ASCII[i >> 4 & 0x0f];
		send_data[4] = '.';
		send_data[5] = ASCII[i & 0x0f];
		send_data[6] = ' ';
		SendComputer(send_data,7);
		point = 1;
		display(i);									//显示当前轮偏量				

		if(!CH_KEY){								//如果校验键按下
			delay(8,250);							//延时
			if(!CH_KEY){							//确认校验键按下
				key_release();						//等待按键盘松开
				break;								//结束校验
			}
		}
	}
	point = 1;
	display(0xbb00);
}		

/***************************************************************************************************
* File: Tmr1init.c
* 功能: 初始化TMR1, 溢出时间为0.5秒
***************************************************************************************************/
void tmr1init(){
	T1CON = 0x30;			//设定TMR1溢出时间为0.5秒
	TMR1H = 0x78;
	TMR1L = 0xff;
	TMR1IF = 0;
	TMR1ON = 1;	
}

/***************************************************************************************************
* File: measure.c
* 功能: 检测轮偏
***************************************************************************************************/
unsigned char measure()
{
	unsigned char i ;
	unsigned short temp_sideslip;		//当前轮偏
	unsigned short max_negative;		//最大负值轮偏
	unsigned short max_positive;		//最大正值轮偏
	unsigned short max_sideslip;		//最大轮偏值

	send_data[0] = 'A';					//向上位机发送:Arrive => 车辆到位信号
	send_data[1] = 'r';					
	send_data[2] = 'r';
	send_data[3] = 'i';
	send_data[4] = 'v';
	send_data[5] = 'e';
	send_data[6] = ' ';
	SendComputer(send_data,7);
	tmr1init();
	for(i = 0; i < 6;){				//设定2秒延时,在两秒钟内,如果到位信号无效,则退出
		if(ARRIVE == false){
			return 0;
		}
		if(TMR1IF == 1){
			tmr1init();
			i++;
		}
	}

	send_data[0] = 'S';					//向上位机发送: Start => 开始检测信号
	send_data[1] = 't';
	send_data[2] = 'a';
	send_data[3] = 'r';
	send_data[4] = 't';
	send_data[5] = ' ';
	SendComputer(send_data,6);
	CLOSE_2 = 1;					//夹后轴		
	delay(800,250);					//延时1秒
	CLOSE_1 = 1;					//夹前轴
	
	delay(1600,250);				// 延时2秒
	max_sideslip = 0;				//最大轮偏初始化
	max_negative = 0;
	max_positive = 0;
	tmr1init();	
	for(i = 0; i < 4;){			//设定秒检测时间,检测时间已改短,i值从10改为现在的4.
		temp_sideslip = count_side(ad_adverage(1));
		if((temp_sideslip >> 12) == 0x0b){			//判断当前轮偏是正还是负
			if(temp_sideslip >= max_positive){		//如果当前轮偏大于最大轮偏(以前),则更新最大轮偏
				max_positive = temp_sideslip;
			}
		}else{										//当前轮偏是负
			if(temp_sideslip >= max_negative){		//如果当前轮偏大于最大轮偏(以前),更新最大轮偏
				max_negative = temp_sideslip;
			}
		}
		point = 1;
		display(temp_sideslip);						//显示当前轮偏
		if(TMR1IF == 1){							//检测时间参数
			tmr1init();
			i++;
		}
	}
	CLOSE_1 = 0;									//前后夹紧器松开
	CLOSE_2 = 0;
	if((max_negative & 0x0fff) > (max_positive & 0x0fff)){		//判断最大轮偏是正还是负
		max_sideslip = max_negative;
	}else{
		max_sideslip = max_positive;
	}

	send_data[0] = '*';									//发送最轮偏
	send_data[1] = ASCII[max_sideslip >> 12 & 0x0f];
	send_data[2] = ASCII[max_sideslip >> 8 & 0x0f];
	send_data[3] = ASCII[max_sideslip >> 4 & 0x0f];
	send_data[4] = '.';
	send_data[5] = ASCII[max_sideslip & 0x0f];
	send_data[6] = ' ';
	SendComputer(send_data,7);
	point = 1;
	display(max_sideslip);								//显示最大轮偏

	while(1){											//等前轮出台
		if(!ARRIVE){
			delay(8,250);
			if(!ARRIVE){
				break;
			}
		}
	}
	send_data[0] = 'O';						//向上位机发送: Wrong => 出错信号
	send_data[1] = 'v';
	send_data[2] = 'e';
	send_data[3] = 'r';
	send_data[4] = ' ';
	SendComputer(send_data,5);
    for(i = 0; i < 9; i++)
     {
      delay(800,250);					//延时1秒   
     }
	point = 1;
    display(0xbb00);
	return true;
}

/***************************************************************************************************
* File: interrupt.c
* 功能: 中断函数
***************************************************************************************************/
void interrupt rc_int(void)
{
	if(RCIF){				//如果有接收数据
		command = RCREG;			//将数据送到command中
	}
	RCIF = false;					//清接收中断标志
}
 
/***************************************************************************************************
* File: motor_side.C
* 功能: 系统主程序
***************************************************************************************************/
main()
{
	int i, j;

	SystemIni();
//	display(0xbb00);
	dema_value[0] = 0;
	dema_value[1] = 0;
	dema_value[2] = 0;
	for(i = 0; i < 3; i++){
		dema_value[i] = eeprom_read(i * 2) << 8;
		dema_value[i] |= eeprom_read((i * 2) + 1);
	}
	delay(400,250);				// 延时2秒
	point = 1;
	display(0xbb00);
	display(0xbb00);	

	while(1){
		if(ARRIVE == true)
			measure();
		if(CH_KEY == false)
			check();
		if(DEMA_KEY == true)
			side_dema();
		if(C_Z_KEY == true)
			clear_zer0();
	}
}

⌨️ 快捷键说明

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