📄 motor_side.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 + -