资料大家看吧!截图截得不全。
单片机源程序如下:
- /***************************************************/
- /* 寻迹小车 FollowMe 项目 */
- /* —— 主控程序轨迹控制模块 */
- /* 之程序部分 */
- /* 20060905 */
- /* By DingQi */
- /***************************************************/
- // 注:以下文档的 TAB 为 2 个字符!
- /*------------------------------------------------------------------------
- 此程序为"寻迹小车FollowMe"项目中单板控制模式的走轨迹控制部分,附带相关调试功能。
- 要实现:
- 1)接收各种调试命令,并解析;
- 2)通过串口反馈所需的调试信息;
- 3)获取轨迹采样部分处理后的信息,产生对策,发给电机驱动部分实施。
-
- 根据上述要实现的功能,通讯部分归此模块管理。
-
- 第一步先将原来的电机驱动功能整合到一个MCU中,将原来的通讯功能从电机驱动模块中分解出来。
-
- 目前的电机控制由串口实现,通讯协议定义如下:
- 1、帧格式:
- 帧头(2字节) 帧长(1字节) 命令字(1字节) 数据区(N字节)校验和(1字节)
- 其中:
- 帧头 —— 0x55 0xAA
- 帧长 —— 命令字 + 数据区的长度
- 命令字 —— 0x01 :电机转动控制参数,开环模式,电机的PWM值、转动持续脉冲数;
- 0x02 :电机转动控制参数,闭环模式,电机的转速、转动持续脉冲数;
- 0x03 :电机工作参数,PWM频率、PID参数
- 数据区 —— 命令01:电机1数据(2字节PWM值,2字节转动持续脉冲数)电机2数据(2字节PWM值,2字节转动持续脉冲数),共 8字节;
- 命令02:电机1数据(2字节转速值,2字节转动持续脉冲数)电机2数据(2字节转速值,2字节转动持续脉冲数),共 8字节;
- 命令03:2字节PWM频率,2字节比例系数,2字节积分系数,2字节微分系数,2字节PID系数的分母, 共10字节,两个电机驱动器相同;
- 校验和 —— 从命令字开始到数据区结束所有字节的算术和的反码,取低字节。
- 上述数据中,PWM值,速度值、PWM频率、PID系数等定义如下:
- PWM值 —— 2字节有符号数,正对应正转,负对应反转,数值为占空比的百分数,
- 取值范围:- 1000 —— +1000, 对应 0.1% ~ 100%;1001为电机“惰行”,1002为“刹车”;
-
- 转动持续脉冲数 —— 2字节无符号数,0 表示连续转动;
-
- 转速值 —— 2字节有符号数,正对应正转,负对应反转,单位为:0.1转/每分钟;
- 取值范围:- 10000~ +10000,10001为电机“惰行”,10002为“刹车”;
-
- PWM频率 —— 2字节整数,单位Hz,取值范围:200 – 2000;
-
- PID系数 —— 均为 2字节无符号数;
- PID系数分母 —— 2字节无符号数,为避免使用浮点数而增加了此参数,实际作用的PID系数为上述值除此值;
- 如:比例系数为190 ,PID分母为200,实际比例系数为0.95。
- 以上所有2字节的数据均为先低后高。
- 暂时不设计应答帧,因为一帧命令包含了两个电机的驱动数据。
- 通讯数据格式为:19200 8 N 1。
- 此时,一帧数据约占 7ms。
- 为了调试,添加转速读取命令 0x04 ,原来的读转速命令是分开实现的:
- 0x55 0xAA 0x02(帧长) 0x04 (读转速命令) 电机序号(1字节)校验和(1字节)
-
- 对应的返回帧为:
- 0xAA 0x55 0x04(帧长) 0x84 (转速值返回) 电机序号(1字节)转速(2字节)校验和(1字节)
-
- 因为合并到一个MCU中了,所以对应将协议改为:
- 0x55 0xAA 0x01(帧长) 0x04 (读转速命令) 校验和(1字节)
-
- 对应的返回帧为:
- 0xAA 0x55 0x05(帧长) 0x84 (转速值返回) 电机1转速(2字节)电机2转速(2字节)校验和(1字节)
- 因为集成了走轨迹控制功能,所以要添加一个控制命令,使小车启动,进入到走轨迹状态或结束走轨迹的状态。
- 走轨迹控制命令: 0x05 . 命令参数 —— 1 启动走轨迹, 2 —— 启动走直线 ,0 停止,
- 命令帧为:
- 0x55 0xAA 0x02 0x05 0x01 CS —— 启动走轨迹命令
- 0x55 0xAA 0x02 0x05 0x02 CS —— 启动直线走命令
- 0x55 0xAA 0x02 0x05 0x00 CS —— 停止命令
- 为了调试方便,增加一个内存数据读取命令:
- 内存数据读取命令:0x06
- 命令帧为:
- 0x55 0xAA 0x04 0x06 读数据低地址 读数据高地址 读数据长度 CS
- 返回帧为:
- 0x55 0xAA 帧长 0x86 读数据低地址 读数据高地址 读数据长度 数据N字节 CS
- ------------------------------------------------------------------------
- 因为用双轮驱动的小车由于电机等驱动元素的差异,导致走直线成为问题,故在此尝试
- 用这两个简易的码盘来实现直线行走。
- 因为码盘的分辨率太低,所以直接用脉冲计数方式控制似乎有些不够精确,所以考虑用
- 两路脉冲的触发时间差别来控制。
- 实质上这是一种周期测量的变换,因为不能保证每个脉冲周期是真实的(即由于干扰会
- 导致某个周期变大或变小),所以用累计的方式消除之。
- 具体的方式如下:
- 设立两个 4 字节的计数器,2字节纪录PCA的溢出值,2字节纪录 PCA 的计时器值,这样
- 构成了一个对PCA计数脉冲(Fosc/2)的长整形计数器,可纪录约 388秒(2^32/11.0592M),
- 这个值一般可以应付大部分比赛项目中的需要。
- 将这个时间计数器作为两个轮子采样脉冲(只取下降沿)的时标,根据两者的差值确定两轮
- 的驱动差。也就是要保证两个轮子对应脉冲到达的时间相同,这样,如果没有漏计或打滑,两
- 个轮子行走的距离应当是一样的,轨迹也应当是直线!
- 这个控制也可以考虑使用PID控制,其控制的量为两个计数器的差值,定值为“0”。
-
- ------------------------------------------------------------------------*/
- #pragma PR
- #pragma OT(5,size)
- #pragma Listinclude
- #pragma code
- #include <E:\dingqi\keilc51\inc\math.h>
- #include <STC12C5410AD.h> /* STC12C5410AD 的头文件*/
- #include <Port_Def.H>
- #include <ComConst.H>
- #include <LC_Const.H>
- #include <LC_Var.H>
- void init_SIO(unsigned char baud); // 初始化串口
- void rcvdata_proc(void); // 接收数据帧
- void getCommandData(void); // 从数据帧中取出命令数据
- unsigned int calStopCntValue(unsigned int uiRun_Num,unsigned char No); // 根据命令中的行走脉冲数计算出停止点
- char setMotorStat(int iRunValue); // 根据命令中的PWM值或转速设置电机状态
- void followLineControl(void); // 走轨迹控制
- void straightRun(void); // 走直线控制
- /******************************** 外部调用函数 *********************************/
- // 以下函数为公共函数,需要在调用的模块中声明。
- /********************************************/
- /* 名称:init_LineCtrl_Hardware */
- /* 用途:初始化串口等, 以保证相应硬件工作 */
- /********************************************/
- void init_LineCtrl_Hardware(void)
- {
- //初始化串口
- init_SIO(B_19200);
-
- // 初始化相关中断
- IE = IE|EnUART_C; // 允许 UART 中断
- }
- /********************************************/
- /* 名称:init_LineCtrl_Var */
- /* 用途:初始化自身工作变量 */
- /********************************************/
- void init_LineCtrl_Var(void)
- {
- unsigned char j;
-
- // 接收数据变量初始化
- gi_ucSavePtr=0;
- gi_ucGetPtr=0;
-
- gb_NewData = FALSE;
- gb_StartRcv = FALSE;
- gb_DataOK = FALSE;
-
- // 命令数据存放单元初始化
- for(j=0;j<2;j++)
- {
- ga_iPWM_Value[j] = FLOAT_PWM;
- ga_iRotateSpeed[j] = FLOAT_SPEED;
-
- ga_uiRotateNum[j] = 0;
- }
-
- g_uiPWM_Freq = INIT_PWM_FREQ; // 初始化时,将PWM的频率置为 200Hz
-
- gb_M1CalOutValue = TRUE; // 上电计算一次输出,以保证电机的正常工作状态
- gb_M2CalOutValue = TRUE; // 上电计算一次输出,以保证电机的正常工作状态
-
- // PID 控制初始化
- g_uiKp = DEFAULT_KP; // 加载默认系数
- g_uiTi = DEFAULT_TI;
- g_uiTd = DEFAULT_TD;
- g_uiPID_Ratio = DEFAULT_PID_RATIO;
-
- g_fKp = ((float)g_uiKp)/g_uiPID_Ratio; // 在此处计算好,减少每次 PID 的运算量
- g_fTi = ((float)g_uiTi)/g_uiPID_Ratio;
- g_fTd = ((float)g_uiTd)/g_uiPID_Ratio;
- gb_EnablePID = FALSE; // 禁止调速 PID 功能
-
- gb_StartLineFollow = FALSE;
- gb_StartStraightRun = FALSE;
- g_ucDownSampCnt = 0; // 初始化时将脉冲采样计数清为“0”
- }
- /********************************************/
- /* 名称:lineCtrl_proc */
- /* 用途:轨迹控制部分处理入口函数,根据带入 */
- /* 的消息作相应处理。 */
- /*入口参数:要处理的消息 */
- /********************************************/
- void lineCtrl_proc(unsigned char ucMessage)
- {
- switch(ucMessage)
- {
- case NEW_RCV_DATA:
- {
- rcvdata_proc(); // 处理接收缓冲区数据
- if(gb_DataOK)
- {
- gb_DataOK = FALSE;
- getCommandData(); // 从数据帧中提取命令数据
- }
- break;
- }
-
- case NEW_SAMP_DATA:
- {
- followLineControl();
- break;
- }
-
- case SAMPLE_DOWN_PULS:
- {
- straightRun();
- break;
- }
-
- default: break;
-
- }
- }
- /***************************** 模块自用函数 *******************************/
- // 以下函数只由模块自身使用,别的模块不用声明。
- /********************************************/
- /* 名称: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)
- }
- /********************************************/
- /*名称: rcvdata_proc */
- /*用途: 检测接收缓冲区数据, */
- /*说明: 如果收到正确的数据帧则建立标志 */
- /********************************************/
- void rcvdata_proc(void)
- {
- unsigned char i,j,k;
-
-
- if(gb_StartRcv == FALSE)
- {
- /* 检测帧头 0x55 0xAA LEN */
-
- i=(gi_ucGetPtr-2)&(MaxRcvByte_C-1); // 指向0x55
- j=(gi_ucGetPtr-1)&(MaxRcvByte_C-1); // 指向0xAA
-
- if((ga_ucRcvBuf[i]==0x55)&&(ga_ucRcvBuf[j]==0xAA))
- {
- i=gi_ucGetPtr;
-
- if(ga_ucRcvBuf[i]<= (MaxRcvByte_C-1));
- {
- //帧头正确,启动数据区接收
- gb_StartRcv=TRUE;
- gc_ucDataLen=ga_ucRcvBuf[i];
- gi_ucStartPtr=(gi_ucGetPtr+1)&(MaxRcvByte_C-1);
- gi_ucEndPtr= (gi_ucGetPtr + gc_ucDataLen+1)&(MaxRcvByte_C-1);
- }
- }
- gi_ucGetPtr=(gi_ucGetPtr+1)&(MaxRcvByte_C-1);
- }
- else
- {
- //开始接收数据处理
- if(gi_ucGetPtr==gi_ucEndPtr)
- {
- /* 数据帧接收完 */
- gb_StartRcv=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 +=ga_ucRcvBuf[j];
- if( k == 0xFF)
- {
- // 数据校验正确
- gb_DataOK=TRUE;
- }
- }
- gi_ucGetPtr=(gi_ucGetPtr+1)&(MaxRcvByte_C-1);
- }
- }
- /********************************************/
- /*名称: getCommandData */
- /*用途: 从接收缓冲区中取出数据, */
- /*说明: 建立对应标志,通知相应的处理 */
- /********************************************/
- void getCommandData(void)
- {
- union
- {
- unsigned int all;
- unsigned char b[2];
- }uitemp;
-
- union
- {
- int all;
- unsigned char b[2];
- }itemp;
-
- unsigned char ucCommand,i,j,sum,n;
- unsigned char idata *ucI_Ptr;
- unsigned char xdata *ucX_Ptr;
-
- ucCommand = ga_ucRcvBuf[gi_ucStartPtr]; // 取出数据帧中的命令字
-
- switch (ucCommand)
- {
- case PWM_MODE:
- {
- // 处理PWM开环控制命令
- i = (gi_ucStartPtr + 1)&(MaxRcvByte_C - 1); // 指向电机 1 数据区
-
- for(j=0;j<2;j++) // 循环 2 次完成两个电机的数据提取
- {
- itemp.b[1] = ga_ucRcvBuf[i]; // 注意,在C51中,整形等多字节数据在内存中是先高后低存放!
- i =(i+1)&(MaxRcvByte_C-1);
- itemp.b[0] = ga_ucRcvBuf[i];
-
- if(itemp.all < (-1000)) // PWM值合法性处理
- {
- itemp.all = -1000;
- }
- if(itemp.all > 1002)
- {
- itemp.all = 1000;
- }
- ga_iPWM_Value[j] = itemp.all; // 得到 PWM 值
- // 行走脉冲计数数据处理
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- ga_uiRotateNum[j] = uitemp.all; // 得到转动脉冲计数值
-
- ga_uiStopCnt[j] = calStopCntValue(ga_uiRotateNum[j],j); // 计算出停止计数值
-
- ga_cMotorStat[j] = setMotorStat(ga_iPWM_Value[j]); // 根据命令设置电机运转标志
-
- i = (gi_ucStartPtr + 1+4)&(MaxRcvByte_C - 1); // 指向电机 2 数据区
- }
-
- gb_EnablePID = FALSE; // 收到PWM控制命令后,禁止 PID 控制
-
- gb_M1CalOutValue =TRUE; // 建立计算电机控制输出值标志,因为PWM数据变化
- gb_M2CalOutValue =TRUE;
-
- break;
- }
-
- case SPEED_MODE:
- {
- // 处理转速闭环控制命令
- i = (gi_ucStartPtr + 1 )&(MaxRcvByte_C-1); // 指向电机 1 数据区
-
- for(j=0;j<2;j++) // 循环 2 次完成两个电机的数据提取
- {
- itemp.b[1] = ga_ucRcvBuf[i]; // 注意,在C51中,整形等多字节数据在内存中是先高后低存放!
- i =(i+1)&(MaxRcvByte_C-1);
- itemp.b[0] = ga_ucRcvBuf[i];
- if(itemp.all < (-10000)) // 转速数据合法性处理
- {
- itemp.all = -10000;
- }
- if(itemp.all > 10002)
- {
- itemp.all = 10000;
- }
- ga_iRotateSpeed[j] = itemp.all; // 得到转速
- // 行走脉冲数据处理
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- ga_uiRotateNum[j] = uitemp.all; // 得到转动脉冲计数值
-
- ga_uiStopCnt[j] = calStopCntValue(ga_uiRotateNum[j],j); // 计算出停止计数值
-
- ga_cMotorStat[j] = setMotorStat(ga_iRotateSpeed[j]); // 根据命令设置电机运转标志
-
- i = (gi_ucStartPtr + 1 + 4)&(MaxRcvByte_C-1); // 指向电机 2 数据区
- }
-
- if(gb_EnablePID)
- {
- // 已启动PID控制
- }
- else
- {
- // 启动 PID 控制
- gb_EnablePID = TRUE;
- gac_ucGetSpeedCnt[MOTOR1] = 3; // 电机 1 采集3次速度数据后才允许计算PID
- gac_ucGetSpeedCnt[MOTOR2] = 3; // 电机 2 采集3次速度数据后才允许计算PID
- ga_iPWM_Value[MOTOR1] = INI_PWM_VALUE; // 电机 1 输出PWM初值,启动电机
- ga_iPWM_Value[MOTOR2] = INI_PWM_VALUE; // 电机 2 输出PWM初值,启动电机
- gb_M1CalOutValue = TRUE; // 通知输出计算
- gb_M2CalOutValue = TRUE;
- }
-
- break;
- }
-
- case SET_PARA:
- {
- // 处理参数设置命令
- i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i]; // 注意,在C51中,整形等多字节数据在内存中是先高后低存放!
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- g_uiPWM_Freq = uitemp.all;
- if(g_uiPWM_Freq <200) // 数据合法性处理
- {
- g_uiPWM_Freq = 200;
- }
- if(g_uiPWM_Freq >2000)
- {
- g_uiPWM_Freq = 2000;
- }
- gb_M1CalOutValue =TRUE; // 建立计算电机控制输出值标志,因为PWM的频率变了。
- gb_M2CalOutValue =TRUE;
-
- // 取 PID 参数
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- g_uiKp = uitemp.all;
-
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- g_uiTi = uitemp.all;
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- g_uiTd = uitemp.all;
-
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[1] = ga_ucRcvBuf[i];
- i =(i+1)&(MaxRcvByte_C-1);
- uitemp.b[0] = ga_ucRcvBuf[i];
- if(uitemp.all >0)
- {
- g_uiPID_Ratio = uitemp.all;
- }
-
- g_fKp = ((float)g_uiKp)/g_uiPID_Ratio; // 在此处计算好,减少每次 PID 的运算量
- g_fTi = ((float)g_uiTi)/g_uiPID_Ratio;
- g_fTd = ((float)g_uiTd)/g_uiPID_Ratio;
-
- break;
- }
-
- case READ_SPEED:
- {
- // 读取转速命令处理
- ga_ucTxdBuf[0] = 0xAA;
- ga_ucTxdBuf[1] = 0x55; // 帧头
- ga_ucTxdBuf[2] = 0x05; // 帧长
- ga_ucTxdBuf[3] = 0x80+READ_SPEED; // 返回命令
- sum = ga_ucTxdBuf[3];
- i=4;
- for(j=0;j<2;j++) // 循环 2 次,返回 2 个电机的转速
- {
- itemp.all = ga_iCurSpeed[j];
- ga_ucTxdBuf[i] = itemp.b[1]; // 返回转速值,先低后高
- sum += ga_ucTxdBuf[i];
- i++;
- ga_ucTxdBuf[i] = itemp.b[0];
- sum += ga_ucTxdBuf[i];
- i++;
- }
-
- ga_ucTxdBuf[i] = ~sum; // 校验和
-
- gc_ucTxdCnt = 9; // 发送字节计数
- gi_ucTxdPtr = 0; // 发送指针
- SBUF = ga_ucTxdBuf[0]; // 启动发送
-
- break;
- }
-
- case FOLLOW_LINE_CTRL:
- {
- i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);
- switch (ga_ucRcvBuf[i])
- {
- case FOLLOW_LINE:
- {
- break;
- }
-
- case STRAIGHT_RUN:
- {
- gb_StartStraightRun = TRUE;
-
- gc_uiPCA_OverCnt = 0;
- g_ucDownSampCnt = 0;
-
- //gb_EnSpeed_Hi_Low = TRUE; // 启动速度上下限控制
-
- g_iInit_PWM = INI_PWM_VALUE; // 启动电机
- ga_iPWM_Value[MOTOR1] = g_iInit_PWM;
- ga_cMotorStat[MOTOR1] = setMotorStat(ga_iPWM_Value[MOTOR1]); // 设置电机运转标志
- ga_iPWM_Value[MOTOR2] = g_iInit_PWM;
- ga_cMotorStat[MOTOR2] = setMotorStat(ga_iPWM_Value[MOTOR2]); // 设置电机运转标志
-
- m_iDiffPWM = 0;
- gb_M1CalOutValue =TRUE; // 建立计算电机控制输出值标志,
- gb_M2CalOutValue =TRUE;
-
- m_iError_Int = 0; // 初始化PID计算数据
- m_iErrorOld = 0;
-
- break;
- }
-
- case STOP_RUN:
- {
- ga_iPWM_Value[MOTOR1] = BRAKE_PWM;
- ga_cMotorStat[MOTOR1] = setMotorStat(ga_iPWM_Value[MOTOR1]); // 设置电机运转标志
- ga_iPWM_Value[MOTOR2] = BRAKE_PWM;
- ga_cMotorStat[MOTOR2] = setMotorStat(ga_iPWM_Value[MOTOR2]); // 设置电机运转标志
- gb_EnSpeed_Hi_Low = FALSE;
- gb_StartStraightRun = FALSE;
- gb_StartLineFollow = FALSE;
- gb_M1CalOutValue =TRUE; // 建立计算电机控制输出值标志,
- gb_M2CalOutValue =TRUE;
- break;
- }
-
- default: break;
- }
-
- break;
- }
-
- case READ_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]; // 取读数据长度
- if(n>(MaxTxdByte_C - 4))
- {
- n = (MaxTxdByte_C - 4); // 受发送缓冲区限制,减 4 个字节对应: 命令 地址 长度
- }
-
- ga_ucTxdBuf[0] = 0xAA;
- ga_ucTxdBuf[1] = 0x55; // 帧头
- ga_ucTxdBuf[2] = n + 4; // 帧长
- ga_ucTxdBuf[3] = 0x80+READ_MEMORY; // 返回命令
- ga_ucTxdBuf[4] = uitemp.b[1]; // 将要读数据的地址和长度返回
- ga_ucTxdBuf[5] = uitemp.b[0];
- ga_ucTxdBuf[6] = n;
- sum = ga_ucTxdBuf[3]+ga_ucTxdBuf[4]+ga_ucTxdBuf[5]+ga_ucTxdBuf[6];
- i = 7; // 数据区起始指针
-
- if(uitemp.b[0] == 0)
- {
- ucI_Ptr = uitemp.b[1]; // 如果高地址为 0 ,则读IDATA内容
- for(j=0;j<n;j++)
- {
- ga_ucTxdBuf[i] = *ucI_Ptr;
- i++;
- ucI_Ptr++;
- }
- }
- else
- {
- ucX_Ptr = uitemp.b[1]; // 如果高地址不为“0”,则读XDATA内容,因为只有256字节的XDATA,所以只取低字节。
- for(j=0;j<n;j++)
- {
- ga_ucTxdBuf[i] = *ucX_Ptr;
- i++;
- ucX_Ptr++;
- }
- }
- ga_ucTxdBuf[i] = ~sum; // 校验和
-
- gc_ucTxdCnt = i+1; // 发送字节计数
- gi_ucTxdPtr = 0; // 发送指针
- SBUF = ga_ucTxdBuf[0]; // 启动发送
-
- break;
- }
-
- default:
- {
- break;
- }
- }
- }
- /********************************************/
- /*名称: calStopCntValue */
- /*用途: 根据得到的行走脉冲数计算出停止点 */
- /********************************************/
- unsigned int calStopCntValue(unsigned int uiRun_Num,unsigned char No)
- {
- unsigned int cnt1;
-
- if(uiRun_Num !=0)
- {
- cnt1 = gac_uiPulsCnt[No];
- while(cnt1 != gac_uiPulsCnt[No])
- {
- cnt1 = gac_uiPulsCnt[No]; // 防护处理,避免正好在PCA中断时取数
- }
-
- cnt1 = cnt1 + uiRun_Num; // 得到停止的判断点
- }
- else
- {
- cnt1 = 65535; // g_uiRotateNum =0;设置为最大值,永不停止
- }
- return(cnt1);
- }
- /*********************************************/
- /*名称: setMotorStat */
- /*用途: 根据命令中的PWM值或转速值设置电机状态*/
- /*********************************************/
- char setMotorStat(int iRunValue)
- {
- char stat;
-
- switch (iRunValue)
- {
- case 0:
- {
- stat = IN_STOP;
- break;
- }
-
- case FLOAT_PWM:
- {
- stat = IN_STOP;
- break;
- }
-
- case BRAKE_PWM:
- {
- stat = IN_STOP;
- break;
- }
-
- case FLOAT_SPEED:
- {
- stat = IN_STOP;
- break;
- }
-
- case BRAKE_SPEED:
- {
- stat = IN_STOP;
- break;
- }
-
- default:
- {
- if(iRunValue >0)
- {
- stat = IN_FORWARD;
- }
- else
- {
- stat = IN_BACKWARD;
- }
- break;
- }
- }
- return(stat);
- }
- /*********************************************/
- /*名称: followLineControl */
- /*用途: 根据采样输出值g_cSampleOut 控制寻迹 */
- /*********************************************/
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
循迹小车详细资料包括电路图、软件编程.rar
(238.93 KB, 下载次数: 150)
|