set /?

显示、设置或删除 cmd.exe 环境变量。

SET [variable=[string]]

  variable  指定环境变量名。
  string    指定要指派给变量的一系列字符串。

要显示当前环境变量,键入不带参数的 SET。

如果命令扩展名被启用,SET 会如下改变:

可仅用一个变量激活 SET 命令,等号或值不显示所有前缀匹配
SET 命令已使用的名称的所有变量的值。例如:

    SET P

会显示所有以字母 P 打头的变量

如果在当前环境中找不到该变量名称,SET 命令将把 ERRORLEVEL
设置成 1。

SET 命令不允许变量名含有等号。

在 SET 命令中添加了两个新命令行开关:

    SET /A expression
    SET /P variable=[promptString]

/A 命令行开关指定等号右边的字符串为被评估的数字表达式。该表达式
评估器很简单并以递减的优先权顺序支持下列操作:

    ()                  - 分组
    ! ~ -               - 一元运算符
    * / %               - 算数运算符
    + -                 - 算数运算符
    << >>               - 逻辑移位
                       - 按位“与”
    ^                   - 按位“异”
    |                   - 按位“或”
    = *= /= %= += -=    - 赋值
      &= ^= |= <<= >>=
    ,                   - 表达式分隔符

如果您使用任何逻辑或取余操作符, 您需要将表达式字符串用
引号扩起来。在表达式中的任何非数字字符串键作为环境变量
名称,这些环境变量名称的值已在使用前转换成数字。如果指定
了一个环境变量名称,但未在当前环境中定义,那么值将被定为
零。这使您可以使用环境变量值做计算而不用键入那些 % 符号
来得到它们的值。如果 SET /A 在命令脚本外的命令行执行的,
那么它显示该表达式的最后值。该分配的操作符在分配的操作符
左边需要一个环境变量名称。除十六进制有 0x 前缀, 八进制
有 0 前缀的,数字值为十进位数字。因此, 0x12 与 18 和 022
相同。请注意八进制公式可能很容易搞混: 08 和 09 是无效的数字,
因为 8 和 9 不是有效的八进制位数。

/P 命令行开关允许将变量数值设成用户输入的一行输入。读取输入
行之前,显示指定的 promptString。promptString 可以是空的。

环境变量替换已如下增强:

    %PATH:str1=str2%

会扩展 PATH 环境变量,用 "str2" 代替扩展结果中的每个 "str1"。
要有效地从扩展结果中删除所有的 "str1","str2" 可以是空的。
"str1" 可以以星号打头;在这种情况下,"str1" 会从扩展结果的
开始到 str1 剩余部分第一次出现的地方,都一直保持相配。

也可以为扩展名指定子字符串。

    %PATH:~10,5%

会扩展 PATH 环境变量,然后只使用在扩展结果中从第 11 个(偏
移量 10)字符开始的五个字符。如果没有指定长度,则采用默认
值,即变量数值的余数。如果两个数字(偏移量和长度)都是负数,
使用的数字则是环境变量数值长度加上指定的偏移量或长度。

    %PATH:~-10%

会提取 PATH 变量的最后十个字符。

    %PATH:~0,-2%

会提取 PATH 变量的所有字符,除了最后两个。

终于添加了延迟环境变量扩充的支持。该支持总是按默认值被
停用,但也可以通过 CMD.EXE 的 /V 命令行开关而被启用/停用。
请参阅 CMD /?

考虑到读取一行文本时所遇到的目前扩充的限制时,延迟环境
变量扩充是很有用的,而不是执行的时候。以下例子说明直接
变量扩充的问题:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "%VAR%" == "after" @echo If you see this, it worked
    )

不会显示消息,因为在读到第一个 IF 语句时,BOTH IF 语句中
的 %VAR% 会被代替;原因是: 它包含 IF 的文体,IF 是一个
复合语句。所以,复合语句中的 IF 实际上是在比较 "before" 和
"after",这两者永远不会相等。同样,以下这个例子也不会达到
预期效果:

    set LIST=
    for %i in (*) do set LIST=%LIST% %i
    echo %LIST%

原因是,它不会在目前的目录中建立一个文件列表,而只是将
LIST 变量设成找到的最后一个文件。这也是因为 %LIST% 在
FOR 语句被读取时,只被扩充了一次;而且,那时的 LIST 变量
是空的。因此,我们真正执行的 FOR 循环是:

    for %i in (*) do set LIST= %i

这个循环继续将 LIST 设成找到的最后一个文件。

延迟环境变量扩充允许您使用一个不同的字符(惊叹号)在执行
时间扩充环境变量。如果延迟的变量扩充被启用,可以将上面
例子写成以下所示,以达到预期效果:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "!VAR!" == "after" @echo If you see this, it worked
    )

    set LIST=
    for %i in (*) do set LIST=!LIST! %i
    echo %LIST%

如果命令扩展名被启用,有几个动态环境变量可以被扩展,但
不会出现在 SET 显示的变量列表中。每次变量数值被扩展时,
这些变量数值都会被动态计算。如果用户用这些名称中任何
一个定义变量,那个定义会替代下面描述的动态定义:

%CD% - 扩展到当前目录字符串。

%DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。

%TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。

%RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。

%ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。

%CMDEXTVERSION% - 扩展到当前命令处理器扩展名版本号。

%CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。

 

 

#include <reg52.h> // ????? sbit LEFT_SENSOR = P1^1; // ???? sbit MID_LEFT_SENSOR = P1^0; // ????? sbit MID_RIGHT_SENSOR = P1^2;// ????? sbit RIGHT_SENSOR = P1^3; // ???? // ?????? sbit ENA = P2^3; // ???PWM sbit IN1 = P2^5; // ?????1 sbit IN2 = P2^4; // ?????2 sbit ENB = P2^1; // ???PWM sbit IN3 = P2^0; // ?????1 sbit IN4 = P2^2; // ?????2 // ???? #define FORWARD 1 #define BACKWARD 2 #define STOP 0 // ???? #define TURN_NONE 0 // ?? #define TURN_SLIGHT_LEFT 1 // ???? #define TURN_LEFT 2 // ?? #define TURN_SHARP_LEFT 3 // ??? #define TURN_SLIGHT_RIGHT 4 // ???? #define TURN_RIGHT 5 // ?? #define TURN_SHARP_RIGHT 6 // ??? // ???? #define MODE_AUTO 0 // ?????? #define MODE_MANUAL 1 // ?????? // ????(0-100??) - ??????? #define MAX_SPEED 12 // ??????(?25) #define CRUISE_SPEED 10 // ????(??)(?20) #define TURN_SPEED 8 // ????(??)(?15) #define MIN_SPEED 3 // ??????(?5) #define PWM_FREQ 200 // PWM??(Hz) // ???? unsigned char current_mode = MODE_AUTO; unsigned char left_target_speed = 0; unsigned char right_target_speed = 0; unsigned char left_current_dir = STOP; unsigned char right_current_dir = STOP; unsigned int pwm_period; // PWM???? // ?????? unsigned char min(unsigned char a, unsigned char b) { return (a < b) ? a : b; } // ???? void delay_ms(unsigned int ms) { unsigned int i, j; for(i = 0; i < ms; i++) for(j = 0; j < 123; j++); } // ????? void motor_init() { // ??????????? ENA = 0; ENB = 0; IN1 = 0; IN2 = 0; IN3 = 0; IN4 = 0; // ??PWM?? pwm_period = (11059200 / 12) / PWM_FREQ; // ???0???(16???) TMOD |= 0x01; TH0 = (65536 - pwm_period) >> 8; TL0 = (65536 - pwm_period) & 0xFF; ET0 = 1; EA = 1; TR0 = 1; } // PWM????? void timer0_isr() interrupt 1 { static unsigned char pwm_counter = 0; static unsigned char left_current_speed = 0; static unsigned char right_current_speed = 0; // ??????? TH0 = (65536 - pwm_period) >> 8; TL0 = (65536 - pwm_period) & 0xFF; pwm_counter++; if(pwm_counter >= 100) pwm_counter = 0; // ??????(????1???) if(left_current_speed < left_target_speed) { left_current_speed += 1; } else if(left_current_speed > left_target_speed) { left_current_speed -= 1; } if(right_current_speed < right_target_speed) { right_current_speed += 1; } else if(right_current_speed > right_target_speed) { right_current_speed -= 1; } // ??PWM?? ENA = (left_current_dir != STOP && pwm_counter < left_current_speed) ? 1 : 0; ENB = (right_current_dir != STOP && pwm_counter < right_current_speed) ? 1 : 0; } // ???? void limit_speed(unsigned char *speed) { if(*speed > MAX_SPEED) *speed = MAX_SPEED; if(*speed < MIN_SPEED && *speed != 0) *speed = MIN_SPEED; } // ?????? void set_motors(unsigned char left_dir, unsigned char right_dir, unsigned char left_speed, unsigned char right_speed) { // ??????(???85%, ???90%) left_speed = (left_speed * 100) / 100; right_speed = (right_speed * 70) / 100; // ?????? limit_speed(&left_speed); limit_speed(&right_speed); // ?????? left_current_dir = left_dir; right_current_dir = right_dir; // ??????? if(left_dir == FORWARD) { IN1 = 1; IN2 = 0; } else if(left_dir == BACKWARD) { IN1 = 0; IN2 = 1; } else { IN1 = 0; IN2 = 0; } // ??????? if(right_dir == FORWARD) { IN3 = 1; IN4 = 0; } else if(right_dir == BACKWARD) { IN3 = 0; IN4 = 1; } else { IN3 = 0; IN4 = 0; } // ?????? left_target_speed = left_speed; right_target_speed = right_speed; } // ???????? void set_motors_with_turn(unsigned char dir, unsigned char speed, unsigned char turn_type) { unsigned char left_speed = speed, right_speed = speed; // ???????????(???30%) switch(turn_type) { case TURN_SLIGHT_LEFT: left_speed = speed*70/100; right_speed = speed*130/100; break; case TURN_LEFT: left_speed = speed*50/100; right_speed = speed*150/100; break; case TURN_SHARP_LEFT: left_speed = speed*40/100; right_speed = speed*160/100; break; case TURN_SLIGHT_RIGHT: left_speed = speed*130/100; right_speed = speed*70/100; break; case TURN_RIGHT: left_speed = speed*150/100; right_speed = speed*50/100; break; case TURN_SHARP_RIGHT: left_speed = speed*160/100; right_speed = speed*40/100; break; default: left_speed = speed; right_speed = speed; } // ????????? left_speed = min(left_speed, MAX_SPEED); right_speed = min(right_speed, MAX_SPEED); set_motors(dir, dir, left_speed, right_speed); } // ??????? unsigned char get_sensor_status() { unsigned char status = 0; if(LEFT_SENSOR == 0) status |= 0x01; if(MID_LEFT_SENSOR == 0) status |= 0x02; if(MID_RIGHT_SENSOR == 0) status |= 0x04; if(RIGHT_SENSOR == 0) status |= 0x08; return status; } // ???? void emergency_stop() { set_motors(STOP, STOP, 0, 0); delay_ms(500); } // ???? void search_line() { unsigned char i; // ???????? for(i = 0; i < 3; i++) { set_motors_with_turn(BACKWARD, 10, TURN_SHARP_LEFT); // ???20??10 delay_ms(200); set_motors_with_turn(BACKWARD, 10, TURN_SHARP_RIGHT); // ???20??10 delay_ms(200); if(get_sensor_status() != 0x00) return; } emergency_stop(); } // ?????? - ?????? void track_line() { unsigned char sensor = get_sensor_status(); // ????????????? switch(sensor) { case 0x06: // 0110 - ?? set_motors_with_turn(FORWARD, CRUISE_SPEED, TURN_NONE); break; case 0x02: // 0010 case 0x07: // 0111 case 0x01: // 0001 case 0x03: // 0011 set_motors_with_turn(FORWARD, TURN_SPEED, TURN_LEFT); break; case 0x04: // 0100 case 0x0E: // 1110 case 0x08: // 1000 case 0x0C: // 1100 set_motors_with_turn(FORWARD, TURN_SPEED, TURN_RIGHT); break; case 0x00: // 0000 search_line(); break; case 0x0F: // 1111 case 0x09: // 1001 set_motors(FORWARD, FORWARD, CRUISE_SPEED, CRUISE_SPEED); delay_ms(300); break; case 0x0B: // 1011 case 0x0D: // 1101 emergency_stop(); break; default: set_motors_with_turn(FORWARD, CRUISE_SPEED, TURN_NONE); } } // ?????? void set_mode(unsigned char mode) { current_mode = mode; if(mode == MODE_MANUAL) { set_motors(STOP, STOP, 0, 0); } } // ??? - ??????????? void main() { // ????????,?????? delay_ms(500); motor_init(); // ?????? - ??????? set_motors(FORWARD, FORWARD, 12, 12); // ?25??12 delay_ms(300); set_motors(BACKWARD, BACKWARD, 12, 12); // ?25??12 delay_ms(300); set_motors(STOP, STOP, 0, 0); delay_ms(500); // ???????? set_mode(MODE_AUTO); // ??? - ?????? while(1) { if(current_mode == MODE_AUTO) { // ????????P0????? P0 = (left_target_speed << 4) | right_target_speed; track_line(); } delay_ms(30); // ???????33Hz } }
最新发布
07-20
### 8051单片机实现自动寻迹机器人 #### 传感器输入处理 在自动寻迹机器人中,通常使用红外传感器或光电传感器来检测路径上的黑线。传感器阵列通常由多个传感器组成,以提高检测精度。传感器信号通过比较器(如LM339)进行处理,将模拟信号转换为数字信号输入到8051单片机的I/O口[^1]。 传感器的检测结果可以通过轮询或中断方式进行读取。例如,使用P1口连接传感器阵列,每个传感器对应一个I/O引脚。根据传感器输出的高低电平判断黑线位置,并将信息传递给控制逻辑。 ```c unsigned char read_sensors() { return P1; // 假设传感器连接到P1口 } ``` #### 控制逻辑与路径判断 控制逻辑基于传感器数据决定机器人的转向。例如,若中间传感器检测到黑线而两侧未检测到,则机器人保持直行;若左侧传感器检测到黑线,则机器人向左转;反之则向右转。 ```c void control_logic(unsigned char sensor_data) { if (sensor_data == 0x04) { // 假设0x04表示中间传感器检测到黑线 move_forward(); } else if (sensor_data & 0x03) { // 假设0x03表示左侧传感器检测到黑线 turn_left(); } else if (sensor_data & 0x18) { // 假设0x18表示右侧传感器检测到黑线 turn_right(); } else { stop_robot(); // 如果所有传感器都未检测到黑线,则停止 } } ``` #### PWM调速 8051单片机没有内置的PWM模块,但可以通过定时器/计数器实现软件PWM。通常使用定时器0或定时器1生成PWM信号,控制电机的速度。 ```c #include <mcs51/8051.h> #define PWM_PERIOD 100 // PWM周期 unsigned char pwm_duty = 50; // 初始占空比50% void timer0_isr(void) __interrupt(1) { static unsigned char count = 0; TH0 = 0xFF; // 重载高字节 TL0 = 0xA0; // 重载低字节(假设系统时钟为12MHz) if (count < pwm_duty) { P2_0 = 1; // 高电平 } else { P2_0 = 0; // 低电平 } count++; if (count >= PWM_PERIOD) { count = 0; } } void init_pwm() { TMOD = 0x02; // 定时器0模式2(8位自动重载) TH0 = 0xFF; // 初始值 TL0 = 0xA0; ET0 = 1; // 使能定时器0中断 EA = 1; // 使能全局中断 TR0 = 1; // 启动定时器0 } ``` #### 自动/手动模式切换 自动/手动模式切换可以通过一个外部开关或按钮实现。例如,使用P3.2引脚连接一个按钮,当按下按钮时切换模式。在自动模式下,机器人根据传感器数据自动寻迹;在手动模式下,机器人由用户通过遥控器或其他输入设备控制。 ```c bit auto_mode = 1; // 初始为自动模式 void check_mode_switch() { if (P3_2 == 0) { // 假设P3.2连接按钮 auto_mode = !auto_mode; while (P3_2 == 0); // 等待按钮释放 } } ``` #### 主程序逻辑 主程序循环中不断读取传感器数据、检查模式切换状态,并根据当前模式执行相应的控制逻辑。 ```c void main() { init_pwm(); // 初始化PWM while (1) { check_mode_switch(); if (auto_mode) { unsigned char sensor_data = read_sensors(); control_logic(sensor_data); } else { // 手动模式下的控制逻辑,例如通过串口或遥控器输入 } } } ``` #### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值