SPI_WRITE宏解析

内核代码

#define SPI_WRITE_0(addr, data) spi_write(addr, data, 0)
#define SPI_WRITE_1(addr, data, wait) spi_write(addr, data, wait)
#define GET_SPI_WRITE_MACRO(_1, _2, _3, NAME, ...) NAME
#define SPI_WRITE(...) GET_SPI_WRITE_MACRO(__VA_ARGS__, SPI_WRITE_1, SPI_WRITE_0)(__VA_ARGS__)

在C语言中,VA_ARGS 是一个可变参数宏的特殊标识符,它用于在宏定义中展开传递给宏的参数。这个标识符是由预处理器处理的,它代表了由省略号(…)表示的可变数量的参数。在宏展开时,VA_ARGS 会被替换为实际传递给宏的参数。

SPI_WRITE(0x70, 0x01, 5);
第一步展开成:
GET_SPI_WRITE_MACRO(0x70, 0x01, 5,SPI_WRITE_1,SPI_WRITE_0) (0x70, 0x01, 5)

#define GET_SPI_WRITE_MACRO(_1, _2, _3, NAME, …) NAME中:_1, _2, _3 是 GCC 提供的参数扩展,它们会展开为传递给宏的第一个、第二个和第三个参数;NAME 是最后一个参数;… 表示剩余的参数;整体上是一个带参宏。

本例中,NAME此时是SPI_WRITE_1,
进一步展开:SPI_WRITE_1(0x70, 0x01, 5)

如果SPI_WRITE(0x70, 0x01);
NAME 是 SPI_WRITE_0,_3 代表 SPI_WRITE_1
最终展开成SPI_WRITE(0x70, 0x01, 0);

#include "BAT32G135.h" #include "gpio.h" #include "wdt.h" #include "motor.h" #include "stdio.h" #include "intp.h" #include "global_config.h" #include "pt.h" #include "v_timer.h" #include "string.h" #define TYPE_CMD "type=" #define DIRECT_CMD "direct=" #define FREQ_CMD "freq=" #define FREQ_2_CMD "freq2=" #define STEP_CMD "step=" #define STEP_2_CMD "step2=" #define START_CMD "start" #define SPI_DEBUG_CMD "spi_debug=" #define MOTOR_WRITE_CMD "write=" #define MOTOR_READ_CMD "read=" struct queue *motor_action_queue; struct motor_action_info { uint8_t action_type; uint32_t fre; }; struct pt motor_pt; extern struct v_timer motor_main_timer; uint8_t spi_debug_flag; uint32_t step = 1000; uint32_t step_cnt = 0; uint8_t g_run_type = 5; uint8_t g_direct = 0; uint32_t g_freq = 500; uint32_t g_freq_2 = 1700; uint32_t g_freq_div = 0; uint32_t g_freq_sel = 0; uint32_t g_duty = 1000000/500; uint32_t g_step = 0; uint32_t g_step_2 = 0; //微秒级的延时 void delay_us(uint32_t delay_us) { volatile unsigned int num; volatile unsigned int t; for (num = 0; num < delay_us; num++) { t = 11; while (t != 0) { t--; } } } //毫秒级的延时 void delay_ms(uint16_t delay_ms) { volatile unsigned int num; for (num = 0; num < delay_ms; num++) { delay_us(1000); } } // 使用标准库实现的引脚控制函数 void std_gpio_writepin(PORT_TypeDef PORTx, uint16_t GPIO_Pin, uint8_t pinstate) { // 根据状态选择设置或清除操作 if(pinstate) { // 设置引脚高电平 PORT_SetBit(PORTx, GPIO_Pin); // 使用已有接口 // 或者直接操作: GPIO_Set_Value(port_reg, GPIO_Get_Value(port_reg) | GPIO_Pin); } else { // 设置引脚低电平 PORT_ClrBit(PORTx, GPIO_Pin); // 使用已有接口 // 或者直接操作: GPIO_Set_Value(port_reg, GPIO_Get_Value(port_reg) & ~GPIO_Pin); } } uint8_t std_gpio_readpin(PORT_TypeDef PORTx, uint16_t GPIO_Pin) { // 参数合法性检查 uint8_t PORT_MAX=14; if(PORTx >= PORT_MAX || GPIO_Pin == 0) { return 0; // 无效参数返回0 } // 使用PORT_GetBit直接读取引脚状态 return PORT_GetBit(PORTx, (PIN_TypeDef)GPIO_Pin); } // 修改后的 motor_1parse_run 函数 void motor_1parse_run(uint8_t line_1, uint8_t line_2, uint8_t line_3, uint8_t line_4) { std_gpio_writepin(MOTOR1_PORT, MOTOR1_PIN, line_1); std_gpio_writepin(MOTOR2_PORT, MOTOR2_PIN, line_2); std_gpio_writepin(MOTOR3_PORT, MOTOR3_PIN, line_3); std_gpio_writepin(MOTOR4_PORT, MOTOR4_PIN, line_4); } void motor_2parse_run(uint8_t line_5, uint8_t line_6, uint8_t line_7, uint8_t line_8) { std_gpio_writepin(MOTOR5_PORT, MOTOR5_PIN, line_5);//motor还没定义 std_gpio_writepin(MOTOR6_PORT, MOTOR6_PIN, line_6); std_gpio_writepin(MOTOR7_PORT, MOTOR7_PIN, line_7); std_gpio_writepin(MOTOR8_PORT, MOTOR8_PIN, line_8); } void motor_gpio_stop() { motor_1parse_run(0,0,0,0); motor_2parse_run(0,0,0,0); } void motor_gpio_run_1_2() { switch(step){ case 0: motor_1parse_run(0,0,0,1); break; case 1: motor_1parse_run(1,0,0,1); break; case 2: motor_1parse_run(1,0,0,0); break; case 3: motor_1parse_run(1,1,0,0); break; case 4: motor_1parse_run(0,1,0,0); break; case 5: motor_1parse_run(0,1,1,0); break; case 6: motor_1parse_run(0,0,1,0); break; case 7: motor_1parse_run(0,0,1,1); break; case 8: motor_1parse_run(0,0,0,0); break; } } void motor_gpio_run_1() { switch(step){ case 0: motor_1parse_run(1,0,0,0); break; case 1: motor_1parse_run(0,1,0,0); break; case 2: motor_1parse_run(0,0,1,0); break; case 3: motor_1parse_run(0,0,0,1); break; } } void motor_gpio_run_2() { switch(step){ case 0: motor_1parse_run(1,1,0,0); break; case 1: motor_1parse_run(0,1,1,0); break; case 2: motor_1parse_run(0,0,1,1); break; case 3: motor_1parse_run(1,0,0,1); break; } } #define MOTOR_RUN_SPI_CS(out) std_gpio_writepin(MOTOR_SPI_CS_PORT,MOTOR_SPI_CS_PIN,out)//spi直接写入值 #define MOTOR_RUN_SPI_CLK(out) std_gpio_writepin(MOTOR_SPI_CLK_PORT,MOTOR_SPI_CLK_PIN,out) #define MOTOR_RUN_SPI_MOSI(out) std_gpio_writepin(MOTOR_SPI_MOSI_PORT,MOTOR_SPI_MOSI_PIN,out) #define MOTOR_RUN_SPI_MISO std_gpio_readpin(MOTOR_SPI_MISO_PORT,MOTOR_SPI_MOSI_PIN) void spi_write(uint8_t DDATA, uint8_t Delay_Cnt)//带延时的SPI数据输入 { uint8_t S_DATA, j; uint8_t B_DATA; S_DATA = DDATA; B_DATA = (S_DATA & 0x80) ? 1 : 0;//三元运算符确保 B_DATA 的值始终为 0 或 1 for(j = 0; j < 8; j++) { MOTOR_RUN_SPI_MOSI(B_DATA); //设置 MOSI 为当前最高位 delay_ms(Delay_Cnt); //时钟建立时间(数据稳定) MOTOR_RUN_SPI_CLK(1); //时钟上升沿(数据采样点) delay_ms(Delay_Cnt*2); MOTOR_RUN_SPI_CLK(0); //时钟下降沿 delay_ms(Delay_Cnt); S_DATA = S_DATA << 1; B_DATA = S_DATA & 0X80; } if(Delay_Cnt > 20){ delay_ms(Delay_Cnt-20); }else{ delay_ms(Delay_Cnt); } MOTOR_RUN_SPI_MOSI(0); } uint8_t spi_read(uint8_t Delay_Cnt)//带延时SPI读取 { uint8_t R_DATA, j; MOTOR_RUN_SPI_MOSI(0); for(j = 0; j < 8; j++) { MOTOR_RUN_SPI_CLK(1); //????? delay_us(Delay_Cnt); R_DATA = R_DATA << 1; if(MOTOR_RUN_SPI_MISO == 1) //?????? { R_DATA = R_DATA | 0x01; } else { R_DATA = R_DATA & 0xFE; } delay_us(Delay_Cnt); MOTOR_RUN_SPI_CLK(0); //????? delay_us(Delay_Cnt*2); } return R_DATA; } uint8_t motor_spi_read(uint8_t addr)//SPI读取电机寄存器的值 { uint8_t data; // 初始化 SPI 总线状态 MOTOR_RUN_SPI_CLK(0); // 设置时钟线低电平(SPI 空闲状态) MOTOR_RUN_SPI_CS(0); MOTOR_RUN_SPI_CS(0); // 拉低片选信号(选中设备) delay_ms(5); delay_ms(5); // 设备初始化延时(5ms 确保设备就绪) // 发送要读取的寄存器地址 spi_write(addr, 50); // 调用写函数发送地址(50μs/位时序) delay_us(20); // 设备响应延时(20μs 准备数据) // 读取寄存器数据 data = spi_read(50); // 调用读函数获取数据(50μs/位时序) // 结束通信 MOTOR_RUN_SPI_CS(1); // 拉高片选信号(取消选中设备) MOTOR_RUN_SPI_CLK(0); // 时钟线回到低电平(空闲状态) if(spi_debug_flag){ printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } return data; } void motor_spi_write(uint8_t addr,uint8_t data)//SPI写入电机寄存器的值 { if(spi_debug_flag){ printf("[WRITE]addr: 0x%x , data: 0x%x\r\n",addr,data); } addr |= 0x80; MOTOR_RUN_SPI_CLK(0); MOTOR_RUN_SPI_CS(0); delay_ms(5); spi_write(addr, 50); delay_us(20); spi_write(data, 50); MOTOR_RUN_SPI_CS(1); MOTOR_RUN_SPI_CLK(0); #if 0 data = motor_spi_read(addr); #endif } void set_motor_direct(uint8_t direct)//电机转向控制,0顺时针,1逆时针 { g_direct = direct; printf("g_direct: %d \r\n",g_direct); } void motor_step_count(uint8_t parse)//STEP计数器 { if(g_direct){ step++; step = step%parse; }else{ step = step + parse; step--; step = step%parse; } } void print_motor()//输出电机各状态 { printf("g_run_type: %d \r\n",g_run_type); printf("g_direct: %d \r\n",g_direct); printf("g_freq: %d HZ\r\n",g_freq); printf("g_freq_2: %d HZ\r\n",g_freq_2); printf("g_duty: %d us\r\n",g_duty); printf("g_step: %d \r\n",g_step); printf("g_step_2: %d \r\n",g_step_2); } void set_motor_run_type(uint8_t run_type)//选择电机运行模式,分别对应1-2相驱动、1相驱动、2相驱动。 { g_run_type = run_type; printf("g_run_type: %d \r\n",g_run_type); if(g_run_type == 0){ printf("GPIO 1-2.\r\n"); }else if(g_run_type == 1){ printf("GPIO 1.\r\n"); }else if(g_run_type == 2){ printf("GPIO 2.\r\n"); }else if(g_run_type == 3){ printf("8152 PWM-128.\r\n"); }else if(g_run_type == 4){ printf("8152 1-2.\r\n"); }else if(g_run_type == 5){ printf("8152 2.\r\n"); }else if(g_run_type == 6){ printf("8152 PWM-64.\r\n"); }else if(g_run_type == 7){ printf("8152 PWM-32.\r\n"); }else if(g_run_type == 8){ printf("8152 PWM-16.\r\n"); }else if(g_run_type == 9){ printf("8152 PWM-8.\r\n"); }else if(g_run_type == 10){ printf("8152 PWM-4.\r\n"); }else{ printf("Type error!!\r\n"); } } void set_motor_freq(uint32_t freq)//第一次启动频率 { g_freq = freq; if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ printf("Type GPIO.\r\n"); printf("g_freq: %d HZ\r\n",g_freq); printf("g_duty: %d us\r\n",g_duty); }else if(g_run_type == 3 || g_run_type > 5){ printf("Type 8152 : PWM.\r\n"); switch(freq){ case 0: printf("Freq:100.\r\n"); g_freq_div = 0; g_freq_sel = 16; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 1: printf("Freq:213.\r\n"); g_freq_div = 3; g_freq_sel = 0; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 2: printf("Freq:341.\r\n"); g_freq_div = 0; g_freq_sel = 4; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 3: printf("Freq:427.\r\n"); g_freq_div = 2; g_freq_sel = 0; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 4: printf("Freq:568.\r\n"); g_freq_div = 0; g_freq_sel = 2; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 5: printf("Freq:854.\r\n"); g_freq_div = 1; g_freq_sel = 0; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; default: printf("PWM:error!!\r\n"); break; } }else if(g_run_type == 4 || g_run_type == 5){ printf("Type 8152 : 1-2 & 2.\r\n"); switch(freq){ case 0: printf("Freq:100.\r\n"); g_freq_div = 6; g_freq_sel = 16; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 1: printf("Freq:213.\r\n"); g_freq_div = 5; g_freq_sel = 15; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 2: printf("Freq:341.\r\n"); g_freq_div = 4; g_freq_sel = 19; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 3: printf("Freq:427.\r\n"); g_freq_div = 4; g_freq_sel = 26; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 4: printf("Freq:568.\r\n"); g_freq_div = 4; g_freq_sel = 11; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; case 5: printf("Freq:854.\r\n"); g_freq_div = 2; g_freq_sel = 31; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); break; default: printf("freq error!!\r\n"); break; } }else{ printf("Type error!!\r\n"); } } void set_motor_freq_2(uint32_t freq)//更改后的频率 { if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ printf("Type GPIO.\r\n"); g_freq_2 = freq; printf("g_freq: %d HZ\r\n",g_freq_2); }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5 || g_run_type > 5){ printf("Type 8152.\r\n"); g_freq_div = freq >> 5; g_freq_sel = freq & 0x1F; printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); } } void set_motor_step(uint32_t t_step)//启动时的步长 { g_step = t_step; g_duty = 1000000/g_freq; step_cnt = 0; } void set_motor_step_2(uint32_t t_step)//更改后的步长 { g_step_2 = t_step; printf("g_step_2: %d \r\n",g_step_2); } void set_motor_start() { uint8_t temp_frq_div,temp_step; if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2)//驱动四相电机时 { print_motor();//输出电机各个状态 while(g_step){//当剩余步数不为0时循环 if(g_run_type == 0){ motor_gpio_run_1_2();//1-2相驱动运行方式 motor_step_count(8);//每步计数增加8(半步模式) }else if(g_run_type == 1)//1相驱动运行方式 { motor_gpio_run_1(); motor_step_count(4);//每步计数增加4(全步模式) }else if(g_run_type == 2)//2相驱动运行方式 { motor_gpio_run_2(); motor_step_count(4);//每步计数增加4(全步模式) } delay_us(g_duty);//阻塞延时,控制步进间隔(决定电机速度) //每128步喂一次看门狗(防止系统死机) if(g_step%128 == 0){ WDT_Restart(); } g_step--;//步数减一 step_cnt++;//运行步数计数器加一 //到达指定位置后切换到第二速度 if(g_step_2 && step_cnt>g_step_2){ g_duty = 1000000/g_freq_2;//更新延时时间=1秒/目标频率 } } motor_gpio_stop();//循环结束后停止电机 }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5 || g_run_type > 5){ //enable 使能 motor_spi_write(0x02,0x03); motor_spi_write(0x02,0x83); //clear now step 清零当前圈数 motor_spi_write(0x18,0x00);//CH34CYCNT0 1.25mm motor_spi_write(0x19,0x00);//CH34CYCNT1 motor_spi_write(0x08,0x00);//CH12CYCNT0 1.5mm motor_spi_write(0x09,0x00);//CH12CYCNT1 //set freq div 设定分频 temp_frq_div = g_freq_div<<5 | g_freq_sel; printf("temp_frq_div: %d .\r\n",temp_frq_div); motor_spi_write(0x16,temp_frq_div);//CH34 motor_spi_write(0x06,temp_frq_div);//CH12 //set step 设定步数 if(g_direct){//将16位步进值 g_step 拆分为两个8位字节,同时写入两组电机驱动寄存器实现多电机同步控制 temp_step = g_step & 0xFF;//使用位掩码提取 g_step 的低8位 printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8;//提取高8位 printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } //set phase 设定相位 motor_spi_write(0x1A,0x00);//34 motor_spi_write(0x0A,0x00);//12 if(g_run_type == 5){ motor_spi_write(0x1A,0x80);//34 motor_spi_write(0x0A,0x80);//12 motor_spi_write(0x12,0x10);//34 motor_spi_write(0x0F,0x10);//12 } //set channel config 设定通道配置 if(g_run_type == 3 || g_run_type > 5){ motor_spi_write(0x14,0x07);//手动PWM CH34 motor_spi_write(0x04,0x07);//CH12 }else if(g_run_type == 4){ motor_spi_write(0x14,0x02);//1-2 CH34 motor_spi_write(0x04,0x02);//CH12 }else if(g_run_type == 5){ motor_spi_write(0x14,0x03);//2相 CH34 motor_spi_write(0x04,0x03);//CH12 } //set micro step 设定细分控制及方向 if(g_direct){ switch(g_run_type){ case 3: motor_spi_write(0x15,0x75);//128细分 CH34 motor_spi_write(0x05,0x75);//128细分 CH12 printf("PWM-128-CW.\r\n"); break; case 6: motor_spi_write(0x15,0x65);//64细分 motor_spi_write(0x05,0x65);//64细分 printf("PWM-64-CW.\r\n"); break; case 7: motor_spi_write(0x15,0x55);//32细分 motor_spi_write(0x05,0x55);//32细分 printf("PWM-32-CW.\r\n"); break; case 8: motor_spi_write(0x15,0x45);//16细分 motor_spi_write(0x05,0x45);//16细分 printf("PWM-16-CW.\r\n"); break; case 9: motor_spi_write(0x15,0x35);//8细分 motor_spi_write(0x05,0x35);//8细分 printf("PWM-8-CW.\r\n"); break; case 10: motor_spi_write(0x15,0x25);//4细分 motor_spi_write(0x05,0x25);//4细分 printf("PWM-4-CW.\r\n"); break; } //motor_spi_write(0x15,0x75);//128细分 CH34 //motor_spi_write(0x15,0x65);//64细分 //motor_spi_write(0x15,0x55);//32细分 //motor_spi_write(0x15,0x45);//16细分 //motor_spi_write(0x15,0x35);//8细分 //motor_spi_write(0x15,0x25);//4细分 //motor_spi_write(0x15,0x15);//2细分 //motor_spi_write(0x05,0x75);//128细分 CH12 //motor_spi_write(0x05,0x65);//64细分 //motor_spi_write(0x05,0x55);//32细分 //motor_spi_write(0x05,0x45);//16细分 //motor_spi_write(0x05,0x35);//8细分 //motor_spi_write(0x05,0x25);//4细分 //motor_spi_write(0x05,0x15);//2细分 if(g_run_type == 4 || g_run_type == 5){ motor_spi_write(0x15,0x85);// CH34 motor_spi_write(0x05,0x85);// CH12 } }else{ switch(g_run_type){ case 3: motor_spi_write(0x15,0x7A);//128细分 CH34 motor_spi_write(0x05,0x7A);//128细分 CH12 printf("PWM-128-CCW.\r\n"); break; case 6: motor_spi_write(0x15,0x6A);//64细分 motor_spi_write(0x05,0x6A);//64细分 printf("PWM-64-CCW.\r\n"); break; case 7: motor_spi_write(0x15,0x5A);//32细分 motor_spi_write(0x05,0x5A);//32细分 printf("PWM-32-CCW.\r\n"); break; case 8: motor_spi_write(0x15,0x4A);//16细分 motor_spi_write(0x05,0x4A);//16细分 printf("PWM-16-CCW.\r\n"); break; case 9: motor_spi_write(0x15,0x3A);//8细分 motor_spi_write(0x05,0x3A);//8细分 printf("PWM-8-CCW.\r\n"); break; case 10: motor_spi_write(0x15,0x2A);//4细分 motor_spi_write(0x05,0x2A);//4细分 printf("PWM-4-CCW.\r\n"); break; } //motor_spi_write(0x15,0x7A);//128细分 CH34 //motor_spi_write(0x15,0x6A);//64细分 //motor_spi_write(0x15,0x5A);//32细分 //motor_spi_write(0x15,0x4A);//16细分 //motor_spi_write(0x15,0x3A);//8细分 //motor_spi_write(0x15,0x2A);//4细分 //motor_spi_write(0x15,0x1A);//2细分 //motor_spi_write(0x05,0x7A);//128细分 CH12 //motor_spi_write(0x05,0x6A);//64细分 //motor_spi_write(0x05,0x5A);//32细分 //motor_spi_write(0x05,0x4A);//16细分 //motor_spi_write(0x05,0x3A);//8细分 //motor_spi_write(0x05,0x2A);//4细分 //motor_spi_write(0x05,0x1A);//2细分 if(g_run_type == 4 || g_run_type == 5){ motor_spi_write(0x15,0x8A);//CH34 motor_spi_write(0x05,0x8A);//CH12 } } //set channel enable if(g_run_type == 3 || g_run_type > 5){ motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 }else if(g_run_type == 4){ motor_spi_write(0x14,0x82);//1-2相 CH34 motor_spi_write(0x04,0x82);//CH12 }else if(g_run_type == 5){ motor_spi_write(0x14,0x83);//2相 CH34 motor_spi_write(0x04,0x83);//CH12 } //set enable motor_spi_write(0x02,0x89); } } void motor_button_CW(){ set_motor_run_type(4); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(700); set_motor_start(); /* u32 temp_step; g_step = 1200; if(g_direct){ temp_step = g_step & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 motor_spi_write(0x02,0x89);*/ } void motor_button_CCW(){ set_motor_run_type(4); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(700); set_motor_start(); /*u32 temp_step; g_step = 1200 ; if(g_direct){ temp_step = g_step & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 motor_spi_write(0x02,0x89);*/ } void motor_circ_1_CW(){//正转一圈 set_motor_run_type(3); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(10); set_motor_start(); } void motor_circ_10_CW(){//正转10圈 set_motor_run_type(3); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(100); set_motor_start(); } void motor_circ_1_CCW(){//反转1圈 set_motor_run_type(3); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(10); set_motor_start(); } void motor_circ_10_CCW(){//反转10圈 set_motor_run_type(3); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(100); set_motor_start(); } void motor_button_start(){ int key_con_0=0; int key_con_1=0; while(1){ key_con_0=std_gpio_readpin(KEY_PORT,KEY_PIN); delay_ms(50); key_con_1=std_gpio_readpin(KEY_PORT,KEY_PIN); if(key_con_0 == 0 & key_con_1== 1 ){ motor_button_CW();//shunshizhen } else if(key_con_0 == 1 & key_con_1== 0 ){ motor_button_CCW();//nishizhen } WDT_Restart(); } } void motor_button_start_circ(){ int key_con_0=0;//第一次按键状态的值 int key_con_1=0;//50ms后按键的值 int i_circ; int j_circ; while(1){ key_con_0=std_gpio_readpin(KEY_PORT,KEY_PIN);//读取按键的状态 delay_ms(50);//50ms消抖 key_con_1=std_gpio_readpin(KEY_PORT,KEY_PIN);//再读取一次 if(key_con_0 == 0 & key_con_1== 1 )//检测按键释放(按下->释放) { j_circ=200;//200此循环 while(j_circ){ i_circ=10; while(i_circ){ motor_circ_1_CCW();//逆时针旋转一圈 delay_ms(500); i_circ--; WDT_Restart(); } motor_circ_10_CCW(); delay_ms(2000); j_circ--; } } else if(key_con_0 == 1 & key_con_1== 0 ){ j_circ=200; while(j_circ){ i_circ=10; while(i_circ){ motor_circ_1_CW(); delay_ms(500); i_circ--; WDT_Restart(); } motor_circ_10_CW(); delay_ms(2000); j_circ--; } } WDT_Restart(); } } int my_convert_str_to_u32(u8 *str,u8 length) { u8 cnt; u32 number; number=0; for(cnt=0;cnt<length;cnt++){ if('0'<=str[cnt]&&'9'>=str[cnt]){ number=number*10+(str[cnt]-'0'); }else{ return -1; } } return number; } static int motor_debug_handl(const uint8_t * name,uint8_t * cmd,int cmd_length) { int num,result; int addr,data; if(strcmp(name,TYPE_CMD)==0){//设置电机运行类型 num = my_convert_str_to_u32(cmd,cmd_length);//比较字符串是不是关键词 set_motor_run_type(num);//具体指令 }else if(strcmp(name,DIRECT_CMD)==0){//设置电机方向 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_direct(num); }else if(strcmp(name,FREQ_CMD)==0){//设置电机频率 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_freq(num); }else if(strcmp(name,STEP_CMD)==0){//设置电机步数 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_step(num); }else if(strcmp(name,FREQ_2_CMD)==0){//当为四相电机,设置电机频率2 if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ num = my_convert_str_to_u32(cmd,cmd_length); set_motor_freq_2(num); }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5){//当为8152时 result=sscanf(cmd,"%d,%d",&addr,&data); printf("Type 8152.\r\n"); g_freq_div = addr;//设置频率分频值 g_freq_sel = data;//设置频率选择值 printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); } }else if(strcmp(name,STEP_2_CMD)==0){//设置二级步数 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_step_2(num); }else if(strcmp(name,START_CMD)==0){//启动电机 set_motor_start(); }else if(strcmp(name,MOTOR_WRITE_CMD)==0){ result=sscanf(cmd,"%d,%d",&addr,&data); printf("[WRITE]addr: 0x%x , data: 0x%x\r\n",addr,data); if(result!=2){ printf("Wrong data format!\r\n"); }else{ motor_spi_write(addr,data);//写入SPI data = motor_spi_read(addr);//读取SPI printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } }else if(strcmp(name,MOTOR_READ_CMD)==0){ result=sscanf(cmd,"%d",&addr);//SPI寄存器读取操作 if(result!=1){ printf("Wrong data format!\r\n"); }else{ data = motor_spi_read(addr);//读取指令 printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } }else if(strcmp(name,SPI_DEBUG_CMD)==0){ result=sscanf(cmd,"%d",&data); spi_debug_flag = data;//开启关闭SPI调试模式 if(spi_debug_flag){ printf("Spi debug on!\r\n"); }else{ printf("Spi debug off!\r\n"); } }else { // 处理未知命令 printf("Unknown command: %s\n", name); return -1; // 返回错误码 } return 0; // 成功执行 } // 明确定义结构体(根据初始化器推断成员) struct debug_cmd_info { int cmd; // 根据 TYPE_CMD 等推断为 int 类型 const char *help; // 初始化为 NULL void (*parse)(void); // 函数指针 }; // 再声明数组 struct debug_cmd_info motor_cmd[]= { { .cmd=TYPE_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=DIRECT_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=FREQ_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=STEP_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=FREQ_2_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=STEP_2_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=MOTOR_WRITE_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=MOTOR_READ_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=START_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=SPI_DEBUG_CMD, .help=NULL, .parse=motor_debug_handl, }, }; static PT_THREAD (motor_thread(struct pt *pt)) { // 静态变量,用于保存电机动作信息(当前被注释) static struct motor_action_info motor_action_info; // PT线程开始点(必需的) PT_BEGIN(pt); // 从队列读取电机指令的部分(当前被注释) // while(read_queue(motor_action_queue,(u8*)&motor_action_info)==QUEUE_TRUE){ // if(motor_action_info.action_type == 1){ // // 处理特定电机动作 // } // } // 设置7个时间单位的超时定时器 v_timer_set_time_out(&motor_main_timer,7); // 电机控制主循环(无限循环) while(1){ // 关键点:等待直到定时器超时 // 此处线程会让出CPU,直到条件满足 PT_WAIT_UNTIL(pt,v_timer_time_out(&motor_main_timer,1)); // 记录当前步数 printf("step: %d \r\n",step); // 根据全局运行类型变量执行不同操作 if(g_run_type == 0){ motor_gpio_run_1_2(); motor_step_count(8); }else if(g_run_type == 1){ motor_gpio_run_1(); motor_step_count(4); }else if(g_run_type == 2){ motor_gpio_run_2(); motor_step_count(4); } } // Protothread结束点(必需的) PT_END(pt); } static PT_THREAD (motor_thread_2(struct pt *pt)) { static struct motor_action_info motor_action_info; PT_BEGIN(pt); //set_motor_step(4096); PT_END(pt); } void motor_init() { uint8_t init_addr,init_data; PORT_Init(MOTOR1_PORT,MOTOR1_PIN,OUTPUT); PORT_Init(MOTOR2_PORT,MOTOR2_PIN,OUTPUT); PORT_Init(MOTOR3_PORT,MOTOR3_PIN,OUTPUT); PORT_Init(MOTOR4_PORT,MOTOR4_PIN,OUTPUT); PORT_Init(MOTOR5_PORT,MOTOR5_PIN,OUTPUT); PORT_Init(MOTOR6_PORT,MOTOR6_PIN,OUTPUT); PORT_Init(MOTOR7_PORT,MOTOR7_PIN,OUTPUT); PORT_Init(MOTOR8_PORT,MOTOR8_PIN,OUTPUT); motor_gpio_stop(); PORT_Init(MOTOR_EN_PORT,MOTOR_EN_PIN,OUTPUT); PORT_Init(MOTOR_SPI_CS_PORT,MOTOR_SPI_CS_PIN,OUTPUT); PORT_Init(MOTOR_SPI_CLK_PORT,MOTOR_SPI_CLK_PIN,OUTPUT); PORT_Init(MOTOR_SPI_MOSI_PORT,MOTOR_SPI_MOSI_PIN,OUTPUT); PORT_Init(MOTOR_SPI_MISO_PORT,MOTOR_SPI_MISO_PIN,INPUT); std_gpio_writepin(MOTOR_EN_PORT,MOTOR_EN_PIN,1); init_addr= 0x00; init_data = motor_spi_read(init_addr); if(init_data == 0x81){ printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); init_addr= 0x01; init_data = motor_spi_read(init_addr); if(init_data == 0x50){ printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); printf("TMI8152 INIT SUCCESS!!\r\n"); }else{ printf("TMI8152 INIT FAILED!!\r\n"); printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); } }else{ printf("TMI8152 INIT FAILED!!\r\n"); printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); } //debug_regist_cmd(motor_cmd,ARRAY_SIZE(motor_cmd)); } void motor_task() { //PT_SCHEDULE(motor_thread_2(&motor_pt)); } 帮我检查一下,并把这段代码记录下来
09-26
#include “BAT32G135.h” #include “gpio.h” #include “wdt.h” #include “motor.h” #include “stdio.h” #include “intp.h” #include “global_config.h” #include “pt.h” #include “v_timer.h” #include “string.h” #define TYPE_CMD “type=” #define DIRECT_CMD “direct=” #define FREQ_CMD “freq=” #define FREQ_2_CMD “freq2=” #define STEP_CMD “step=” #define STEP_2_CMD “step2=” #define START_CMD “start” #define SPI_DEBUG_CMD “spi_debug=” #define MOTOR_WRITE_CMD “write=” #define MOTOR_READ_CMD “read=” struct queue *motor_action_queue; struct motor_action_info { uint8_t action_type; uint32_t fre; }; struct pt motor_pt; extern struct v_timer motor_main_timer; uint8_t spi_debug_flag; uint32_t step = 1000; uint32_t step_cnt = 0; uint8_t g_run_type = 5; uint8_t g_direct = 0; uint32_t g_freq = 500; uint32_t g_freq_2 = 1700; uint32_t g_freq_div = 0; uint32_t g_freq_sel = 0; uint32_t g_duty = 1000000/500; uint32_t g_step = 0; uint32_t g_step_2 = 0; //微秒级的延时 void delay_us(uint32_t delay_us) { volatile unsigned int num; volatile unsigned int t; for (num = 0; num < delay_us; num++) { t = 11; while (t != 0) { t–; } } } //毫秒级的延时 void delay_ms(uint16_t delay_ms) { volatile unsigned int num; for (num = 0; num < delay_ms; num++) { delay_us(1000); } } // 使用标准库实现的引脚控制函数 void std_gpio_writepin(PORT_TypeDef PORTx, uint16_t GPIO_Pin, uint8_t pinstate) { // 根据状态选择设置或清除操作 if(pinstate) { // 设置引脚高电平 PORT_SetBit(PORTx, GPIO_Pin); // 使用已有接口 // 或者直接操作: GPIO_Set_Value(port_reg, GPIO_Get_Value(port_reg) | GPIO_Pin); } else { // 设置引脚低电平 PORT_ClrBit(PORTx, GPIO_Pin); // 使用已有接口 // 或者直接操作: GPIO_Set_Value(port_reg, GPIO_Get_Value(port_reg) & ~GPIO_Pin); } } uint8_t std_gpio_readpin(PORT_TypeDef PORTx, uint16_t GPIO_Pin) { // 参数合法性检查 uint8_t PORT_MAX=14; if(PORTx >= PORT_MAX || GPIO_Pin == 0) { return 0; // 无效参数返回0 } // 使用PORT_GetBit直接读取引脚状态 return PORT_GetBit(PORTx, (PIN_TypeDef)GPIO_Pin); } // 修改后的 motor_1parse_run 函数 void motor_1parse_run(uint8_t line_1, uint8_t line_2, uint8_t line_3, uint8_t line_4) { std_gpio_writepin(MOTOR1_PORT, MOTOR1_PIN, line_1); std_gpio_writepin(MOTOR2_PORT, MOTOR2_PIN, line_2); std_gpio_writepin(MOTOR3_PORT, MOTOR3_PIN, line_3); std_gpio_writepin(MOTOR4_PORT, MOTOR4_PIN, line_4); } void motor_2parse_run(uint8_t line_5, uint8_t line_6, uint8_t line_7, uint8_t line_8) { std_gpio_writepin(MOTOR5_PORT, MOTOR5_PIN, line_5);//motor还没定义 std_gpio_writepin(MOTOR6_PORT, MOTOR6_PIN, line_6); std_gpio_writepin(MOTOR7_PORT, MOTOR7_PIN, line_7); std_gpio_writepin(MOTOR8_PORT, MOTOR8_PIN, line_8); } void motor_gpio_stop() { motor_1parse_run(0,0,0,0); motor_2parse_run(0,0,0,0); } void motor_gpio_run_1_2() { switch(step){ case 0: motor_1parse_run(0,0,0,1); break; case 1: motor_1parse_run(1,0,0,1); break; case 2: motor_1parse_run(1,0,0,0); break; case 3: motor_1parse_run(1,1,0,0); break; case 4: motor_1parse_run(0,1,0,0); break; case 5: motor_1parse_run(0,1,1,0); break; case 6: motor_1parse_run(0,0,1,0); break; case 7: motor_1parse_run(0,0,1,1); break; case 8: motor_1parse_run(0,0,0,0); break; } } void motor_gpio_run_1() { switch(step){ case 0: motor_1parse_run(1,0,0,0); break; case 1: motor_1parse_run(0,1,0,0); break; case 2: motor_1parse_run(0,0,1,0); break; case 3: motor_1parse_run(0,0,0,1); break; } } void motor_gpio_run_2() { switch(step){ case 0: motor_1parse_run(1,1,0,0); break; case 1: motor_1parse_run(0,1,1,0); break; case 2: motor_1parse_run(0,0,1,1); break; case 3: motor_1parse_run(1,0,0,1); break; } } #define MOTOR_RUN_SPI_CS(out) std_gpio_writepin(MOTOR_SPI_CS_PORT,MOTOR_SPI_CS_PIN,out)//spi直接写入值 #define MOTOR_RUN_SPI_CLK(out) std_gpio_writepin(MOTOR_SPI_CLK_PORT,MOTOR_SPI_CLK_PIN,out) #define MOTOR_RUN_SPI_MOSI(out) std_gpio_writepin(MOTOR_SPI_MOSI_PORT,MOTOR_SPI_MOSI_PIN,out) #define MOTOR_RUN_SPI_MISO std_gpio_readpin(MOTOR_SPI_MISO_PORT,MOTOR_SPI_MOSI_PIN) void spi_write(uint8_t DDATA, uint8_t Delay_Cnt)//带延时的SPI数据输入 { uint8_t S_DATA, j; uint8_t B_DATA; S_DATA = DDATA; B_DATA = (S_DATA & 0x80) ? 1 : 0;//三元运算符确保 B_DATA 的值始终为 0 或 1 for(j = 0; j < 8; j++) { MOTOR_RUN_SPI_MOSI(B_DATA); //设置 MOSI 为当前最高位 delay_ms(Delay_Cnt); //时钟建立时间(数据稳定) MOTOR_RUN_SPI_CLK(1); //时钟上升沿(数据采样点) delay_ms(Delay_Cnt*2); MOTOR_RUN_SPI_CLK(0); //时钟下降沿 delay_ms(Delay_Cnt); S_DATA = S_DATA << 1; B_DATA = S_DATA & 0X80; } if(Delay_Cnt > 20){ delay_ms(Delay_Cnt-20); }else{ delay_ms(Delay_Cnt); } MOTOR_RUN_SPI_MOSI(0); } uint8_t spi_read(uint8_t Delay_Cnt)//带延时SPI读取 { uint8_t R_DATA, j; MOTOR_RUN_SPI_MOSI(0); for(j = 0; j < 8; j++) { MOTOR_RUN_SPI_CLK(1); //????? delay_us(Delay_Cnt); R_DATA = R_DATA << 1; if(MOTOR_RUN_SPI_MISO == 1) //?????? { R_DATA = R_DATA | 0x01; } else { R_DATA = R_DATA & 0xFE; } delay_us(Delay_Cnt); MOTOR_RUN_SPI_CLK(0); //????? delay_us(Delay_Cnt*2); } return R_DATA; } uint8_t motor_spi_read(uint8_t addr)//SPI读取电机寄存器的值 { uint8_t data; // 初始化 SPI 总线状态 MOTOR_RUN_SPI_CLK(0); // 设置时钟线低电平(SPI 空闲状态) MOTOR_RUN_SPI_CS(0); MOTOR_RUN_SPI_CS(0); // 拉低片选信号(选中设备) delay_ms(5); delay_ms(5); // 设备初始化延时(5ms 确保设备就绪) // 发送要读取的寄存器地址 spi_write(addr, 50); // 调用写函数发送地址(50μs/位时序) delay_us(20); // 设备响应延时(20μs 准备数据) // 读取寄存器数据 data = spi_read(50); // 调用读函数获取数据(50μs/位时序) // 结束通信 MOTOR_RUN_SPI_CS(1); // 拉高片选信号(取消选中设备) MOTOR_RUN_SPI_CLK(0); // 时钟线回到低电平(空闲状态) if(spi_debug_flag){ printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } return data; } void motor_spi_write(uint8_t addr,uint8_t data)//SPI写入电机寄存器的值 { if(spi_debug_flag){ printf(“[WRITE]addr: 0x%x , data: 0x%x\r\n”,addr,data); } addr |= 0x80; MOTOR_RUN_SPI_CLK(0); MOTOR_RUN_SPI_CS(0); delay_ms(5); spi_write(addr, 50); delay_us(20); spi_write(data, 50); MOTOR_RUN_SPI_CS(1); MOTOR_RUN_SPI_CLK(0); #if 0 data = motor_spi_read(addr); #endif } void set_motor_direct(uint8_t direct)//电机转向控制,0顺时针,1逆时针 { g_direct = direct; printf(“g_direct: %d \r\n”,g_direct); } void motor_step_count(uint8_t parse)//STEP计数器 { if(g_direct){ step++; step = step%parse; }else{ step = step + parse; step–; step = step%parse; } } void print_motor()//输出电机各状态 { printf(“g_run_type: %d \r\n”,g_run_type); printf(“g_direct: %d \r\n”,g_direct); printf(“g_freq: %d HZ\r\n”,g_freq); printf(“g_freq_2: %d HZ\r\n”,g_freq_2); printf(“g_duty: %d us\r\n”,g_duty); printf(“g_step: %d \r\n”,g_step); printf(“g_step_2: %d \r\n”,g_step_2); } void set_motor_run_type(uint8_t run_type)//选择电机运行模式,分别对应1-2相驱动、1相驱动、2相驱动。 { g_run_type = run_type; printf(“g_run_type: %d \r\n”,g_run_type); if(g_run_type == 0){ printf("GPIO 1-2.\r\n"); }else if(g_run_type == 1){ printf("GPIO 1.\r\n"); }else if(g_run_type == 2){ printf("GPIO 2.\r\n"); }else if(g_run_type == 3){ printf("8152 PWM-128.\r\n"); }else if(g_run_type == 4){ printf("8152 1-2.\r\n"); }else if(g_run_type == 5){ printf("8152 2.\r\n"); }else if(g_run_type == 6){ printf("8152 PWM-64.\r\n"); }else if(g_run_type == 7){ printf("8152 PWM-32.\r\n"); }else if(g_run_type == 8){ printf("8152 PWM-16.\r\n"); }else if(g_run_type == 9){ printf("8152 PWM-8.\r\n"); }else if(g_run_type == 10){ printf("8152 PWM-4.\r\n"); }else{ printf("Type error!!\r\n"); } } void set_motor_freq(uint32_t freq)//第一次启动频率 { g_freq = freq; if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ printf(“Type GPIO.\r\n”); printf(“g_freq: %d HZ\r\n”,g_freq); printf(“g_duty: %d us\r\n”,g_duty); }else if(g_run_type == 3 || g_run_type > 5){ printf(“Type 8152 : PWM.\r\n”); switch(freq){ case 0: printf(“Freq:100.\r\n”); g_freq_div = 0; g_freq_sel = 16; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 1: printf(“Freq:213.\r\n”); g_freq_div = 3; g_freq_sel = 0; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 2: printf(“Freq:341.\r\n”); g_freq_div = 0; g_freq_sel = 4; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 3: printf(“Freq:427.\r\n”); g_freq_div = 2; g_freq_sel = 0; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 4: printf(“Freq:568.\r\n”); g_freq_div = 0; g_freq_sel = 2; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 5: printf(“Freq:854.\r\n”); g_freq_div = 1; g_freq_sel = 0; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; default: printf(“PWM:error!!\r\n”); break; } }else if(g_run_type == 4 || g_run_type == 5){ printf(“Type 8152 : 1-2 & 2.\r\n”); switch(freq){ case 0: printf(“Freq:100.\r\n”); g_freq_div = 6; g_freq_sel = 16; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 1: printf(“Freq:213.\r\n”); g_freq_div = 5; g_freq_sel = 15; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 2: printf(“Freq:341.\r\n”); g_freq_div = 4; g_freq_sel = 19; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 3: printf(“Freq:427.\r\n”); g_freq_div = 4; g_freq_sel = 26; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 4: printf(“Freq:568.\r\n”); g_freq_div = 4; g_freq_sel = 11; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; case 5: printf(“Freq:854.\r\n”); g_freq_div = 2; g_freq_sel = 31; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); break; default: printf(“freq error!!\r\n”); break; } }else{ printf(“Type error!!\r\n”); } } void set_motor_freq_2(uint32_t freq)//更改后的频率 { if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ printf(“Type GPIO.\r\n”); g_freq_2 = freq; printf(“g_freq: %d HZ\r\n”,g_freq_2); }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5 || g_run_type > 5){ printf(“Type 8152.\r\n”); g_freq_div = freq >> 5; g_freq_sel = freq & 0x1F; printf(“g_freq_div: %d , g_freq_sel: %d .\r\n”,g_freq_div,g_freq_sel); } } void set_motor_step(uint32_t t_step)//启动时的步长 { g_step = t_step; g_duty = 1000000/g_freq; step_cnt = 0; } void set_motor_step_2(uint32_t t_step)//更改后的步长 { g_step_2 = t_step; printf(“g_step_2: %d \r\n”,g_step_2); } void set_motor_start() { uint8_t temp_frq_div,temp_step; if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2)//驱动四相电机时 { print_motor();//输出电机各个状态 while(g_step){//当剩余步数不为0时循环 if(g_run_type == 0){ motor_gpio_run_1_2();//1-2相驱动运行方式 motor_step_count(8);//每步计数增加8(半步模式) }else if(g_run_type == 1)//1相驱动运行方式 { motor_gpio_run_1(); motor_step_count(4);//每步计数增加4(全步模式) }else if(g_run_type == 2)//2相驱动运行方式 { motor_gpio_run_2(); motor_step_count(4);//每步计数增加4(全步模式) } delay_us(g_duty);//阻塞延时,控制步进间隔(决定电机速度) //每128步喂一次看门狗(防止系统死机) if(g_step%128 == 0){ WDT_Restart(); } g_step--;//步数减一 step_cnt++;//运行步数计数器加一 //到达指定位置后切换到第二速度 if(g_step_2 && step_cnt>g_step_2){ g_duty = 1000000/g_freq_2;//更新延时时间=1秒/目标频率 } } motor_gpio_stop();//循环结束后停止电机 }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5 || g_run_type > 5){ //enable 使能 motor_spi_write(0x02,0x03); motor_spi_write(0x02,0x83); //clear now step 清零当前圈数 motor_spi_write(0x18,0x00);//CH34CYCNT0 1.25mm motor_spi_write(0x19,0x00);//CH34CYCNT1 motor_spi_write(0x08,0x00);//CH12CYCNT0 1.5mm motor_spi_write(0x09,0x00);//CH12CYCNT1 //set freq div 设定分频 temp_frq_div = g_freq_div<<5 | g_freq_sel; printf("temp_frq_div: %d .\r\n",temp_frq_div); motor_spi_write(0x16,temp_frq_div);//CH34 motor_spi_write(0x06,temp_frq_div);//CH12 //set step 设定步数 if(g_direct){//将16位步进值 g_step 拆分为两个8位字节,同时写入两组电机驱动寄存器实现多电机同步控制 temp_step = g_step & 0xFF;//使用位掩码提取 g_step 的低8位 printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8;//提取高8位 printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; printf("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } //set phase 设定相位 motor_spi_write(0x1A,0x00);//34 motor_spi_write(0x0A,0x00);//12 if(g_run_type == 5){ motor_spi_write(0x1A,0x80);//34 motor_spi_write(0x0A,0x80);//12 motor_spi_write(0x12,0x10);//34 motor_spi_write(0x0F,0x10);//12 } //set channel config 设定通道配置 if(g_run_type == 3 || g_run_type > 5){ motor_spi_write(0x14,0x07);//手动PWM CH34 motor_spi_write(0x04,0x07);//CH12 }else if(g_run_type == 4){ motor_spi_write(0x14,0x02);//1-2 CH34 motor_spi_write(0x04,0x02);//CH12 }else if(g_run_type == 5){ motor_spi_write(0x14,0x03);//2相 CH34 motor_spi_write(0x04,0x03);//CH12 } //set micro step 设定细分控制及方向 if(g_direct){ switch(g_run_type){ case 3: motor_spi_write(0x15,0x75);//128细分 CH34 motor_spi_write(0x05,0x75);//128细分 CH12 printf("PWM-128-CW.\r\n"); break; case 6: motor_spi_write(0x15,0x65);//64细分 motor_spi_write(0x05,0x65);//64细分 printf("PWM-64-CW.\r\n"); break; case 7: motor_spi_write(0x15,0x55);//32细分 motor_spi_write(0x05,0x55);//32细分 printf("PWM-32-CW.\r\n"); break; case 8: motor_spi_write(0x15,0x45);//16细分 motor_spi_write(0x05,0x45);//16细分 printf("PWM-16-CW.\r\n"); break; case 9: motor_spi_write(0x15,0x35);//8细分 motor_spi_write(0x05,0x35);//8细分 printf("PWM-8-CW.\r\n"); break; case 10: motor_spi_write(0x15,0x25);//4细分 motor_spi_write(0x05,0x25);//4细分 printf("PWM-4-CW.\r\n"); break; } //motor_spi_write(0x15,0x75);//128细分 CH34 //motor_spi_write(0x15,0x65);//64细分 //motor_spi_write(0x15,0x55);//32细分 //motor_spi_write(0x15,0x45);//16细分 //motor_spi_write(0x15,0x35);//8细分 //motor_spi_write(0x15,0x25);//4细分 //motor_spi_write(0x15,0x15);//2细分 //motor_spi_write(0x05,0x75);//128细分 CH12 //motor_spi_write(0x05,0x65);//64细分 //motor_spi_write(0x05,0x55);//32细分 //motor_spi_write(0x05,0x45);//16细分 //motor_spi_write(0x05,0x35);//8细分 //motor_spi_write(0x05,0x25);//4细分 //motor_spi_write(0x05,0x15);//2细分 if(g_run_type == 4 || g_run_type == 5){ motor_spi_write(0x15,0x85);// CH34 motor_spi_write(0x05,0x85);// CH12 } }else{ switch(g_run_type){ case 3: motor_spi_write(0x15,0x7A);//128细分 CH34 motor_spi_write(0x05,0x7A);//128细分 CH12 printf("PWM-128-CCW.\r\n"); break; case 6: motor_spi_write(0x15,0x6A);//64细分 motor_spi_write(0x05,0x6A);//64细分 printf("PWM-64-CCW.\r\n"); break; case 7: motor_spi_write(0x15,0x5A);//32细分 motor_spi_write(0x05,0x5A);//32细分 printf("PWM-32-CCW.\r\n"); break; case 8: motor_spi_write(0x15,0x4A);//16细分 motor_spi_write(0x05,0x4A);//16细分 printf("PWM-16-CCW.\r\n"); break; case 9: motor_spi_write(0x15,0x3A);//8细分 motor_spi_write(0x05,0x3A);//8细分 printf("PWM-8-CCW.\r\n"); break; case 10: motor_spi_write(0x15,0x2A);//4细分 motor_spi_write(0x05,0x2A);//4细分 printf("PWM-4-CCW.\r\n"); break; } //motor_spi_write(0x15,0x7A);//128细分 CH34 //motor_spi_write(0x15,0x6A);//64细分 //motor_spi_write(0x15,0x5A);//32细分 //motor_spi_write(0x15,0x4A);//16细分 //motor_spi_write(0x15,0x3A);//8细分 //motor_spi_write(0x15,0x2A);//4细分 //motor_spi_write(0x15,0x1A);//2细分 //motor_spi_write(0x05,0x7A);//128细分 CH12 //motor_spi_write(0x05,0x6A);//64细分 //motor_spi_write(0x05,0x5A);//32细分 //motor_spi_write(0x05,0x4A);//16细分 //motor_spi_write(0x05,0x3A);//8细分 //motor_spi_write(0x05,0x2A);//4细分 //motor_spi_write(0x05,0x1A);//2细分 if(g_run_type == 4 || g_run_type == 5){ motor_spi_write(0x15,0x8A);//CH34 motor_spi_write(0x05,0x8A);//CH12 } } //set channel enable if(g_run_type == 3 || g_run_type > 5){ motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 }else if(g_run_type == 4){ motor_spi_write(0x14,0x82);//1-2相 CH34 motor_spi_write(0x04,0x82);//CH12 }else if(g_run_type == 5){ motor_spi_write(0x14,0x83);//2相 CH34 motor_spi_write(0x04,0x83);//CH12 } //set enable motor_spi_write(0x02,0x89); } } void motor_button_CW(){ set_motor_run_type(4); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(700); set_motor_start(); /* u32 temp_step; g_step = 1200; if(g_direct){ temp_step = g_step & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 motor_spi_write(0x02,0x89);*/ } void motor_button_CCW(){ set_motor_run_type(4); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(700); set_motor_start(); /*u32 temp_step; g_step = 1200 ; if(g_direct){ temp_step = g_step & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = g_step >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 ++ }else{ temp_step = (8192-g_step) & 0xFF; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1B,temp_step);//CH34 motor_spi_write(0x0B,temp_step);//CH12 temp_step = (8192-g_step) >> 8; log_d("temp_step: %d .\r\n",temp_step); motor_spi_write(0x1C,temp_step);//CH34 motor_spi_write(0x0C,temp_step);//CH12 } motor_spi_write(0x14,0x87);//手动PWM CH34 motor_spi_write(0x04,0x87);//CH12 motor_spi_write(0x02,0x89);*/ } void motor_circ_1_CW(){//正转一圈 set_motor_run_type(3); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(10); set_motor_start(); } void motor_circ_10_CW(){//正转10圈 set_motor_run_type(3); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(100); set_motor_start(); } void motor_circ_1_CCW(){//反转1圈 set_motor_run_type(3); set_motor_direct(1); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(10); set_motor_start(); } void motor_circ_10_CCW(){//反转10圈 set_motor_run_type(3); set_motor_direct(0); set_motor_freq(5); //motor_spi_write(0x16,0x9A);// set_motor_step(100); set_motor_start(); } void motor_button_start(){ int key_con_0=0; int key_con_1=0; while(1){ key_con_0=std_gpio_readpin(KEY_PORT,KEY_PIN); delay_ms(50); key_con_1=std_gpio_readpin(KEY_PORT,KEY_PIN); if(key_con_0 == 0 & key_con_1== 1 ){ motor_button_CW();//shunshizhen } else if(key_con_0 == 1 & key_con_1== 0 ){ motor_button_CCW();//nishizhen } WDT_Restart(); } } void motor_button_start_circ(){ int key_con_0=0;//第一次按键状态的值 int key_con_1=0;//50ms后按键的值 int i_circ; int j_circ; while(1){ key_con_0=std_gpio_readpin(KEY_PORT,KEY_PIN);//读取按键的状态 delay_ms(50);//50ms消抖 key_con_1=std_gpio_readpin(KEY_PORT,KEY_PIN);//再读取一次 if(key_con_0 == 0 & key_con_1== 1 )//检测按键释放(按下->释放) { j_circ=200;//200此循环 while(j_circ){ i_circ=10; while(i_circ){ motor_circ_1_CCW();//逆时针旋转一圈 delay_ms(500); i_circ–; WDT_Restart(); } motor_circ_10_CCW(); delay_ms(2000); j_circ–; } } else if(key_con_0 == 1 & key_con_1== 0 ){ j_circ=200; while(j_circ){ i_circ=10; while(i_circ){ motor_circ_1_CW(); delay_ms(500); i_circ–; WDT_Restart(); } motor_circ_10_CW(); delay_ms(2000); j_circ–; } } WDT_Restart(); } } int my_convert_str_to_u32(u8 *str,u8 length) { u8 cnt; u32 number; number=0; for(cnt=0;cnt<length;cnt++){ if('0'<=str[cnt]&&'9'>=str[cnt]){ number=number*10+(str[cnt]-'0'); }else{ return -1; } } return number; } static int motor_debug_handl(const uint8_t * name,uint8_t * cmd,int cmd_length) { int num,result; int addr,data; if(strcmp(name,TYPE_CMD)==0){//设置电机运行类型 num = my_convert_str_to_u32(cmd,cmd_length);//比较字符串是不是关键词 set_motor_run_type(num);//具体指令 }else if(strcmp(name,DIRECT_CMD)==0){//设置电机方向 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_direct(num); }else if(strcmp(name,FREQ_CMD)==0){//设置电机频率 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_freq(num); }else if(strcmp(name,STEP_CMD)==0){//设置电机步数 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_step(num); }else if(strcmp(name,FREQ_2_CMD)==0){//当为四相电机,设置电机频率2 if(g_run_type == 0 || g_run_type == 1 || g_run_type == 2){ num = my_convert_str_to_u32(cmd,cmd_length); set_motor_freq_2(num); }else if(g_run_type == 3 || g_run_type == 4 || g_run_type == 5){//当为8152时 result=sscanf(cmd,"%d,%d",&addr,&data); printf("Type 8152.\r\n"); g_freq_div = addr;//设置频率分频值 g_freq_sel = data;//设置频率选择值 printf("g_freq_div: %d , g_freq_sel: %d .\r\n",g_freq_div,g_freq_sel); } }else if(strcmp(name,STEP_2_CMD)==0){//设置二级步数 num = my_convert_str_to_u32(cmd,cmd_length); set_motor_step_2(num); }else if(strcmp(name,START_CMD)==0){//启动电机 set_motor_start(); }else if(strcmp(name,MOTOR_WRITE_CMD)==0){ result=sscanf(cmd,"%d,%d",&addr,&data); printf("[WRITE]addr: 0x%x , data: 0x%x\r\n",addr,data); if(result!=2){ printf("Wrong data format!\r\n"); }else{ motor_spi_write(addr,data);//写入SPI data = motor_spi_read(addr);//读取SPI printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } }else if(strcmp(name,MOTOR_READ_CMD)==0){ result=sscanf(cmd,"%d",&addr);//SPI寄存器读取操作 if(result!=1){ printf("Wrong data format!\r\n"); }else{ data = motor_spi_read(addr);//读取指令 printf("[READ]addr: 0x%x , data: 0x%x\r\n",addr,data); } }else if(strcmp(name,SPI_DEBUG_CMD)==0){ result=sscanf(cmd,"%d",&data); spi_debug_flag = data;//开启关闭SPI调试模式 if(spi_debug_flag){ printf("Spi debug on!\r\n"); }else{ printf("Spi debug off!\r\n"); } }else { // 处理未知命令 printf("Unknown command: %s\n", name); return -1; // 返回错误码 } return 0; // 成功执行 } // 明确定义结构体(根据初始化器推断成员) struct debug_cmd_info { int cmd; // 根据 TYPE_CMD 等推断为 int 类型 const char *help; // 初始化为 NULL void (*parse)(void); // 函数指针 }; // 再声明数组 struct debug_cmd_info motor_cmd[]= { { .cmd=TYPE_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=DIRECT_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=FREQ_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=STEP_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=FREQ_2_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=STEP_2_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=MOTOR_WRITE_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=MOTOR_READ_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=START_CMD, .help=NULL, .parse=motor_debug_handl, }, { .cmd=SPI_DEBUG_CMD, .help=NULL, .parse=motor_debug_handl, }, }; static PT_THREAD (motor_thread(struct pt *pt)) { // 静态变量,用于保存电机动作信息(当前被注释) static struct motor_action_info motor_action_info; // PT线程开始点(必需的) PT_BEGIN(pt); // 从队列读取电机指令的部分(当前被注释) // while(read_queue(motor_action_queue,(u8*)&motor_action_info)==QUEUE_TRUE){ // if(motor_action_info.action_type == 1){ // // 处理特定电机动作 // } // } // 设置7个时间单位的超时定时器 v_timer_set_time_out(&motor_main_timer,7); // 电机控制主循环(无限循环) while(1){ // 关键点:等待直到定时器超时 // 此处线程会让出CPU,直到条件满足 PT_WAIT_UNTIL(pt,v_timer_time_out(&motor_main_timer,1)); // 记录当前步数 printf("step: %d \r\n",step); // 根据全局运行类型变量执行不同操作 if(g_run_type == 0){ motor_gpio_run_1_2(); motor_step_count(8); }else if(g_run_type == 1){ motor_gpio_run_1(); motor_step_count(4); }else if(g_run_type == 2){ motor_gpio_run_2(); motor_step_count(4); } } // Protothread结束点(必需的) PT_END(pt); } static PT_THREAD (motor_thread_2(struct pt *pt)) { static struct motor_action_info motor_action_info; PT_BEGIN(pt); //set_motor_step(4096); PT_END(pt); } void motor_init() { uint8_t init_addr,init_data; PORT_Init(MOTOR1_PORT,MOTOR1_PIN,OUTPUT); PORT_Init(MOTOR2_PORT,MOTOR2_PIN,OUTPUT); PORT_Init(MOTOR3_PORT,MOTOR3_PIN,OUTPUT); PORT_Init(MOTOR4_PORT,MOTOR4_PIN,OUTPUT); PORT_Init(MOTOR5_PORT,MOTOR5_PIN,OUTPUT); PORT_Init(MOTOR6_PORT,MOTOR6_PIN,OUTPUT); PORT_Init(MOTOR7_PORT,MOTOR7_PIN,OUTPUT); PORT_Init(MOTOR8_PORT,MOTOR8_PIN,OUTPUT); motor_gpio_stop(); PORT_Init(MOTOR_EN_PORT,MOTOR_EN_PIN,OUTPUT); PORT_Init(MOTOR_SPI_CS_PORT,MOTOR_SPI_CS_PIN,OUTPUT); PORT_Init(MOTOR_SPI_CLK_PORT,MOTOR_SPI_CLK_PIN,OUTPUT); PORT_Init(MOTOR_SPI_MOSI_PORT,MOTOR_SPI_MOSI_PIN,OUTPUT); PORT_Init(MOTOR_SPI_MISO_PORT,MOTOR_SPI_MISO_PIN,INPUT); std_gpio_writepin(MOTOR_EN_PORT,MOTOR_EN_PIN,1); init_addr= 0x00; init_data = motor_spi_read(init_addr); if(init_data == 0x81){ printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); init_addr= 0x01; init_data = motor_spi_read(init_addr); if(init_data == 0x50){ printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); printf("TMI8152 INIT SUCCESS!!\r\n"); }else{ printf("TMI8152 INIT FAILED!!\r\n"); printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); } }else{ printf("TMI8152 INIT FAILED!!\r\n"); printf("init_addr: 0x%x , init_data: 0x%x\r\n",init_addr,init_data); } //debug_regist_cmd(motor_cmd,ARRAY_SIZE(motor_cmd)); } void motor_task() { //PT_SCHEDULE(motor_thread_2(&motor_pt)); } 帮我检查一下,并把这段代码记录下来,并取名为motor.c,后续以这个名字进行修改
最新发布
09-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清欢_小铭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值