int click(); int click(bool); auto p = [](bool){printf("xx);};怎么用信号槽链接

时间: 2025-02-03 07:15:39 浏览: 26
在C++中,信号槽机制通常用于实现观察者模式,使得对象之间可以解耦地进行通信。Qt框架提供了强大的信号槽机制,但如果你想在一个简单的C++环境中实现类似的功能,可以使用`std::function`和`std::bind`来实现。 以下是一个简单的示例,展示了如何将一个lambda函数连接到信号槽: ```cpp #include <iostream> #include <functional> #include <vector> class Signal { public: void connect(std::function<void(bool)> slot) { slots.push_back(slot); } void emit(bool value) { for (auto& slot : slots) { slot(value); } } private: std::vector<std::function<void(bool)>> slots; }; int main() { Signal signal; // 连接一个lambda函数到信号槽 auto p = [](bool value) { std::cout << "Value: " << value << std::endl; }; signal.connect(p); // 发射信号 signal.emit(true); return 0; } ``` 在这个示例中: 1. `Signal`类定义了一个`connect`方法,用于连接槽函数。 2. `emit`方法用于发射信号,调用所有连接的槽函数。 3. 在`main`函数中,我们创建了一个`Signal`对象,并使用lambda函数`p`连接到信号槽。 4. 最后,我们发射信号,lambda函数将被调用并输出相应的值。 这样,你就可以在C++中实现简单的信号槽机制,并将lambda函数作为槽函数连接。
阅读全文

相关推荐

ExMessage msg = {0}; const int distancex = 102, distancey =172 ; const int interval = 5; const int block_size = 70; int click=0; int first_click_row, first_click_col; int second_click_row, second_click_col; bool isMoving = false; bool isSwap = false; bool uptype = true; struct block { int x, y; int type; int row, col; int match; int tmd; }; struct block animal[8 + 2][8 + 2]; bool inArea(int mx, int my, int x, int y, int w, int h) { if (mx >= x && mx <= x + w && my >= y && my <= y + h) { return true; } return false; } bool button(int x, int y, int w, int h,IMAGE* picture) { int i; if (inArea(msg.x, msg.y, x, y, w, h)) { if (x % 2 == 0) { i = 2; } else { i = 3; } } else { if (x % 2 == 0) { i = 0; } else { i = 1; } } drawImg(x, y, picture+i); if (msg.message == WM_LBUTTONDOWN && inArea(msg.x, msg.y, x, y, w, h)) { msg.message = 0; return true; } else { return false; } } void exchange(int row1, int col1, int row2, int col2) { struct block tmp = animal[row1][col1]; animal[row1][col1] = animal[row2][col2]; animal[row2][col2] = tmp; animal[row1][col1].row = row1; animal[row1][col1].col = col1; animal[row2][col2].row = row2; animal[row2][col2].col = col2; //printf("交换后:\n"); //printf("animal[%d][%d].x = %d, y = %d\n", row1, col1, animal[row1][col1].x, animal[row1][col1].y); //printf("animal[%d][%d].x = %d, y = %d\n", row2, col2, animal[row2][col2].x, animal[row2][col2].y); } void move() { int dx; int dy; isMoving = false; for (int i = 8;i > 0;i--) { for (int j = 1;j < 9;j++) { struct block* p = &animal[i][j]; int x = distancex + (p->col - 1) * (block_size + 5); int y = distancey + (p->row - 1) * (block_size + 5); dx = p->x - x; dy = p->y - y; if (dx)p->x -= dx / abs(dx); if (dy)p->y -= dy / abs(dy); if (dy || dx)isMoving = true; } } } void userClick() { if (peekmessage(&msg)&&msg.message==WM_LBUTTONDOWN) { if (msg.x < distancex || msg.y < distancey)return; int col = (msg.x - distancex) / (block_size + 5) + 1; int row = (msg.y - distancey) / (block_size + 5) + 1; if (row > 8 || col > 8)return; click++; if (click == 1) { first_click_row = row; first_click_col = col; } else if (click == 2) { second_click_row = row; second_click_col = col; if (abs(first_click_row - second_click_row) + abs(first_click_col - second_click_col) == 1) { exchange(first_click_row, first_click_col, second_click_row, second_click_col); click = 0; isSwap = true; } else { first_click_row = row; first_click_col = col; click = 1; } } } } void reduction() { if (isSwap && !isMoving) { int count = 0; for (int i = 1;i < 9;i++) { for (int j = 1;j < 9;j++) { count += animal[i][j].match; } } if (count==0) { Sleep(300); exchange(first_click_row, first_click_col, second_click_row, second_click_col); } isSwap = false; } } void check() { for (int i = 0;i < 11;i++) { for (int j = 1;j < 9;j++) { animal[i][j].match = 0; } } for (int i = 1;i < 9; i++) { for (int j = 1;j < 7;j++) { if (animal[i][j].type == animal[i + 1][j].type && animal[i][j].type == animal[i +2][j].type) { animal[i][j].match = 1; animal[i + 1][j].match = 1; animal[i + 2][j].match = 1; } } } for (int j = 1;j < 9;j++) { for (int i = 1;i < 7;i++) { if (animal[i][j].type == animal[i][j + 1].type && animal[i][j].type == animal[i][j+2].type) { animal[i][j].match = 1; animal[i][j + 1].match = 1; animal[i][j + 2].match = 1; } } } } void Eliminate() { for (int i = 1;i < 9;i++) { for (int j = 0;j < 9;j++) { if (animal[i][j].match) { animal[i][j].tmd = max(0, animal[i][j].tmd - 5); if (animal[i][j].tmd <= 0) { animal[i][j].type = 0; } isMoving = true; } } } } void Generation() { for (int j = 1;j < 9;j++) { int bottom = 8; for (int i = 8;i > 0;i--) { if (animal[i][j].type != 0) { if (i != bottom) { exchange(i, j, bottom, j); } bottom--; } } for (int pos = bottom; pos >= 1; pos--) { animal[pos][j] = animal[0][j]; animal[pos][j].row = pos; animal[pos][j].col = j; animal[pos][j].x = distancex + (j - 1) * (block_size + 5); animal[pos][j].y = distancey - block_size; animal[pos][j].tmd = 255; } } for (int j = 1; j <= 8; j++) { animal[0][j].type = 1 + rand() % 6; } } int main() { initgraph(800, 800, EX_SHOWCONSOLE | EX_MOUSE | EX_DBLCLKS); setbkcolor(WHITE); cleardevice(); setfillcolor(RGB(230, 231, 232)); IMAGE bkpicture; loadimage(&bkpicture, "picture/bk.jpg"); char str1[100] = ""; IMAGE startpicture[4]; IMAGE startbk; for (int i = 0;i < 4;i++) { sprintf_s(str1, "picture/startpicture%d.png", i + 1); loadimage(startpicture + i, str1); } putimage(0, 0, &bkpicture); //solidroundrect(100, 600, 345, 700, 50, 50); //solidroundrect(445, 600, 690, 700, 50, 50); int open = 1; while (open == 1) { BeginBatchDraw(); peekmessage(&msg, EX_MOUSE); if (button(100, 600, 245, 100, startpicture)) { open = 0; } else if (button(445, 600, 245, 100, startpicture)) { closegraph(); } EndBatchDraw(); } cleardevice(); loadimage(&startbk, "picture/startbk.jpg"); putimage(0, 0, &startbk); srand(time(NULL)); for (int i = 1;i < 9; i++) { for (int j = 1;j < 9;j++) { animal[i][j].type = 1 + rand() % 6; animal[i][j].row = i; animal[i][j].col = j; animal[i][j].x = distancex + (j - 1) * (block_size + 5); animal[i][j].y = distancey + (i - 1) * (block_size + 5); animal[i][j].match = 0; animal[i][j].tmd = 255; } } IMAGE animaltype[6]; char str2[100] = ""; for (int i = 0;i < 6;i++) { sprintf_s(str2, "picture/animal%d.png", i + 1); loadimage(animaltype + i, str2); } while (true) { for (int j = 1;j < 9;j++) { animal[0][j].type = 1 + rand() % 6; } userClick(); move(); if (!isMoving) { check(); reduction(); Eliminate(); } bool needGenerate = false; for (int i = 1; i <= 8; i++) { for (int j = 1; j <= 8; j++) { if (animal[i][j].type == 0) { needGenerate = true; break; } } if (needGenerate) break; } if (needGenerate) { Generation(); isMoving = true; // 触发新动画 } } BeginBatchDraw(); putimage(0, 0, &startbk); for (int i = 1;i < 9; i++) { for (int j = 1;j < 9;j++) { if (animal[i][j].type) { putimageTMD(animal[i][j].x, animal[i][j].y, animaltype + animal[i][j].type - 1, animal[i][j].tmd); } } } EndBatchDraw(); system("pause"); return 0; }

在任务三中间添加了逻辑在使用CCD巡线的部分,在原程序所规定的时间跑完之后,只有当6050得到检测到的角度值(检测值范围在-180到+180)偏差(把初始的值看做0,运行完程序后的值看做末值)大于180(先换做360度的规则去看,再看初末差值是否大于180)的时候,才接着执行后面的程序,否则继续进行ccd巡线,直到偏差值大于180 empty.c #include <math.h> // 添加数学库用于fabs函数 #include "board.h" #include "my_key.h" #include "my_time.h" #include "ti_msp_dl_config.h" void BUZZY_OFF(void) { DL_GPIO_setPins(BUZZY_PORT, BUZZY_PIN_PIN); } void BUZZY_ON(void) { DL_GPIO_clearPins(BUZZY_PORT, BUZZY_PIN_PIN); } void refresh_oled(void); void key(void); void go_straight(int dis); void go_arc_ccd(hsu_time_t); void go_brc_ccd(hsu_time_t); void turn_in_place(float angle); void sound_light_alert(void); u8 Car_Mode = Diff_Car; int Motor_Left, Motor_Right; // 电机PWM变量 应是Motor的 u8 PID_Send; // 延时和调参相关变量 float RC_Velocity = 200, RC_Turn_Velocity, Move_X, Move_Y, Move_Z, PS2_ON_Flag; // 遥控控制的速度 float Velocity_Left, Velocity_Right; // 车轮速度(mm/s) u16 test_num, show_cnt; float Voltage = 0; extern float Yaw; // 声明外部YAW角度变量 int64_t left_encoder = 0, right_encoder = 0; void SysTick_Handler(void) { hsu_time_systick_handler(); } typedef enum { BEGIN, T1, T2, T3, T4 } TaskState; typedef enum { STOP, GO_STRAIGHT, GO_CCD, TURN_IN_PLACE, WAIT_ALERT } DoingWhat; typedef struct __TASK_NAMESPACE { uint8_t is; uint8_t is_running; uint8_t finish; uint8_t sub_finish; TaskState state; DoingWhat doing_what; float target; float vx; float vz; // 用于复杂任务 uint8_t sub_task_stage; // 子任务阶段 uint8_t lap_count; // 圈数计数 int64_t start_encoder; // 起始编码器值 uint32_t alert_start_time; // 声光提示开始时间 float start_yaw; // 起始YAW角度 float target_yaw_diff; // 目标YAW角度差 hsu_time_t ccd_end_time; float ccd_start_yaw; // 记录CCD巡线开始时的Yaw角度 uint8_t angle_check_flag; // 角度检测标志 } TaskNamespace; void reset_task_namespace(TaskNamespace *t) { t->is_running = 0; t->finish = 0; t->sub_finish = 0; t->state = BEGIN; t->doing_what = STOP; t->vx = 0; t->vz = 0; t->sub_task_stage = 0; t->lap_count = 0; t->start_encoder = left_encoder; t->alert_start_time = 0; t->start_yaw = 0; t->target_yaw_diff = 0; t->ccd_end_time = 0; t->is = 0; } void next_state(TaskNamespace *t) { TaskState last_state = t->state; reset_task_namespace(t); if (last_state < T4) { t->state = last_state + 1; } } TaskNamespace task_namespace; void show_task_now(void) { OLED_ShowString(0, 0, (uint8_t *)"Task Now:"); switch (task_namespace.state) { case BEGIN: OLED_ShowString(0, 12, (uint8_t *)"NO TASK"); break; case T1: OLED_ShowString(0, 12, (uint8_t *)"TASK 1 "); break; case T2: OLED_ShowString(0, 12, (uint8_t *)"TASK 2 "); break; case T3: OLED_ShowString(0, 12, (uint8_t *)"TASK 3 "); break; case T4: OLED_ShowString(0, 12, (uint8_t *)"TASK 4 "); break; default: break; } } void main_task(void); int main(void) { // 系统初始化 SYSCFG_DL_init(); // 初始化系统配置 hsu_time_init(); // 时间 // 清除所有外设的中断挂起状态 NVIC_ClearPendingIRQ(ENCODERA_INT_IRQN); // 编码器A中断 NVIC_ClearPendingIRQ(ENCODERB_INT_IRQN); // 编码器B中断 NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN); // UART0串口中断 // 使能各外设的中断 NVIC_EnableIRQ(ENCODERA_INT_IRQN); // 开启编码器A中断 NVIC_EnableIRQ(ENCODERB_INT_IRQN); // 开启编码器B中断 NVIC_EnableIRQ(UART_0_INST_INT_IRQN); // 开启UART0中断 // 定时器和ADC相关中断配置 NVIC_ClearPendingIRQ(TIMER_0_INST_INT_IRQN); // 清除定时器0中断挂起 NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); // 开启定时器0中断 NVIC_EnableIRQ(ADC12_VOLTAGE_INST_INT_IRQN); NVIC_EnableIRQ(ADC12_CCD_INST_INT_IRQN); OLED_Init(); // 初始化OLED显示屏 MPU6050_initialize(); DMP_Init(); // 主循环 BUZZY_ON(); // printf("Test delay 500us\n"); // hsu_time_delay_us(500); // printf("Test delay 500us end\n"); uint8_t main_task_timer = hsu_time_timer_create(10, true, main_task); hsu_time_timer_start(main_task_timer); uint8_t refresh_oled_timer = hsu_time_timer_create(5, true, refresh_oled); hsu_time_timer_start(refresh_oled_timer); uint8_t key_timer = hsu_time_timer_create(2, true, key); hsu_time_timer_start(key_timer); while (1) { hsu_time_timer_process(); RD_TSL(); // 读取CCD数据 Find_CCD_Median(); // 计算CCD数据中值 Read_DMP(); show_task_now(); // printf("L=%lld R=%lld YAW=%.1f\n", left_encoder, right_encoder, Yaw); } } void task_no(void); void task_1(void); void task_2(void); void task_3(void); void task_4(void); void main_task(void) { if (!(task_namespace.is)) return; printf("main task\n"); switch (task_namespace.state) { case BEGIN: task_no(); break; case T1: task_1(); break; case T2: task_2(); break; case T3: task_3(); break; case T4: task_4(); break; default: break; } switch (task_namespace.doing_what) { case STOP: Get_Target_Encoder(0, 0); break; case GO_STRAIGHT: if ((left_encoder * 1.f) < task_namespace.target) { Get_Target_Encoder(0.6, 0); // 提高速度到600mm/s } else { Get_Target_Encoder(0, 0); task_namespace.doing_what = STOP; task_namespace.finish = 1; } break; case GO_CCD: if (task_namespace.ccd_end_time < hsu_time_get_ms()) { if (task_namespace.angle_check_flag) { // 计算角度偏差(处理角度环绕) float yaw_diff = fabsf(Yaw - task_namespace.start_yaw); if (yaw_diff > 0) { yaw_diff = 180 - yaw_diff; } if (yaw_diff > 60.0f) { // 角度偏差大于45度,结束巡线 Get_Target_Encoder(0, 0); task_namespace.doing_what = STOP; task_namespace.finish = 1; } else { // 角度不足,继续巡线(延长50ms) task_namespace.ccd_end_time = hsu_time_get_ms() + 50; } } else { // 不需要角度检测的情况 Get_Target_Encoder(0, 0); task_namespace.doing_what = STOP; task_namespace.finish = 1; } } else { CCD_Mode(); // 继续巡线 } break; case TURN_IN_PLACE: // 原地转向控制 if (task_namespace.target_yaw_diff != 0) { float current_yaw_diff = Yaw - task_namespace.start_yaw; // 处理角度跨越±180度的情况 if (current_yaw_diff > 180) { current_yaw_diff -= 360; } else if (current_yaw_diff < -180) { current_yaw_diff += 360; } printf("Turn: Start=%.1f Current=%.1f Diff=%.1f Target=%.1f\n", task_namespace.start_yaw, Yaw, current_yaw_diff, task_namespace.target_yaw_diff); // 检查是否达到目标角度 if ((task_namespace.target_yaw_diff > 0 && current_yaw_diff >= task_namespace.target_yaw_diff) || (task_namespace.target_yaw_diff < 0 && current_yaw_diff <= task_namespace.target_yaw_diff)) { Get_Target_Encoder(0, 0); // 停止转向 task_namespace.doing_what = STOP; task_namespace.finish = 1; } else { // 继续转向 - 修改此处提高速度 float turn_speed = (task_namespace.target_yaw_diff > 0) ? 0.3 : -0.3; // 提高到0.3 // 添加比例控制 - 离目标角度越远,速度越快 float remaining_angle = fabsf(task_namespace.target_yaw_diff - current_yaw_diff); float speed_factor = fminf(1.0, remaining_angle / 30.0); // 角度差>30°时全速 // 应用比例控制后的速度 turn_speed *= speed_factor; Get_Target_Encoder(0, turn_speed); } } break; case WAIT_ALERT: Get_Target_Encoder(0, 0); // 停车 if (hsu_time_get_ms() - task_namespace.alert_start_time > 1000) { // 声光提示1秒 task_namespace.doing_what = STOP; task_namespace.finish = 1; } break; default: break; } } void task_no(void) { return; } // 任务1:A点到B点直线行驶 void task_1(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; go_straight(3300); return; } if (task_namespace.finish) { sound_light_alert(); // 声光提示 reset_task_namespace(&task_namespace); } return; } // 任务2:A->B->C->D->A循环 void task_2(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: // 开始第一阶段:A到B go_straight(3300); break; case 1: // A到B完成,开始B到C弧线 sound_light_alert(); go_arc_ccd(3550); break; case 2: // B到C弧线完成,开始C到D直线 sound_light_alert(); //turn_in_place(-17.0f); go_straight(2980); break; case 3: // C到D完成,开始D到A弧线 sound_light_alert(); go_arc_ccd(3530); break; case 4: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } return; } // 任务3:A->C->B->D->A循环 void task_3(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: turn_in_place(-31.0f); break; case 1: go_straight(4060); break; case 2: turn_in_place(30.0f); break; case 3: // 开始C到B弧线 sound_light_alert(); //go_straight(40); go_brc_ccd(500); break; case 4: turn_in_place(36.0f); break; case 5: sound_light_alert(); go_straight(3985); break; case 6: turn_in_place(-40.0f); break; case 7: // 开始C到B弧线 sound_light_alert(); go_arc_ccd(3600); break; case 8: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } return; } // 任务4:重复任务3路径4圈 void task_4(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: turn_in_place(-30.0f); break; case 1: go_straight(4045); break; case 2: turn_in_place(29.0f); break; case 3: // 开始C到B弧线 sound_light_alert(); //go_straight(40); go_brc_ccd(5000); break; case 4: turn_in_place(34.0f); break; case 5: sound_light_alert(); go_straight(4035); break; case 6: turn_in_place(-33.0f); break; case 7: // 开始C到B弧线 sound_light_alert(); go_arc_ccd(5000); break; case 8: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } } void TIMER_0_INST_IRQHandler(void) { if (DL_TimerA_getPendingInterrupt(TIMER_0_INST)) { if (DL_TIMER_IIDX_ZERO) { Get_Velocity_From_Encoder(Get_Encoder_countA, Get_Encoder_countB); Get_Encoder_countA = Get_Encoder_countB = 0; MotorA.Motor_Pwm = Incremental_PI_Left(MotorA.Current_Encoder, MotorA.Target_Encoder); MotorB.Motor_Pwm = Incremental_PI_Right(MotorB.Current_Encoder, MotorB.Target_Encoder); if (!Flag_Stop) { Set_PWM(-MotorA.Motor_Pwm, -MotorB.Motor_Pwm); } else { Set_PWM(0, 0); } } } } uint32_t gpio_interrup1, gpio_interrup2; int64_t B1, B2, B3, B4; int64_t A1, A2, A3, A4; void GROUP1_IRQHandler(void) { // 获取中断信号 gpio_interrup1 = DL_GPIO_getEnabledInterruptStatus(ENCODERA_PORT, ENCODERA_E1A_PIN | ENCODERA_E1B_PIN); gpio_interrup2 = DL_GPIO_getEnabledInterruptStatus(ENCODERB_PORT, ENCODERB_E2A_PIN | ENCODERB_E2B_PIN); // encoderB if ((gpio_interrup1 & ENCODERA_E1A_PIN) == ENCODERA_E1A_PIN) { if (!DL_GPIO_readPins(ENCODERA_PORT, ENCODERA_E1B_PIN)) { right_encoder--; Get_Encoder_countB--; } else { right_encoder++; Get_Encoder_countB++; } } else if ((gpio_interrup1 & ENCODERA_E1B_PIN) == ENCODERA_E1B_PIN) { if (!DL_GPIO_readPins(ENCODERA_PORT, ENCODERA_E1A_PIN)) { right_encoder++; Get_Encoder_countB++; } else { right_encoder--; Get_Encoder_countB--; } } // encoderA if ((gpio_interrup2 & ENCODERB_E2A_PIN) == ENCODERB_E2A_PIN) { if (!DL_GPIO_readPins(ENCODERB_PORT, ENCODERB_E2B_PIN)) { left_encoder++; Get_Encoder_countA--; } else { left_encoder--; Get_Encoder_countA++; } } else if ((gpio_interrup2 & ENCODERB_E2B_PIN) == ENCODERB_E2B_PIN) { if (!DL_GPIO_readPins(ENCODERB_PORT, ENCODERB_E2A_PIN)) { left_encoder--; Get_Encoder_countA++; } else { left_encoder++; Get_Encoder_countA--; } } DL_GPIO_clearInterruptStatus(ENCODERA_PORT, ENCODERA_E1A_PIN | ENCODERA_E1B_PIN); DL_GPIO_clearInterruptStatus(ENCODERB_PORT, ENCODERB_E2A_PIN | ENCODERB_E2B_PIN); } // 直线行驶函数 void go_straight(int dis) { task_namespace.doing_what = GO_STRAIGHT; task_namespace.target = left_encoder + dis; task_namespace.finish = 0; } // 原地转向函数 void turn_in_place(float angle) { task_namespace.doing_what = TURN_IN_PLACE; task_namespace.start_yaw = Yaw; task_namespace.target_yaw_diff = angle; // 正值右转,负值左转 task_namespace.finish = 0; } // CCD巡线函数(需要外部条件结束) void go_ccd_line(void) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = left_encoder; task_namespace.finish = 0; // 设置一个安全的最大距离,防止无限巡线 // 可以根据实际场地调整这个值 static uint32_t ccd_end_time = 0; if (ccd_end_time == 0) { ccd_end_time = hsu_time_get_ms(); } // 如果巡线时间超过10秒或距离超过2000mm,强制结束 if (hsu_time_get_ms() - ccd_end_time > 10000 || (left_encoder * 1.f - task_namespace.start_encoder) > 2000) { task_namespace.finish = 1; ccd_end_time = 0; } } // 弧线CCD巡线函数 void go_arc_ccd(hsu_time_t time) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = left_encoder; task_namespace.ccd_end_time = hsu_time_get_ms() + time; } void go_brc_ccd(hsu_time_t time) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = right_encoder; task_namespace.ccd_end_time = hsu_time_get_ms() + time; task_namespace.ccd_start_yaw = Yaw; // 记录起始角度 task_namespace.angle_check_flag = 1; // 启用角度检测 } // 声光提示函数 void sound_light_alert(void) { LED_ON(); DL_GPIO_setPins(BUZZY_PORT, BUZZY_PIN_PIN); uint32_t start_time = hsu_time_get_ms(); while (hsu_time_get_ms() - start_time < 1000) { // 空循环等待1秒 } //hsu_time_delay_ms(200); DL_GPIO_clearPins(BUZZY_PORT, BUZZY_PIN_PIN); LED_OFF(); } // callback void refresh_oled(void) { show_task_now(); OLED_Refresh_Gram(); } uint32_t key_get_tick_ms(void) { return hsu_time_get_ms(); } void key(void) { key_event_t event = key_scan(); switch (event) { case KEY_EVENT_SINGLE_CLICK: next_state(&task_namespace); break; case KEY_EVENT_DOUBLE_CLICK: task_namespace.is = 1; break; } } CCD.c #include "CCD.h" uint8_t CCD_Zhongzhi; uint16_t ADV[128] = {0}; unsigned int adc_value = 0; unsigned int voltage_value = 0; volatile bool gCheckADC; // ADC²É¼¯³É¹¦±ê־λ float CCD_KP = 18, CCD_KI = 3; float CCD_Vel = 500; float CCD_KD = 4.0; float integral_error = 0; float light_level = 0; void CCD_Mode(void) { static float light_filter = 0; uint16_t avg = 0; for (int i = 20; i < 108; i++) avg += ADV[i]; avg /= 88; light_filter = 0.8 * light_filter + 0.2 * avg; light_level = light_filter / 256.0; Move_X = CCD_Vel / 1000.0f * (0.25 + 0.5 * light_level); static float Bias, Last_Bias; Bias = 64 - CCD_Zhongzhi; // Ìáȡƫ²î Move_Z = Bias * CCD_KP / 1000.0f + (Bias - Last_Bias) * CCD_KI / 1000.0f; // PD¿ØÖÆ Last_Bias = Bias; // ±£´æÉÏÒ»´ÎµÄÆ«²î Get_Target_Encoder(Move_X, Move_Z); } // ¶ÁÈ¡ADCµÄÊý¾Ý int adc_getValue(void) { unsigned int gAdcResult = 0; // Èí¼þ´¥·¢ADC¿ªÊ¼×ª»» DL_ADC12_startConversion(ADC12_CCD_INST); // Èç¹ûµ±Ç°×´Ì¬ÎªÕýÔÚת»»ÖÐÔòµÈ´ýת»»½áÊø // »ñÈ¡Êý¾Ý gAdcResult = DL_ADC12_getMemResult(ADC12_CCD_INST, ADC12_CCD_ADCMEM_0); // Çå³ý±ê־λ gCheckADC = false; return gAdcResult; } // CCD_ADCÖжϷþÎñº¯Êý void ADC12_CCD_INST_IRQHandler(void) { // ²éѯ²¢Çå³ýADCÖÐ¶Ï switch (DL_ADC12_getPendingInterrupt(ADC12_CCD_INST)) { // ¼ì²éÊÇ·ñÍê³ÉÊý¾Ý²É¼¯ case DL_ADC12_IIDX_MEM0_RESULT_LOADED: gCheckADC = true; // ½«±ê־λÖÃ1 break; default: break; } } /************************************************************************** º¯Êý¹¦ÄÜ£ºCCDÊý¾Ý²É¼¯ Èë¿Ú²ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void RD_TSL(void) { TSL_CLK(1); delay_us(5); TSL_SI(0); delay_us(10); TSL_CLK(0); delay_us(5); TSL_SI(1); delay_us(30); TSL_CLK(1); delay_us(5); TSL_SI(1); delay_us(10); TSL_CLK(1); delay_us(5); TSL_SI(0); delay_us(10); TSL_CLK(0); delay_us(100); for (int i = 0; i < 128; i++) // ¶ÁÈ¡128¸öÏñËØµãµçѹֵ { TSL_CLK(0); delay_us(100); // µ÷½ÚÆØ¹âʱ¼ä ADV[i] = (adc_getValue()) >> 4; // ÓÒÒÆ4λÊÇ/4²Ù×÷£¬½«Êý¾Ý·¶Î§´Ó0-4096ѹËõµ½0-256·½±ãÊý¾Ý´¦Àí TSL_CLK(1); delay_us(20); } } /************************************************************************** º¯Êý¹¦ÄÜ£ºÏßÐÔCCDÈ¡ÖÐÖµ Èë¿Ú²ÎÊý£ºÎÞ ·µ»Ø Öµ£ºÎÞ **************************************************************************/ void Find_CCD_Median(void) { static uint16_t i, j, Left, Right, Last_CCD_Median; static uint16_t value1_max, value1_min; static uint16_t CCD_Threshold; // ãÐֵ˵Ã÷£ºCCD²É¼¯»ØÀ´µÄ128¸öÊý¾Ý£¬Ã¿¸öÊý¾Ýµ¥¶ÀÓëãÐÖµ½øÐбȽϣ¬±ÈãÐÖµ´óΪ°×É«£¬±ÈãÐֵСΪºÚÉ« // ¶¯Ì¬ãÐÖµËã·¨£¬¶Áȡÿ´Î²É¼¯Êý¾ÝµÄ×î´óºÍ×îСֵµÄƽ¾ùÊý×÷ΪãÐÖµ value1_max = ADV[0]; for (i = 5; i < 123; i++) // Á½±ß¸÷È¥µô5¸öµã { if (value1_max <= ADV[i]) value1_max = ADV[i]; } value1_min = ADV[0]; // ×îСֵ for (i = 5; i < 123; i++) { if (value1_min >= ADV[i]) value1_min = ADV[i]; } CCD_Threshold = (value1_max + value1_min) / 2; // ¼ÆËã³ö±¾´ÎÖÐÏßÌáÈ¡µÄãÐÖµ for (i = 5; i < 118; i++) // ѰÕÒ×ó±ßÌø±äÑØ£¬Á¬ÐøÈý¸ö°×ÏñËØºóÁ¬ÐøÈý¸öºÚÏñËØÅжÏ×ó±ßÌø±äÑØ { if (ADV[i] > CCD_Threshold && ADV[i + 1] > CCD_Threshold && ADV[i + 2] > CCD_Threshold && ADV[i + 3] < CCD_Threshold && ADV[i + 4] < CCD_Threshold && ADV[i + 5] < CCD_Threshold) { Left = i + 2; break; } } for (j = 118; j > 5; j--) // ѰÕÒÓÒ±ßÌø±äÑØ£¬Á¬ÐøÈý¸öºÚÏñËØºóÁ¬ÐøÈý¸ö°×ÏñËØÅжÏÓÒ±ßÌø±äÑØ { if (ADV[j] < CCD_Threshold && ADV[j + 1] < CCD_Threshold && ADV[j + 2] < CCD_Threshold && ADV[j + 3] > CCD_Threshold && ADV[j + 4] > CCD_Threshold && ADV[j + 5] > CCD_Threshold) { Right = j + 2; break; } } CCD_Zhongzhi = (uint8_t)(Right + Left) / 2; // ¼ÆËãÖÐÏßλÖà } void TSL_CLK(int state) { if (state) { DL_GPIO_setPins(GPIO_CLK_PORT, GPIO_CLK_PIN_23_PIN); } else { DL_GPIO_clearPins(GPIO_CLK_PORT, GPIO_CLK_PIN_23_PIN); } } void TSL_SI(int state) { if (state) { DL_GPIO_setPins(GPIO_SI_PORT, GPIO_SI_PIN_25_PIN); } else { DL_GPIO_clearPins(GPIO_SI_PORT, GPIO_SI_PIN_25_PIN); } }

最新推荐

recommend-type

Google C++ Style Guide(Google C++编程规范)高清PDF

Click it now. You should see "Hooray" appear below. Hooray! Now you know you can expand points to get more details. Alternatively, there's an "expand all" at the top of this document. Background ...
recommend-type

基于QT的黑白棋游戏程序设计与实现(1).docx

基于QT的黑白棋游戏程序设计与实现(1).docx
recommend-type

互联网公司财务风险与管控建议研究论述(1).doc

互联网公司财务风险与管控建议研究论述(1).doc
recommend-type

软件开发过程规范(1).doc

软件开发过程规范(1).doc
recommend-type

langchain4j-document-loader-azure-storage-blob-0.27.0.jar中文文档.zip

1、压缩文件中包含: 中文文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。
recommend-type

C++实现的DecompressLibrary库解压缩GZ文件

根据提供的文件信息,我们可以深入探讨C++语言中关于解压缩库(Decompress Library)的使用,特别是针对.gz文件格式的解压过程。这里的“lib”通常指的是库(Library),是软件开发中用于提供特定功能的代码集合。在本例中,我们关注的库是用于处理.gz文件压缩包的解压库。 首先,我们要明确一个概念:.gz文件是一种基于GNU zip压缩算法的压缩文件格式,广泛用于Unix、Linux等操作系统上,对文件进行压缩以节省存储空间或网络传输时间。要解压.gz文件,开发者需要使用到支持gzip格式的解压缩库。 在C++中,处理.gz文件通常依赖于第三方库,如zlib或者Boost.IoStreams。codeproject.com是一个提供编程资源和示例代码的网站,程序员可以在该网站上找到现成的C++解压lib代码,来实现.gz文件的解压功能。 解压库(Decompress Library)提供的主要功能是读取.gz文件,执行解压缩算法,并将解压缩后的数据写入到指定的输出位置。在使用这些库时,我们通常需要链接相应的库文件,这样编译器在编译程序时能够找到并使用这些库中定义好的函数和类。 下面是使用C++解压.gz文件时,可能涉及的关键知识点: 1. Zlib库 - zlib是一个用于数据压缩的软件库,提供了许多用于压缩和解压缩数据的函数。 - zlib库支持.gz文件格式,并且在多数Linux发行版中都预装了zlib库。 - 在C++中使用zlib库,需要包含zlib.h头文件,同时链接z库文件。 2. Boost.IoStreams - Boost是一个提供大量可复用C++库的组织,其中的Boost.IoStreams库提供了对.gz文件的压缩和解压缩支持。 - Boost库的使用需要下载Boost源码包,配置好编译环境,并在编译时链接相应的Boost库。 3. C++ I/O操作 - 解压.gz文件需要使用C++的I/O流操作,比如使用ifstream读取.gz文件,使用ofstream输出解压后的文件。 - 对于流操作,我们常用的是std::ifstream和std::ofstream类。 4. 错误处理 - 解压缩过程中可能会遇到各种问题,如文件损坏、磁盘空间不足等,因此进行适当的错误处理是必不可少的。 - 正确地捕获异常,并提供清晰的错误信息,对于调试和用户反馈都非常重要。 5. 代码示例 - 从codeproject找到的C++解压lib很可能包含一个或多个源代码文件,这些文件会包含解压.gz文件所需的函数或类。 - 示例代码可能会展示如何初始化库、如何打开.gz文件、如何读取并处理压缩数据,以及如何释放资源等。 6. 库文件的链接 - 编译使用解压库的程序时,需要指定链接到的库文件,这在不同的编译器和操作系统中可能略有不同。 - 通常,在编译命令中加入-l参数,比如使用g++的话可能是`g++ -o DecompressLibrary DecompressLibrary.cpp -lz`,其中`-lz`表示链接zlib库。 7. 平台兼容性 - 在不同平台上使用解压库可能需要考虑平台兼容性问题。 - Windows系统可能需要额外的配置和库文件,因为zlib或其他库可能不是默认预装的。 根据以上知识点,我们可以得出,在C++中解压.gz文件主要涉及到对zlib或类似库的使用,以及熟悉C++的I/O操作。正确使用这些库,能够有效地对压缩文件进行解压,并处理可能出现的错误情况。如果从codeproject获取到的C++解压lib确实是针对.gz文件格式的,那么它很可能已经封装好了大部分的操作细节,让开发者能够以更简单的方式实现解压功能。
recommend-type

【数据融合技术】:甘肃土壤类型空间分析中的专业性应用

# 摘要 数据融合技术作为一种集成多源数据信息的方法,在土壤类型空间分析中发挥着关键作用。本文介绍了数据融合技术的基本概念及其理论基础,阐述了数据预处理、同步整合及冲突解决等关键技术,并详细描述了甘肃土壤类型数据准备的流程,包括数据采集、质量评估、空间化处理及融合实践准备。通过具体案例分析,展示了数据融合在土壤类型空间分布分析、土壤质量评估及土壤保护规划中的应用。同时,文
recommend-type

VM ware如何查看软件版本信息

<think>首先,用户的问题是:“我想查找VMware软件版本信息的查看方法请问如何在VMware中查看软件版本信息”。用户参考了之前的引用,但那些引用主要是关于查看VMware版本的一般方法,现在用户具体想知道在VMware软件中如何查看版本信息。回顾之前的对话:-用户第一次问的是VSCode的版本查看方法。-现在用户问的是VMware的版本查看方法。-系统级指令要求使用中文回答,正确格式化数学表达式(如果需要),但这里可能不需要数学表达式。-指令还要求生成相关问题,并在回答中引用段落时添加引用标识。用户提供的引用[1]到[5]是关于VMware版本的查看方法、下载等,但用户特别强调“参考
recommend-type

数据库课程设计报告:常用数据库综述

数据库是现代信息管理的基础,其技术广泛应用于各个领域。在高等教育中,数据库课程设计是一个重要环节,它不仅是学习理论知识的实践,也是培养学生综合运用数据库技术解决问题能力的平台。本知识点将围绕“经典数据库课程设计报告”展开,详细阐述数据库的基本概念、课程设计的目的和内容,以及在设计报告中常用的数据库技术。 ### 1. 数据库基本概念 #### 1.1 数据库定义 数据库(Database)是存储在计算机存储设备中的数据集合,这些数据集合是经过组织的、可共享的,并且可以被多个应用程序或用户共享访问。数据库管理系统(DBMS)提供了数据的定义、创建、维护和控制功能。 #### 1.2 数据库类型 数据库按照数据模型可以分为关系型数据库(如MySQL、Oracle)、层次型数据库、网状型数据库、面向对象型数据库等。其中,关系型数据库因其简单性和强大的操作能力而广泛使用。 #### 1.3 数据库特性 数据库具备安全性、完整性、一致性和可靠性等重要特性。安全性指的是防止数据被未授权访问和破坏。完整性指的是数据和数据库的结构必须符合既定规则。一致性保证了事务的执行使数据库从一个一致性状态转换到另一个一致性状态。可靠性则保证了系统发生故障时数据不会丢失。 ### 2. 课程设计目的 #### 2.1 理论与实践结合 数据库课程设计旨在将学生在课堂上学习的数据库理论知识与实际操作相结合,通过完成具体的数据库设计任务,加深对数据库知识的理解。 #### 2.2 培养实践能力 通过课程设计,学生能够提升分析问题、设计解决方案以及使用数据库技术实现这些方案的能力。这包括需求分析、概念设计、逻辑设计、物理设计、数据库实现、测试和维护等整个数据库开发周期。 ### 3. 课程设计内容 #### 3.1 需求分析 在设计报告的开始,需要对项目的目标和需求进行深入分析。这涉及到确定数据存储需求、数据处理需求、数据安全和隐私保护要求等。 #### 3.2 概念设计 概念设计阶段要制定出数据库的E-R模型(实体-关系模型),明确实体之间的关系。E-R模型的目的是确定数据库结构并形成数据库的全局视图。 #### 3.3 逻辑设计 基于概念设计,逻辑设计阶段将E-R模型转换成特定数据库系统的逻辑结构,通常是关系型数据库的表结构。在此阶段,设计者需要确定各个表的属性、数据类型、主键、外键以及索引等。 #### 3.4 物理设计 在物理设计阶段,针对特定的数据库系统,设计者需确定数据的存储方式、索引的具体实现方法、存储过程、触发器等数据库对象的创建。 #### 3.5 数据库实现 根据物理设计,实际创建数据库、表、视图、索引、触发器和存储过程等。同时,还需要编写用于数据录入、查询、更新和删除的SQL语句。 #### 3.6 测试与维护 设计完成之后,需要对数据库进行测试,确保其满足需求分析阶段确定的各项要求。测试过程包括单元测试、集成测试和系统测试。测试无误后,数据库还需要进行持续的维护和优化。 ### 4. 常用数据库技术 #### 4.1 SQL语言 SQL(结构化查询语言)是数据库管理的国际标准语言。它包括数据查询、数据操作、数据定义和数据控制四大功能。SQL语言是数据库课程设计中必备的技能。 #### 4.2 数据库设计工具 常用的数据库设计工具包括ER/Studio、Microsoft Visio、MySQL Workbench等。这些工具可以帮助设计者可视化地设计数据库结构,提高设计效率和准确性。 #### 4.3 数据库管理系统 数据库管理系统(DBMS)是用于创建和管理数据库的软件。关系型数据库管理系统如MySQL、PostgreSQL、Oracle、SQL Server等是数据库课程设计中的核心工具。 #### 4.4 数据库安全 数据库安全涉及用户认证、授权、数据加密、审计日志记录等方面,以确保数据的完整性和保密性。设计报告中应考虑如何通过DBMS内置的机制或额外的安全措施来保护数据。 ### 5. 结语 综上所述,一个经典数据库课程设计报告包含了从需求分析到数据库安全的全过程,涵盖了数据库设计的各个方面。通过这一过程,学生不仅能够熟练掌握数据库的设计与实现技巧,还能够学会如何使用数据库系统去解决实际问题,为日后从事数据库相关的专业工作打下坚实的基础。
recommend-type

【空间分布规律】:甘肃土壤类型与农业生产的关联性研究

# 摘要 本文对甘肃土壤类型及其在农业生产中的作用进行了系统性研究。首先概述了甘肃土壤类型的基础理论,并探讨了土壤类型与农业生产的理论联系。通过GIS技术分析,本文详细阐述了甘肃土壤的空间分布规律,并对其特征和影响因素进行了深入分析。此外,本文还研究了甘肃土壤类型对农业生产实际影响,包括不同区域土壤改良和作物种植案例,以及土壤养分、水分管理对作物生长周期和产量的具体影响。最后,提出了促进甘肃土壤与农业可持续发展的策略,包括土壤保护、退化防治对策以及土壤类型优化与农业创新的结合。本文旨在为