&& 与 || 或 !非

 逻辑运算符
&&   ||   !
&&(逻辑与):
全真则真,一假则假。
||(逻辑或):
一真则真,全假则假。
!(逻辑非)
非真则假,非假则真。
截断法则:
逻辑与运算:如果前面的表达式为假,则后面的表达式不执行
逻辑或运算:如果前面的表达式为真,则后面的表达式不执行

位运算符
&  |  ~   ^  <<   >>
&(位与):
全1则1,有0则0

|(位或)
有1则1,全0则0

~(按位取反,通过补码进行取反)
正数的补码是它本身
负数的补码=原码取反码+1
负数原码=补码取反码+1
反码:除符号位,按位取反

^(异或)
不同为1,相同为0

<<(左移)
左移几位右边补几个0

x左移n位,结果=x*2^n

>>右移
右移几位,左边补几个符号位
正数:右移左边补0
负数:右移左边补1

x右移n位,结果:x/2^n

置位问题:
将某个数清零或置一
将n位置一:a|(1<<n)(n从0开始)
将n位清零:a&(~(1<<n))

三目运算符
表达式1?表达式2:表达式3
运算法则:如果表达式1成立,执行表达式2,否则执行表达式3

#include &quot;stm32f10x.h&quot; #include &quot;bsp_usart.h&quot; #include &quot;bsp_adc.h&quot; #include &quot;moto.h&quot; #include &quot;bsp_GeneralTim.h&quot; #include &lt;string.h&gt; #include &quot;stm32f10x_tim.h&quot; #include &quot;stm32f10x_rcc.h&quot; // ==================== 硬件配置 ==================== // ADC1转换的电压值通过DMA方式传到SRAM extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL]; // 用于保存转换计算后的电压值 float ADC_ConvertedValueLocal[NOFCHANEL]; // 电机驱动配置 - 根据MDA12E13-755规格定义脉冲宽度 #define PULSE_STOP 1500 // 停止脉冲宽度 (us) #define PULSE_FORWARD 1550 // 正转脉冲宽度 (us) #define PULSE_REVERSE 1450 // 反转脉冲宽度 (us) #define PULSE_LEFT_ADJ 1520 // 左转微调脉冲宽度 (us) #define PULSE_RIGHT_ADJ 1480 // 右转微调脉冲宽度 (us) // 电机脉冲周期控制 (必须 &ge; 20ms) #define MOTOR_CYCLE_DELAY 18 // 脉冲周期延时 (ms) // 传感器配置 #define SENSOR_THRESHOLD 1.5f // QTI900灰度传感器阈值 // 超声波传感器配置 #define ULTRASONIC_TRIG_PORT GPIOB #define ULTRASONIC_TRIG_PIN GPIO_Pin_12 #define ULTRASONIC_ECHO_PORT GPIOB #define ULTRASONIC_ECHO_PIN GPIO_Pin_13 #define TRIG_H GPIO_SetBits(ULTRASONIC_TRIG_PORT, ULTRASONIC_TRIG_PIN) #define TRIG_L GPIO_ResetBits(ULTRASONIC_TRIG_PORT, ULTRASONIC_TRIG_PIN) #define ECHO_READ GPIO_ReadInputDataBit(ULTRASONIC_ECHO_PORT, ULTRASONIC_ECHO_PIN) // ==================== 传感器状态定义 ==================== // 传感器状态宏定义 - CH1失效,跳过CH1的判断 #define S0 (ADC_ConvertedValueLocal[0] &gt; SENSOR_THRESHOLD) // #define S1 (ADC_ConvertedValueLocal[1] &gt; SENSOR_THRESHOLD) // CH1失效 #define S2 (ADC_ConvertedValueLocal[2] &gt; SENSOR_THRESHOLD) #define S3 (ADC_ConvertedValueLocal[3] &gt; SENSOR_THRESHOLD) #define S4 (ADC_ConvertedValueLocal[4] &gt; SENSOR_THRESHOLD) #define S5 (ADC_ConvertedValueLocal[5] &gt; SENSOR_THRESHOLD) #define S6 (ADC_ConvertedValueLocal[6] &gt; SENSOR_THRESHOLD) #define S7 (ADC_ConvertedValueLocal[7] &gt; SENSOR_THRESHOLD) // CH1失效后的替代判断 #define LEFT_SIDE (S0 || S2) // 左侧有传感器检测到 #define LEFT_STRONG (S0 &amp;&amp; S2) // 左侧强信号 // 障碍物状态枚举 typedef enum { OBSTACLE_NONE = 0, // 无障碍物 OBSTACLE_CRITICAL, // 紧急障碍物 (&lt;10cm) OBSTACLE_CLOSE, // 近距离障碍物 (10-20cm) OBSTACLE_FAR // 远距离障碍物 (20-30cm) } Obstacle_Status; // ==================== 延时函数 ==================== void delaynms(uint32_t ms); void delay_us(int i) { i = i * 2; while(i--); } void delay1ms() { unsigned char i, j; for(i = 0; i &lt; 10; i++) for(j = 0; j &lt; 33; j++); } void delaynms(unsigned int n) { unsigned int i; for(i = 0; i &lt; n; i++) delay1ms(); } // ==================== 基础电机控制函数 ==================== // 发送单个电机脉冲 void Send_Motor_Pulse(uint16_t moto1_pulse, uint16_t moto2_pulse, uint16_t moto3_pulse, uint16_t moto4_pulse) { MOTO1(ON); delay_us(moto1_pulse); MOTO1(OFF); MOTO2(ON); delay_us(moto2_pulse); MOTO2(OFF); MOTO3(ON); delay_us(moto3_pulse); MOTO3(OFF); MOTO4(ON); delay_us(moto4_pulse); MOTO4(OFF); // 确保脉冲周期 &ge; 20ms delaynms(MOTOR_CYCLE_DELAY); } // ==================== 运动控制函数 ==================== // 直行 void GO_moto(void) { Send_Motor_Pulse(PULSE_FORWARD, PULSE_REVERSE, PULSE_FORWARD, PULSE_REVERSE); } // 直行指定距离 void GO_moto_distance(int duration) { for(int i = 0; i &lt; duration; i++) { GO_moto(); } } // 停止 void Stop_moto(void) { Send_Motor_Pulse(PULSE_STOP, PULSE_STOP, PULSE_STOP, PULSE_STOP); } // 左转 void Left_moto(void) { // 左转前进准备 GO_moto_distance(50); // 执行左转 for(int i = 0; i &lt; 125; i++) { Send_Motor_Pulse(PULSE_FORWARD, PULSE_FORWARD, PULSE_FORWARD, PULSE_FORWARD); } // 左转后前进 printf(&quot;左转完成,继续前进\r\n&quot;); GO_moto_distance(80); } // 右转 void Right_moto(void) { // 右转前进准备 GO_moto_distance(50); // 执行右转 for(int i = 0; i &lt; 125; i++) { Send_Motor_Pulse(PULSE_REVERSE, PULSE_REVERSE, PULSE_REVERSE, PULSE_REVER } // 右转后前进 printf(&quot;右转完成,继续前进\r\n&quot;); GO_moto_distance(80); } // 掉头 void Back_moto(void) { for(int i = 0; i &lt; 250; i++) { Send_Motor_Pulse(PULSE_REVERSE, PULSE_REVERSE, PULSE_REVERSE, PULSE_REVERSE); } printf(&quot;掉头完成,继续前进\r\n&quot;); GO_moto_distance(100); } // ==================== 循迹功能 ==================== // 偏移检测修正 - 适配CH1失效 void Adjust_Offset(void) { // 轻微左偏修正 - 右侧传感器检测到黑线 if ((!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 只有S4检测到 (!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; S4 &amp;&amp; S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S4,S5检测到 (!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7)) // S3,S4检测到 { printf(&quot;检测到轻微左偏,向右微调\r\n&quot;); for(int i = 0; i &lt; 5; i++) { Send_Motor_Pulse(PULSE_RIGHT_ADJ, PULSE_RIGHT_ADJ, PULSE_RIGHT_ADJ, PULSE_RIGHT_ADJ); } } // 轻微右偏修正 - 左侧传感器检测到黑线 else if ((!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 只有S3检测到 (S0 &amp;&amp; S2 &amp;&amp; S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S0,S2,S3检测到 (S0 &amp;&amp; S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7)) // S0,S2检测到 { printf(&quot;检测到轻微右偏,向左微调\r\n&quot;); for(int i = 0; i &lt; 5; i++) { Send_Motor_Pulse(PULSE_LEFT_ADJ, PULSE_LEFT_ADJ, PULSE_LEFT_ADJ, PULSE_LEFT_ADJ); } } } // 带自动修正的直行函数 void GO_moto_with_adjust(void) { GO_moto(); Adjust_Offset(); } // ==================== 超声波避障功能 ==================== // 超声波传感器初始化 void Ultrasonic_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置TRIG引脚为推挽输出 GPIO_InitStructure.GPIO_Pin = ULTRASONIC_TRIG_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(ULTRASONIC_TRIG_PORT, &amp;GPIO_InitStructure); // 配置ECHO引脚为上拉输入 GPIO_InitStructure.GPIO_Pin = ULTRASO GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(ULTRASONIC_ECHO_PORT, &amp;GPIO_InitStructure); TRIG_L; // 初始化为低电平 } // 超声波测距函数(返回厘米数) uint16_t Ultrasonic_GetDistance(void) { uint32_t time_start, time_end; uint32_t timeout = 0; float distance_cm; // 发送触发脉冲 TRIG_H; delay_us(15); TRIG_L; // 等待ECHO变为高电平(开始计时) timeout = 0; while(ECHO_READ == 0) { timeout++; if(timeout &gt; 10000) return 0; // 超时 delay_us(1); } time_start = SysTick-&gt;VAL; // 等待ECHO变为低电平(结束计时) timeout = 0; while(ECHO_READ == 1) { timeout++; if(timeout &gt; 60000) return 0; // 超时 delay_us(1); } time_end = SysTick-&gt;VAL; // 计算高电平持续时间 uint32_t pulse_width; if(time_end &lt; time_start) { pulse_width = time_start - time_end; } else { pulse_width = time_end - time_start; } // 计算距离(声速340m/s = 0.034cm/us) distance_cm = (pulse_width * 0.034f) / 2; return (uint16_t)distance_cm; } // 检测障碍物状态 Obstacle_Status Check_Obstacle(void) { uint16_t distance = Ultrasonic_GetDistance(); if(distance == 0) { printf(&quot;超声波传感器错误\r\n&quot;); return OBSTACLE_NONE; } printf(&quot;前方距离: %d cm\r\n&quot;, distance); if(distance &lt; 10) { return OBSTACLE_CRITICAL; } else if(distance &lt; 20) { return OBSTACLE_CLOSE; } else if(distance &lt; 30) { return OBSTACLE_FAR; } else { return OBSTACLE_NONE; } } // 避障策略 void Avoid_Obstacle(Obstacle_Status obstacle_status) { switch(obstacle_status) { case OBSTACLE_CRITICAL: printf(&quot;紧急停止!距离 &lt; 10cm\r\n&quot;); Stop_moto(); delaynms(500); Back_moto(); // 后退 Right_moto(); // 右转避开 break; case OBSTACLE_CLOSE: printf(&quot;障碍物接近,减速准备转向 (10-20cm)\r\n&quot;); // 降低速度 TIM1_CCR1_Val = 100; TIM1_CCR4_Val = 100; GENERAL_TIM_Init(); break; case OBSTACLE_FAR: printf(&quot;前方有障碍物,轻微调整 (20-30cm)\r\n&quot;); // 轻微向左调整避开 for(int i = 0; i &lt; 5; i++) { Send_Motor_Pulse(PULSE_LEFT_ADJ, PULSE_LEFT_ADJ,PULSE_LEFT_ADJ, PULSE_LEFT_ADJ); } break; case OBSTACLE_NONE: default: // 安全距离,正常行驶 break; } } // ==================== 传感器数据处理 ==================== // 计算8路灰度采样值 void QTI_8_DATAS_GET(void) { // 3.3V参考电压,&times;2是因为可能的分压电路 for(int i = 0; i &lt; 8; i++) { ADC_ConvertedValueLocal[i] = (float)ADC_ConvertedValue[i] / 4096 * 3.3 * 2; } } // ==================== 循迹决策逻辑 ==================== void Follow_Line(void) { // 情况1: 直行条件 - 两侧传感器检测到,中间没有(跳过CH1) if((S0 &amp;&amp; S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; S5 &amp;&amp; S6 &amp;&amp; S7) || // 标准直行 (S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; S6 &amp;&amp; S7) || // 轻微偏左但仍直行 (S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; S5 &amp;&amp; S6 &amp;&amp; S7) || // 轻微偏右但仍直行 (S0 &amp;&amp; S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; S6 &amp;&amp; S7) || // 轻微偏右但仍直行 // 新增条件:中间四个传感器有三个及以上无信号时直行 (S0 &amp;&amp; S2 &amp;&amp; ((!S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; S6) || // 只有S6有信号 (!S3 &amp;&amp; !S4 &amp;&amp; S5 &amp;&amp; !S6) || // 只有S5有信号 (!S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6) || // 只有S4有信号 (S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6) || // 只有S3有信号 (!S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6)) &amp;&amp; // 全部无信号 S7) || // 右侧S7必须有信号 (S0 &amp;&amp; S2 &amp;&amp; ((!S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; S6) || (!S3 &amp;&amp; !S4 &amp;&amp; S5 &amp;&amp; !S6) || (!S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6) || (S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6) || (!S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6)) &amp;&amp; S5 &amp;&amp; S6 &amp;&amp; S7)) { printf(&quot;执行直走命令\r\n&quot;); GO_moto_with_adjust(); } // 情况2: 右转条件 - 只有左侧传感器检测到黑线 else if((LEFT_SIDE &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 左侧有信号,右侧无 (LEFT_STRONG &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 左侧有信号,右侧无 (LEFT_STRONG &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7)) // 左侧强信号 { printf(&quot;执行右转命令\r\n&quot;); Right_moto(); } // 情况3: 左转条件 - 只有右侧传感器检测到黑线 else if((!LEFT_SIDE &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; S6 &amp;&amp; S7) || // 右侧有信号,左侧无 (!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; S5 &amp;&amp; S6 &amp;&amp; S7)) // 右侧信号 { printf(&quot;执行左转命令\r\n&quot;); Left_moto(); } // 情况4: 停止条件 - 中间传感器检测到黑线 else if((!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 只有S3检测到 (!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S3,S4检测到 (!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; S4 &amp;&amp; S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 中间三个检测到 (!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7)) // 所有传感器都没检测到 { printf(&quot;执行停止命令\r\n&quot;); Stop_moto(); } // 情况5: 偏移修正 - 轻微偏移情况 else if((!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 只有S4检测到 (!S0 &amp;&amp; !S2 &amp;&amp; !S3 &amp;&amp; S4 &amp;&amp; S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S4,S5检测到 (!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S3,S4检测到 (!S0 &amp;&amp; !S2 &amp;&amp; S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // 只有S3检测到 (S0 &amp;&amp; S2 &amp;&amp; S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7) || // S0,S2,S3检测到 (S0 &amp;&amp; S2 &amp;&amp; !S3 &amp;&amp; !S4 &amp;&amp; !S5 &amp;&amp; !S6 &amp;&amp; !S7)) // S0,S2检测到 { printf(&quot;检测到偏移,执行修正\r\n&quot;); Adjust_Offset(); GO_moto_distance(10); } // 默认情况: 安全停止 else { printf(&quot;未知状态,执行安全停止\r\n&quot;); Stop_moto(); } } // ==================== 主函数 ==================== int main(void) { // 系统初始化 SystemInit(); // 外部8MHz时钟 // 电机驱动初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); MOTO_GPIO_Config(); // 外设初始化 USART1_Config(); // 串口115200 ADCx_Init(); // ADC初始化 GENERAL_TIM_Init(); // 定时器初始化 Ultrasonic_Init(); // 超声波传感器初始化 delaynms(100); // 系统稳定延时 printf(&quot;=== 智能循迹避障小车系统启动 ===\r\n&quot;); printf(&quot;系统就绪...\r\n&quot;); // 避障检测计时器 uint32_t last_obstacle_check = 0; GO_moto_distance(100); { while (1) { // 读取传感器数据 QTI_8_DATAS_GET(); // 调试信息输出 printf(&quot;\r\n=== 传感器数据 (CH1失效) ===\r\n&quot;); for(int i = 0; i &lt; 8; i++) { if(i == 1) { printf(&quot;CH%d = %.2f V (失效) &quot;, i, ADC_ConvertedValueLocal[i]); } else { printf(&quot;CH%d = %.2f V &quot;, i, ADC_ConvertedValueLocal[i]); } if((i+1) % 4 == 0) printf(&quot;\r\n&quot;); } // 避障检测(每100ms检测一次) if(SysTick-&gt;VAL - last_obstacle_check &gt; 100) { Obstacle_Status obstacle = Check_Obstacle(); if(obstacle != OBSTACLE_NONE) { // 优先处理障碍物 Avoid_Obstacle(obstacle); } else { // 无障碍物时正常循迹 Follow_Line(); } last_obstacle_check = SysTick-&gt;VAL; } else { // 避障检测周期,正常循迹 Follow_Line(); } // 主循环延时 delaynms(50); } } } 添加OpenMV通信相关代码: 定义OpenMV通信的数据帧格式(参考引用[1][3][5]) 添加串口接收中断处理,解析数据包 添加接收缓冲区、状态机等 添加颜色搬运逻辑: 根据解析出的颜色(红、蓝、绿)控制小车移动到目标位置 控制机械臂进行抓取(假设已有机械臂控制函数) 将木块搬运到指定地点 考虑到代码的完整性,我们做如下设计: OpenMV通信协议(参考引用[3][5]): 帧头1(0xAA) + 帧头2(0xBB) + 颜色(1字节) + X坐标(4字节,小端) + Y坐标(4字节,小端) + 校验和(2字节,可选) 在STM32端,我们将: 初始化串口(假设使用USART1,OpenMV连接) 在串口中断中接收数据,使用状态机解析 解析成功后,将颜色和坐标保存到全局变量 在主循环中根据这些数据控制小车和机械臂 把python和c部分分别整理好全局发给我
10-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值