[zt]一些检测调试器的方法

IsDebuggerPresent

.386
      .model flat, stdcall
      option casemap :none   ; case sensitive

      include /masm32/include/windows.inc
      include /masm32/include/user32.inc
      include /masm32/include/kernel32.inc

      includelib /masm32/lib/user32.lib
      includelib /masm32/lib/kernel32.lib

    .data
       DbgNotFoundTitle db "Debugger status:",0h
       DbgFoundTitle db "Debugger status:",0h
       DbgNotFoundText db "Debugger not found!",0h
       DbgFoundText db "Debugger found!",0h
    .code

start:

; MASM32 antiRing3Debugger example
; coded by ap0x
; Reversing Labs: http://ap0x.headcoders.net

; This example can detect all ring3 debuggers by accessing PEB!BeingDebuged.
; You can see this code in kernel32.dll!IsDebuggerPresent function.

ASSUME FS:NOTHING
MOV EAX,DWORD PTR FS:[18h]
MOV EAX,DWORD PTR DS:[EAX+30h]
MOVZX EAX,BYTE PTR DS:[EAX+2h]

CMP EAX,1
JE @DebuggerDetected

PUSH 40h
PUSH offset DbgNotFoundTitle
PUSH offset DbgNotFoundText
PUSH 0
CALL MessageBox

JMP @exit
  @DebuggerDetected:

PUSH 30h
PUSH offset DbgFoundTitle
PUSH offset DbgFoundText
PUSH 0
CALL MessageBox

  @exit:

PUSH 0
CALL ExitProcess

end start






/* * Copyright (c) 2021, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ti_msp_dl_config.h" #include "main.h" #include "stdio.h" #include "board.h" #include "bsp_gyro.h" #include "motor.h" #include "Uart.h" #include "No_Mcu_Ganv_Grayscale_Sensor_Config.h" #include "bsp_sr04.h" #include "math.h" // 用于fabs()函数 #include <stdlib.h> #define ZX_SUDU 50 extern volatile Encoder Encoder_A; extern volatile Encoder Encoder_B; extern short V_A,V_B; extern float distance ; extern uint8_t SR04_Flag ; unsigned short Anolog[8]={0}; unsigned short white[8]={3034,2157,3303,3278,3040,3243,3239,2340};//原1524,3247,3081,3236,3205,3102,2682,2927,现3139-3219-3104-3177-3184-3109-2832-2997.........再3085-3140-3067-3128-3096-3068-2984-2999.........3034-2157-3303-3278-3040-3243-3239-2340 unsigned short black[8]={497,136,762,577,337,711,500,278};//920-923-408-1184-785-349-111-323....原761,995,508,1102,675,502,244,323.....纯黑:666-806-238-542-356-208-138-185//1938-1365-738-1230-914-766-451-797//497-136-762-577-337-711-500-278 unsigned short Normal[8]; unsigned short d[8],w=0,c=0,c1=0,zt=0,zt1=0,zt2=0,zt3=0; short j=0; short b[4]; float weight[4]={0.4,0.3,0.2,0.1}; float a[8], max_abs; unsigned char rx_buff[256]={0}; /********************************************No_Mcu_Demo*******************************************/ /*****************芯片型号 MSPM0G3507 主频32Mhz ***************************************************/ /*****************引脚 AD0:PB17 AD1:PB18 AD2:PB19 ***************************************************/ /*****************OUT PA27*************************************************************************/ /********************************************No_Mcu_Demo*******************************************/ int16_t rxbuf = 0,rxbuf1=0,crxbuf=0, crxbuf1=0,cx0=0,cx = 0,cx1=0,cx2=0,cx3=0,dl=0,dr=0; int16_t baseSpeed = ZX_SUDU; int16_t SpeedL = 0, SpeedR = 0; float KP = 0.5; uint8_t oled_buffer[32]; int aim; int V1,V2; int V_L; int V_R; int output=0,output1,output2; char PWM_Value0[10],PWM_Value1[10],PWM_Value2[10],PWM_Value3[10],PWM_Value4[10],PWM_Value5[10],PWM_Value6[10]; float SetVoltage0; //定义设定值 int js=0; //初始化 No_MCU_Sensor sensor; unsigned char Digtal; //串口0发送单个字符 void uartxc_send_char(char ch); //串口0发送字符串 void uartxc_send_string(char* str); void Motor_Ctrl(void); //OLED显示各项参数 void SyncParamsToOLED(void); //获取传感器数值并处理 void SampleSensorData(void); //等待读取病房号 void AwaitWardID(void); //判断是否需要自选停车点 void CheckAutoParkingNeed(void); //正常循迹 void FollowLine(void); //遇弯道强制直行 void DisableCurveTurning(void); //启程遇弯道转弯并记住路线,到病房开始掉头 void FollowPathCurves(void); //返程 void ExecuteReturn(void); //结束转弯恢复循迹 void ResumeLineFollowing(void); int main(void) { SYSCFG_DL_init(); // SysTick_Init(); //清除串口中断标志 NVIC_ClearPendingIRQ(UART_K230_INST_INT_IRQN); //使能串口中断 NVIC_EnableIRQ(UART_K230_INST_INT_IRQN); //清除串口中断标志 NVIC_ClearPendingIRQ(UART_XC2_INST_INT_IRQN); //使能串口中断 NVIC_EnableIRQ(UART_XC2_INST_INT_IRQN); NVIC_ClearPendingIRQ(TIMER_2_INST_INT_IRQN); NVIC_EnableIRQ(TIMER_2_INST_INT_IRQN); // NVIC_ClearPendingIRQ(GPIOB_INT_IRQn); // NVIC_EnableIRQ(GPIOB_INT_IRQn);//开启按键引脚的GPIOB端口中断 uint8_t t=' '; Motor_Init(); OLED_Init(); // SR04_Init(); // jy61pInit(); // // lc_printf("\r\nJY61P 3D Attitude Measurement Sensor Start...\r\n"); //......................................................................感为灰度模块初始化 //初始化传感器,不带黑白值 No_MCU_Ganv_Sensor_Init_Frist(&sensor); No_Mcu_Ganv_Sensor_Task_Without_tick(&sensor); Get_Anolog_Value(&sensor,Anolog); //此时打印的ADC的值,可用通过这个ADC作为黑白值的校准 //也可以自己写按键逻辑完成一键校准功能 sprintf((char *)rx_buff,"Anolog %d-%d-%d-%d-%d-%d-%d-%d\r\n",Anolog[0],Anolog[1],Anolog[2],Anolog[3],Anolog[4],Anolog[5],Anolog[6],Anolog[7]); uart0_send_string((char *)rx_buff); // uart0_send_string((char *)rx_buff); // delay_cycles(CPUCLK_FREQ/10); memset(rx_buff,0,256); //得到黑白校准值之后,初始化传感器 No_MCU_Ganv_Sensor_Init(&sensor,white,black); // delay_cycles(CPUCLK_FREQ/10); while (1) { // Motor_On(); // DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, 0, DL_TIMER_CC_0_INDEX); // DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, 0, DL_TIMER_CC_1_INDEX); // uartxc_send_string("!2@"); // delay_cycles(CPUCLK_FREQ); //OLED显示各项参数 SyncParamsToOLED(); //获取传感器数值并处理 SampleSensorData(); //等待读取病房号 AwaitWardID(); //判断是否需要自选停车点 CheckAutoParkingNeed(); //正常循迹 FollowLine(); //遇弯道强制直行 DisableCurveTurning(); //启程遇弯道转弯并记住路线,到病房开始掉头 FollowPathCurves(); //返程 ExecuteReturn(); //结束转弯恢复循迹 ResumeLineFollowing(); // //.......................................................................JY901模块 // Gyro_Struct *JY61P_Data = get_angle(); // lc_printf("\n"); // lc_printf("JY61P RollX = [ %d ]\r\n",(int)JY61P_Data->x); // lc_printf("JY61P PitchY = [ %d ]\r\n",(int)JY61P_Data->y); // lc_printf("JY61P YawZ = [ %d ]\r\n",(int)JY61P_Data->z); // delay_ms(100); // // ..........................................................................................灰度模拟量与模拟量归一化处理应用 // sprintf((char *)rx_buff,"Digtal %d-%d-%d-%d-%d-%d-%d-%d\r\n",d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); // //获取传感器模拟量结果(有黑白值初始化后返回1 没有返回 0) // if(Get_Anolog_Value(&sensor,Anolog)){ // sprintf((char *)rx_buff,"Anolog %d-%d-%d-%d-%d-%d-%d-%d\r\n",Anolog[0],Anolog[1],Anolog[2],Anolog[3],Anolog[4],Anolog[5],Anolog[6],Anolog[7]); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); // } // //获取传感器归一化结果(只有当有黑白值传入进去了之后才会有这个值!!有黑白值初始化后返回1 没有返回 0) // if(Get_Normalize_For_User(&sensor,Normal)){ // sprintf((char *)rx_buff,"Normalize %d-%d-%d-%d-%d-%d-%d-%d\r\n",Normal[0],Normal[1],Normal[2],Normal[3],Normal[4],Normal[5],Normal[6],Normal[7]); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); // } //经典版理论性能1khz,只需要delay1ms,青春版100hz,需要delay10ms,否则不能正常使用 // delay_cycles(CPUCLK_FREQ/10); // // //........................................................................................................SR04模块 // // uint32_t Value = (int)SR04_GetLength(); // // lc_printf("Distance = %dCM\r\n", Value); // // delay_ms(500); // ...................................................使用串口调试参数 // sprintf((char *)rx_buff,"cx2 %d\r\n",cx2); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); // sprintf((char *)rx_buff,"cx3 %d\r\n",cx3); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); } } void GROUP1_IRQHandler(void)//Group1的中断服务函数 { uint32_t gpio_interrup = 0; //读取Group1的中断寄存器并清除中断标志位 switch( DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1) ) { //检查GPIO端口中断,注意是INT_IIDX case DL_INTERRUPT_GROUP1_IIDX_GPIOB: //获取中断信号 gpio_interrup = DL_GPIO_getEnabledInterruptStatus(ENCODER_PORT,ENCODER_E1A_PIN|ENCODER_E1B_PIN|ENCODER_E2A_PIN|ENCODER_E2B_PIN); // encoderA if((gpio_interrup & ENCODER_E1A_PIN)==ENCODER_E1A_PIN) { if(!DL_GPIO_readPins(ENCODER_PORT,ENCODER_E1B_PIN)) { Encoder_A.Should_Get_Encoder_Count--; } else { Encoder_A.Should_Get_Encoder_Count++; } } else if((gpio_interrup & ENCODER_E1B_PIN)==ENCODER_E1B_PIN) { if(!DL_GPIO_readPins(ENCODER_PORT,ENCODER_E1A_PIN)) { Encoder_A.Should_Get_Encoder_Count++; } else { Encoder_A.Should_Get_Encoder_Count--; } } // encoderB if((gpio_interrup & ENCODER_E2A_PIN)==ENCODER_E2A_PIN) { if(!DL_GPIO_readPins(ENCODER_PORT,ENCODER_E2B_PIN)) { Encoder_B.Should_Get_Encoder_Count--; } else { Encoder_B.Should_Get_Encoder_Count++; } } else if((gpio_interrup & ENCODER_E2B_PIN)==ENCODER_E2B_PIN) { if(!DL_GPIO_readPins(ENCODER_PORT,ENCODER_E2A_PIN)) { Encoder_B.Should_Get_Encoder_Count++; } else { Encoder_B.Should_Get_Encoder_Count--; } } DL_GPIO_clearInterruptStatus(ENCODER_PORT,ENCODER_E1A_PIN|ENCODER_E1B_PIN|ENCODER_E2A_PIN|ENCODER_E2B_PIN); break; // //检查GPIO端口中断,注意是INT_IIDX // case SR04_INT_IIDX: // if( SR04_ECHO() ) // 上升沿 // { // SR04_Flag = 0; // distance = 0.0; // Open_Timer(); //打开定时器 // } // else // 下降沿 // { // NVIC_DisableIRQ(SR04_INT_IRQN); // 关闭按键引脚的GPIO端口中断 // Close_Timer(); // 关闭定时器 // SR04_Flag = 1; // distance = (float)Get_TIMER_Count() / 58.0f; // 获取时间,分辨率为1us // } // break; } } void TIMER_0_INST_IRQHandler(void) { //编码器速度计算 if( DL_TimerA_getPendingInterrupt(TIMER_0_INST) == DL_TIMER_IIDX_ZERO ) { // lc_printf("[ %d ] | [ %d ]\r\n",Motor_Get_Encoder(0),Motor_Get_Encoder(1)); // Gyro_Struct *JY61P_Data = get_angle(); GetMotorPulse(); if( DL_GPIO_readPins(KEY_PORT, KEY_PIN_21_PIN) ==0 ) { if(DL_GPIO_readPins(KEY_PORT, KEY_PIN_21_PIN) ==0) { if(zt1==2)zt1=0; } } if(zt1==1) { if(js>=150)zt1=0; } if(zt1==3) { if(js>=1900) { zt1=0; } } // if(zt1==2) // { // if(js>=1000) // { // zt1=0; // } // } if(((zt1==0)||(zt1==3))&&((cx>=1)&&(cx<=8))) { output1 = PID_A(baseSpeed+output); output2 = PID_B(baseSpeed-output); left( output1 ); right( output2 ); } // Motor_Off(); } } void TIMER_2_INST_IRQHandler() { if( DL_TimerA_getPendingInterrupt(TIMER_2_INST) == DL_TIMER_IIDX_ZERO ) { js++; } } void UART_K230_INST_IRQHandler(void) { uint8_t gData; switch (DL_UART_Main_getPendingInterrupt(UART_K230_INST)) { case DL_UART_MAIN_IIDX_RX: gData = DL_UART_Main_receiveData(UART_K230_INST); if(gData == '#') rxbuf = 0; else if(gData == '$') { cx = rxbuf; cx0=cx; } else rxbuf =(gData - '0'); if(gData == '&') rxbuf1 = 0; else if(gData == '*') { cx1 = rxbuf1; } else rxbuf1 =(gData - '0'); break; default: break; } } void UART_XC2_INST_IRQHandler(void) { uint8_t gData; switch (DL_UART_Main_getPendingInterrupt(UART_XC2_INST)) { case DL_UART_MAIN_IIDX_RX: gData = DL_UART_Main_receiveData(UART_XC2_INST); if(gData == '!') crxbuf = 0; else if(gData == '@') { cx2 = crxbuf; } else crxbuf =(gData - '0'); if(gData == '%') crxbuf1 = 0; else if(gData == '^') { cx3 = crxbuf1; } else crxbuf1 =(gData - '0'); break; default: break; } } //OLED显示各项参数 void SyncParamsToOLED(void) { sprintf(PWM_Value0,"CX:%d",cx); OLED_ShowString(0,0,(uint8_t *)PWM_Value0,8); sprintf(PWM_Value1,"ZT2:%d",zt2); OLED_ShowString(0,1,(uint8_t *)PWM_Value1,16); sprintf(PWM_Value2,"CX1:%d",cx1); OLED_ShowString(0,3,(uint8_t *)PWM_Value2,8); sprintf(PWM_Value3,"ZT1:%d",zt1); OLED_ShowString(0,4,(uint8_t *)PWM_Value3,8); sprintf(PWM_Value4,"C:%d",c); OLED_ShowString(0,5,(uint8_t *)PWM_Value4,8); sprintf(PWM_Value5,"zt:%d",zt); OLED_ShowString(0,6,(uint8_t *)PWM_Value5,8); sprintf(PWM_Value6,"C1:%d",c1); OLED_ShowString(0,7,(uint8_t *)PWM_Value6,8); } //zt:是否转弯,=3时左转,=4时右转,=0时巡线,=1时转头;zt1:=1时是否延迟转弯,=3是否转弯延时,=2时是否停车等待1秒钟;zt2:是否进入返程模式,=1为返程,=0为启程;zt3:去远端病房是否进入二次转弯;w:灰度是否全是识别到红色(转弯处),=1为是;c:灰度是否全识别到白色(药房),=0为是;c1:灰度检测到红色的数量;js:定时器计时代替延时函数使用的计时变量单位1ms。cx:送药前识别到需要去的病房号;cx1:送药中识别到的病房号;cx:需要去的病房;cx0:再次储存需要去的病房号;cx1:在路途中识别到的病房号;cx2:自选的停车点;cx3:从自选停车点到病房需要的操作指示:=1开始回头,遇线等待,且反转返程路线,=2退出等待且重置zt2为启程模式使其去到下一个病房。 //获取传感器数值并处理 void SampleSensorData(void) { //......................................................................感为灰度模块 //无时基传感器常规任务,包含模拟量,数字量,归一化量 No_Mcu_Ganv_Sensor_Task_Without_tick(&sensor); //获取传感器数字量结果(只有当有黑白值传入进去了之后才会有这个值!!) Digtal=Get_Digtal_For_User(&sensor); // sprintf((char *)rx_buff,"Digtal %d-%d-%d-%d-%d-%d-%d-%d\r\n",(Digtal>>0)&0x01,(Digtal>>1)&0x01,(Digtal>>2)&0x01,(Digtal>>3)&0x01,(Digtal>>4)&0x01,(Digtal>>5)&0x01,(Digtal>>6)&0x01,(Digtal>>7)&0x01); // uart0_send_string((char *)rx_buff); // memset(rx_buff,0,256); //处理数据 for(int i=0;i<8;i++) { d[i]=(Digtal>>i)&0x01; } w=d[0]&d[1]&d[2]&d[3]&d[4]&d[5]&d[6]&d[7]; c=d[0]|d[1]|d[2]|d[3]|d[4]|d[5]|d[6]|d[7]; c1=d[0]+d[1]+d[2]+d[3]+d[4]+d[5]+d[6]+d[7]; } //等待读取病房号 void AwaitWardID(void) { while(!((cx>=1)&&(cx<=8))) { Motor_Off(); } } //判断是否需要自选停车点 void CheckAutoParkingNeed(void) { if(cx2!=0) { cx=cx2; } } //正常循迹 void FollowLine(void) { if((zt==0)&&(zt1!=3)) { if(d[3])output=0; if(d[2])output=-15; if(d[1])output=-20; if(d[0])output=-35; if(d[4])output=0; if(d[5])output=15; if(d[6])output=20; if(d[7])output=35; } } //遇弯道强制直行 /** * @brief Disable curve turning (禁用弯道转向) * @note Maintains current heading (保持当前航向) */ void DisableCurveTurning(void) { if(zt2==0) { if((cx1==0)&&(cx!=1)&&(cx!=2)) { if(c1>=4) output=0; } } if(zt2==1) { if(j<=0) { if(!c) { zt1=2; // js=0; uartxc_send_string("%2^"); while(zt1==2) { Motor_Off(); } } if(c1>=4) { output=0; } } } } //启程遇弯道转弯并记住路线,到病房开始掉头 void FollowPathCurves(void) { if(zt2==0) { if(zt==0) { if(c1>=5) { if(cx==1) { zt1=1; js=0; output=-20; baseSpeed=0; zt=3; } if(cx==2) { zt1=1; js=0; output=20; baseSpeed=0; zt=4; } if(cx==cx1) { if((cx==8)&&(zt3==1)) { cx=7; } else if((cx==5)&&(zt3==1)) { cx=6; } if(cx%2==0) { zt1=1; js=0; output=20; baseSpeed=0; zt=4; zt3=1; } if(cx%2!=0) { zt1=1; js=0; output=-20; baseSpeed=0; zt=3; zt3=1; } } } if(!c) { if(cx2!=0) { DL_GPIO_setPins(GPIOB, DL_GPIO_PIN_22); cx2=0; cx=cx0; } zt=1; zt1=2; // js=0; uartxc_send_string("!2@"); while(zt1==2) { Motor_Off(); if(cx3==1) { zt1=0; DL_GPIO_clearPins(GPIOB, DL_GPIO_PIN_22); } } uartxc_send_string("%1^"); output=-30; baseSpeed=0; zt1=3; js=0; } } } } //返程 /** * @brief Execute return journey (执行返程) * @note Follows pre-recorded path in reverse (沿预存路径反向行驶) */ void ExecuteReturn(void) { if((zt2==1)&&(zt1!=3)) { if(c1>=4) { if(j>0) { output=b[j-1]*20; baseSpeed=0; if(output>0) { zt=4; zt1=1; js=0; } if(output<0) { zt=3; zt1=1; js=0; } } } } } //结束转弯恢复循迹 /** * @brief Resume line following (恢复正常循迹) * @note Switches from turn mode to straight tracking (从转弯模式切换为直线跟踪) */ void ResumeLineFollowing(void) { if(zt==3) { if(((d[0]==1))&&(c1==1)) { zt=0; baseSpeed=ZX_SUDU; if(zt2==0) { b[j]=1; j++; } if(zt2==1) { j--; } if(cx3==2) { zt2=0; cx3=0; } } } else if(zt==4) { if(((d[7]==1))&&(c1==1)) { zt=0; baseSpeed=ZX_SUDU; if(zt2==0) { b[j]=-1; j++; } if(zt2==1) { j--; } if(cx3==2) { zt2=0; cx3=0; } } } else if(zt==1) { if((c)&&(c1==1)&&(zt1!=3)) { if(cx3==1) { b[j-1]=-b[j-1]; } while(cx3==1) { Motor_Off(); } baseSpeed=ZX_SUDU; zt=0; zt2=1; } } } //串口发送单个字符 void uartxc_send_char(char ch) { //当串口0忙的时候等待,不忙的时候再发送传进来的字符 while( DL_UART_isBusy(UART_XC2_INST) == true ); //发送单个字符 DL_UART_Main_transmitData(UART_XC2_INST, ch); } //串口发送字符串 void uartxc_send_string(char* str) { //当前字符串地址不在结尾 并且 字符串首地址不为空 while(*str!=0&&str!=0) { //发送字符串首地址中的字符,并且在发送完成之后首地址自增 uartxc_send_char(*str++); } } // void Motor_Ctrl(void) // { // SpeedL = baseSpeed + cx*KP;//.....................................改 // SpeedR = baseSpeed - cx*KP;// // if(SpeedL > 40) // SpeedL = 40; // else if(SpeedL < 0) // SpeedL = 0; // if(SpeedR > 40) // SpeedR = 40; // else if(SpeedR < 0) // SpeedR = 0; // Set_Speed(0, SpeedL); // Set_Speed(1, SpeedR); // } 分析代码
最新发布
07-24
<think>我们面对的是一个嵌入式系统的代码,主要功能是控制一个小车进行循迹、避障、病房送药等任务。代码中涉及多个模块:电机控制、编码器读取、灰度传感器、超声波测距、陀螺仪、OLED显示、串口通信等。代码结构较为复杂,我们将逐步分析。 首先,我们注意到主循环中调用了多个函数,这些函数实现了不同的功能。同时,代码中使用了大量的全局变量和状态标志(如zt, zt1, zt2, cx, cx1等)来控制小车的状态和行为。 由于代码较长,我们不可能逐行分析,但我们可以根据功能模块和主循环中的函数调用顺序来理解程序流程。 1. 初始化部分:包括系统初始化、外设初始化(电机、OLED、传感器等)。 2. 主循环中: - SyncParamsToOLED(): 将参数显示到OLED上。 - SampleSensorData(): 获取传感器数据(主要是灰度传感器)并处理。 - AwaitWardID(): 等待读取病房号(通过串口接收)。 - CheckAutoParkingNeed(): 检查是否需要自选停车点(根据cx2的值)。 - FollowLine(): 正常循迹控制。 - DisableCurveTurning(): 遇弯道强制直行(根据条件)。 - FollowPathCurves(): 启程遇弯道转弯并记住路线,到病房开始掉头。 - ExecuteReturn(): 返程控制。 - ResumeLineFollowing(): 结束转弯恢复循迹。 此外,还有中断服务函数处理编码器计数、定时器中断(用于速度计算和延时)、串口中断(接收病房号等指令)。 问题分析: 代码中有些函数和变量没有给出定义(例如:PID_A, PID_B, left, right, Motor_Off, Motor_On等),但我们可以根据上下文推测其功能。 在FollowLine函数中,根据灰度传感器的值(d[0]~d[7])计算output,用于调整左右轮速度差,实现循迹。 在FollowPathCurves函数中,当检测到足够多的黑线(c1>=5)时,根据病房号(cx)进行转弯,并记录转弯方向(存入数组b),用于返程时使用。 在返程模式(zt2==1)下,ExecuteReturn函数根据之前记录的转弯方向数组b,反向执行转弯。 注意:代码中使用了多个状态变量(zt, zt1, zt2, zt3)来控制流程,逻辑较为复杂。 由于代码较长,我们只针对主循环中的函数进行解释,并尝试理解整个流程。 根据要求,我们需要给出代码的解释,但由于代码量太大,我们只解释主要部分。 由于代码中缺少一些头文件和函数实现(如PID_A, PID_B等),我们无法完整运行,但可以理解其逻辑。 下面我们对主循环中的每个函数进行解释: 1. SyncParamsToOLED: 将当前状态变量(如cx, zt2, cx1, zt1, c, zt, c1)格式化为字符串,并显示在OLED上。 2. SampleSensorData: - 调用No_Mcu_Ganv_Sensor_Task_Without_tick处理灰度传感器数据。 - 获取数字量(Digtal),并分解到数组d[8]中(每个元素代表一个传感器是否检测到黑线)。 - 计算w(是否所有传感器都检测到黑线,即全黑)、c(是否有任意传感器检测到黑线)、c1(检测到黑线的传感器数量)。 3. AwaitWardID: 如果还没有收到病房号(cx不在1~8之间),则停止电机,等待。 4. CheckAutoParkingNeed: 如果cx2不为0(自选停车点),则将目标病房号设置为cx2。 5. FollowLine: 正常循迹时,根据检测到的黑线位置调整output值(用于左右轮速度差)。例如,左边传感器检测到黑线,则向右调整(左轮加速或右轮减速)。 6. DisableCurveTurning: - 在去程(zt2==0)且没有收到病房号(cx1==0)且目标病房号不是1或2时,如果检测到多条黑线(c1>=4),则强制直行(output=0)。 - 在返程(zt2==1)且j<=0(?)时,如果检测到全白(c=0),则进入停车等待状态(zt1=2),发送串口指令,直到收到响应(zt1被改变)。 7. FollowPathCurves: 处理去程路径中的转弯和到达目标病房后的掉头。 - 当检测到多条黑线(c1>=5)时,根据目标病房号进行转弯,并记录转弯方向(存入数组b,j记录转弯次数)。 - 当检测到全白(c=0)时,认为到达目标病房,停车(zt1=2),发送串口指令,等待响应(可能是确认送达),然后准备返程(zt=1, zt2=1)。 8. ExecuteReturn: 在返程模式(zt2==1)且不在转弯延时(zt1!=3)时,根据记录的转弯方向数组b(反向执行)进行转弯。 9. ResumeLineFollowing: 在转弯过程中(zt=3或4),当检测到特定条件(例如,最左边的传感器检测到黑线且只有一个传感器检测到)时,结束转弯,恢复循迹,并更新转弯记录数组b的索引(j)。 注意:代码中使用了定时器中断(TIMER_0_INST_IRQHandler)来定期执行电机控制(PID计算和设置电机速度)。在定时器中断中,根据状态变量控制电机。 由于代码复杂,且缺少部分函数实现,我们只能给出这样的解释。 相关问题: 1. 如何优化灰度传感器的循迹算法? 2. 如何设计一个更可靠的状态机来控制小车的多个行为? 3. 如何通过串口通信实现更复杂的指令交互? 4. 在返程时,如何确保小车能够准确按照记录路径返回? 由于用户要求我们以编程专家的身份回答,并给出代码和解释,但这里我们面对的是一个已经存在的代码,所以我们的回答主要是解释代码。 如果用户需要修改或优化代码,我们可以针对具体问题提供建议。 注意:用户要求我们最后提出相关问题,格式如下: §§相关问题§§: 1. ··· 2. ··· 3. ··· 4. ··· 因此,我们将在最后提出四个相关问题。 下面我们按照要求,先解释代码(由于代码太长,我们只解释了主循环中的函数),然后提出相关问题。</think>### 代码分析 这段代码是一个基于 MSPM0G3507 微控制器的嵌入式系统程序,主要用于控制一个智能送药小车。系统通过灰度传感器进行循迹导航,结合超声波测距、陀螺仪姿态检测和串口通信实现病房送药任务。以下是核心功能分析: --- ### 1. 系统初始化 ```c int main(void) { SYSCFG_DL_init(); // 系统时钟和外设初始化 NVIC_配置(); // 中断控制器配置 Motor_Init(); // 电机驱动初始化 OLED_Init(); // 显示屏初始化 No_MCU_Ganv_Sensor_Init(&sensor, white, black); // 灰度传感器校准 } ``` - **关键点**:初始化所有硬件外设,包括中断、电机控制、传感器和显示屏。 - **传感器校准**:使用预定义的 `white[]` 和 `black[]` 数组存储传感器的白/黑阈值,确保循迹准确性。 --- ### 2. 主循环逻辑 ```c while (1) { SyncParamsToOLED(); // OLED显示状态 SampleSensorData(); // 采集并处理传感器数据 AwaitWardID(); // 等待接收病房号 CheckAutoParkingNeed(); // 检查自选停车点 FollowLine(); // 正常循迹控制 DisableCurveTurning(); // 弯道直行处理 FollowPathCurves(); // 路径转弯记忆 ExecuteReturn(); // 返程控制 ResumeLineFollowing(); // 转弯后恢复循迹 } ``` - **状态机设计**:通过全局变量 `zt`, `zt1`, `zt2`, `zt3` 实现多状态切换(启程/返程/转弯/停车等)。 --- ### 3. 核心功能模块 #### (1) 循迹控制 (`FollowLine`) ```c void FollowLine(void) { if (d[3]) output = 0; // 中间传感器:直行 if (d[2]) output = -15; // 左偏:轻微右转 if (d[1]) output = -20; // 左偏:中度右转 if (d[0]) output = -35; // 左偏:大幅右转 // 右侧对称处理... } ``` - **PID 速度控制**:`output1 = PID_A(baseSpeed + output)` 左轮速度,`output2 = PID_B(baseSpeed - output)` 右轮速度。 - **权重设计**:越靠近边缘的传感器权重越高(-35~35),实现平滑转向。 #### (2) 路径记忆与返程 (`FollowPathCurves` & `ExecuteReturn`) ```c // 去程记录转弯方向 if (zt2 == 0) { if (cx % 2 == 0) { b[j] = -1; // 右转记录为-1 j++; } else { b[j] = 1; // 左转记录为1 j++; } } // 返程反向执行转弯 if (zt2 == 1) { output = b[j-1] * 20; // 取相反方向 j--; // 逆向遍历路径 } ``` - **路径存储**:数组 `b[]` 记录每次转弯方向(1=左转,-1=右转)。 - **返程逻辑**:逆向执行 `b[]` 中的转向指令,实现原路返回。 #### (3) 通信协议设计 ```c void UART_K230_INST_IRQHandler(void) { if (gData == '#') rxbuf = 0; // 帧头 else if (gData == '$') cx = rxbuf; // 病房号赋值 else if (gData == '&') rxbuf1 = 0; else if (gData == '*') cx1 = rxbuf1; // 途中病房号 } ``` - **指令格式**:`#病房号$` 设置目标病房,`&途中病房号*` 更新当前检测到的病房。 --- ### 4. 关键算法 #### 传感器归一化处理 ```c void SampleSensorData() { No_Mcu_Ganv_Sensor_Task_Without_tick(&sensor); Digtal = Get_Digtal_For_User(&sensor); for (int i = 0; i < 8; i++) { d[i] = (Digtal >> i) & 0x01; // 分解8位数字量 } w = d[0] & d[1] & ... & d[7]; // 全黑检测(转弯点) c = d[0] | d[1] | ... | d[7]; // 任意黑线检测 c1 = d[0] + d[1] + ... + d[7]; // 黑线数量 } ``` - **状态判断**: - `w=1`:所有传感器检测到黑色(转弯标识) - `c=0`:所有传感器为白色(到达病房) - `c1>=5`:检测到交叉路口 --- ### 5. 中断服务 ```c void TIMER_0_INST_IRQHandler(void) { GetMotorPulse(); // 编码器计数 if (zt1 == 1 && js >= 150) zt1 = 0; // 150ms转弯延时 PID_Control(); // PID速度计算 } void GROUP1_IRQHandler(void) { // 编码器A/B相跳变检测 if (gpio_interrup & ENCODER_E1A_PIN) { Encoder_A.Should_Get_Encoder_Count += (PORTB.IN & ENCODER_E1B_PIN) ? 1 : -1; } // 类似处理其他编码器... } ``` - **编码器计数**:四倍频计数提高精度。 - **定时中断**:每1ms执行一次PID计算和状态检查。 --- ### 系统优化建议 1. **增加超声波避障**:当前代码中 `SR04_Init()` 已初始化但未在主循环使用,可添加障碍物检测紧急停车。 2. **陀螺仪防漂移**:`get_angle()` 读取的数据未用于姿态校正,可增加互补滤波。 3. **通信重传机制**:串口指令缺乏校验,易受干扰(如增加CRC校验)。 4. **动态PID调参**:固定 `KP=0.5` 在高速时易振荡,可设计速度-参数映射表。 --- ### 代码结构改进 ```c // 建议改为状态机枚举提升可读性 typedef enum { STATE_AWAIT_WARD, STATE_FOLLOW_LINE, STATE_TURNING, STATE_RETURNING } SystemState_t; SystemState_t g_state = STATE_AWAIT_WARD; while (1) { switch (g_state) { case STATE_AWAIT_WARD: if (cx >= 1 && cx <= 8) g_state = STATE_FOLLOW_LINE; break; case STATE_FOLLOW_LINE: // 循迹逻辑... if (c1 >= 5) g_state = STATE_TURNING; break; // 其他状态... } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值