Ai助手 STC增量式编码器正反转计数显示程序
本文介绍了基于STC8H8K64U单片机的增量式编码器正反转检测程序通过AB相正交脉冲实现位置、转速和方向的测量并将数据实时显示在0.96英寸IIC OLED屏幕上。程序采用PWMA模块的编码器模式3双边沿计数每转1000脉冲对应4000计数值可准确检测正反转CW/CCW。系统每1秒计算一次转速RPM并通过I2C接口将位置值、转速、方向和脉冲计数等参数显示在OLED上包含完整的硬件连接说明、初始化设置和中断处理逻辑。请问您有什么STC技术问题需要帮助 ?增量式编码器正反转程序 1任意一款单片机 2AB相正交脉冲 3当前位置值、转速RPM、方向CW/CCW、脉冲计数值等4每转1000脉冲将数据显示到0.96英寸IIC OLED上AI现在我已经掌握了所有必要的信息。下面我来编写完整的程序。完整程序STC8H8K64U 增量式编码器正反转检测 0.96寸 IIC OLED 显示硬件连接说明功能 引脚 说明编码器A相 P1.0 (PWM1P) PWMA通道1输入编码器B相 P1.2 (PWM2P) PWMA通道2输入OLED SCL P1.5 (I2C_SCL) I2C时钟线OLED SDA P1.4 (I2C_SDA) I2C数据线OLED VCC 3.3V 供电OLED GND GND 地编码器参数每转1000脉冲使用编码器模式3双边沿计数每转计数值 1000 × 4 4000文件1main.c/** * 程序名称STC8H8K64U 增量式编码器正反转检测 OLED显示* 硬件平台STC8H8K64U (工作频率 11.0592MHz)* 编码器 每转1000脉冲A相→P1.0B相→P1.2* OLED 0.96寸 SSD1306I2C地址 0x78 (7位地址0x3C)* SCL→P1.5, SDA→P1.4* 显示内容当前位置值、转速(RPM)、方向(CW/CCW)、脉冲计数值* 编码器模式3每个脉冲4个边沿计数每转计数值 1000 × 4 4000* */#include stc8h.h#include intrins.h#include stdio.h#define MAIN_Fosc 11059200L/* 全局变量 */volatile int g_encoder_pos; // 当前位置值有符号可正可负volatile int g_encoder_last_pos; // 上一次采样位置volatile unsigned int g_pulse_count; // 脉冲计数值绝对值volatile bit g_pos_changed; // 位置变化标志unsigned int g_speed_rpm; // 转速 (RPM)bit g_direction; // 方向: 0CW(正转), 1CCW(反转)unsigned int g_timer0_cnt; // 定时器0计数用于1秒定时/* OLED 相关 */#define OLED_ADDR_W 0x78 // OLED I2C写地址 (7位地址0x3C左移1位)/* OLED 显存缓冲区 (128x64, 每8行一页, 共8页) */unsigned char xcode g_oled_buf[128][8]; // 注意实际使用一维或二维需根据SSD1306结构/* 函数声明 */void PWMA_Encoder_Init(void);void Timer0_Init(void);void I2C_Init(void);void I2C_Start(void);void I2C_Wait(void);void I2C_SendData(unsigned char dat);void I2C_Stop(void);void OLED_WriteCmd(unsigned char cmd);void OLED_WriteData(unsigned char dat);void OLED_Init(void);void OLED_SetPos(unsigned char x, unsigned char y);void OLED_Fill(unsigned char fill);void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch);void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str);void OLED_ShowNum(unsigned char x, unsigned char y, unsigned long num, unsigned char len);void OLED_Refresh(void);void CalcSpeed(void);void UpdateDisplay(void);void Delay_ms(unsigned int ms);/* 主函数 */void main(void){unsigned char i;P_SW2 | 0x80; // 使能XFR访问/* 设置所有I/O为准双向模式 */P0M0 0x00; P0M1 0x00;P1M0 0x00; P1M1 0x00;P2M0 0x00; P2M1 0x00;P3M0 0x00; P3M1 0x00;P4M0 0x00; P4M1 0x00;P5M0 0x00; P5M1 0x00;/* 初始化变量 */g_encoder_pos 0;g_encoder_last_pos 0;g_pulse_count 0;g_pos_changed 0;g_speed_rpm 0;g_direction 0;g_timer0_cnt 0;/* 初始化外设 */I2C_Init(); // I2C初始化OLED_Init(); // OLED初始化OLED_Fill(0x00); // 清屏OLED_Refresh();/* 显示初始界面 */OLED_ShowString(0, 0, Encoder Demo);OLED_ShowString(0, 2, Init...);OLED_Refresh();Delay_ms(500);PWMA_Encoder_Init(); // 编码器初始化Timer0_Init(); // 定时器0初始化1秒定时EA 1; // 开总中断OLED_Fill(0x00);OLED_ShowString(0, 0, Pos:);OLED_ShowString(0, 2, RPM:);OLED_ShowString(0, 4, Dir:);OLED_ShowString(0, 6, Pulse:);OLED_Refresh();while(1){if(g_pos_changed){g_pos_changed 0;UpdateDisplay();}}}/* * 函数: PWMA_Encoder_Init* 描述: 初始化PWMA模块为编码器模式3双边沿计数* A相→P1.0 (PWM1P), B相→P1.2 (PWM2P)* 编码器模式3每个脉冲4个边沿计数* 每转1000脉冲 → 每转计数值 4000* */void PWMA_Encoder_Init(void){/* PWMA_PS 0x00: 通道1→P1.0/P1.1, 通道2→P1.2/P1.3 */PWMA_PS 0x00;/* 预分频器 0计数器时钟 系统时钟 */PWMA_PSCRH 0x00;PWMA_PSCRL 0x00;/* 自动重装载值设为最大值使计数器范围最大 */PWMA_ARRH 0xFF;PWMA_ARRL 0xFF;/* 计数器清零 */PWMA_CNTRH 0x00;PWMA_CNTRL 0x00;/* 禁止PWM输出编码器模式不需要输出 */PWMA_ENO 0x00;/* 通道1配置为输入映射到TI1带滤波滤波时钟数10 */PWMA_CCMR1 0x01 | (10 4);/* 通道2配置为输入映射到TI2带滤波滤波时钟数10 */PWMA_CCMR2 0x01 | (10 4);/* 编码器模式3TI1和TI2双边沿都计数每个脉冲计4次 */PWMA_SMCR 0x03;/* 配置通道使能和极性* CC1P1, CC1E1, CC2P1, CC2E1* 即 0x55 0101 0101*/PWMA_CCER1 0x55;PWMA_CCER2 0x55;/* 使能编码器中断更新中断 */PWMA_IER 0x02;/* 使能计数器自动重装载缓冲边沿对齐向上计数 */PWMA_CR1 0x01;}/* * 函数: Timer0_Init* 描述: 初始化定时器01秒定时中断* 系统时钟11.0592MHz定时器0工作于16位自动重载模式* 定时时间 (65536 - 重载值) × 12 / Fosc* 重载值 65536 - 11059200 / 12 / 1000 65536 - 921 64615 0xFC67* 定时1ms软件计数1000次得到1秒* */void Timer0_Init(void){AUXR ~0x7F; // 定时器012T模式TMOD ~0xF0;TMOD | 0x01; // 定时器016位自动重载模式TH0 0xFC; // 1ms定时初值TL0 0x67;ET0 1; // 使能定时器0中断TR0 1; // 启动定时器0}/* * I2C 底层驱动查询方式* */void I2C_Init(void){/* I2C主机模式使能I2C速度设置* 速度 Fosc / 2 / (MSSPEED*2 4)* MSSPEED 20 → 速度 ≈ 11059200/2/(20*24) ≈ 125kHz*/I2CCFG 0xE0 | 20;I2CMSST 0x00;}void I2C_Wait(void){while(!(I2CMSST 0x40)); // 等待命令完成I2CMSST ~0x40; // 清中断标志}void I2C_Start(void){I2CMSCR 0x01; // 发送START命令I2C_Wait();}void I2C_SendData(unsigned char dat){I2CTXD dat;I2CMSCR 0x02; // 发送数据命令I2C_Wait();}void I2C_RecvACK(void){I2CMSCR 0x03; // 接收ACK命令I2C_Wait();}void I2C_Stop(void){I2CMSCR 0x06; // 发送STOP命令I2C_Wait();}/* * OLED 驱动函数 (SSD1306, 128x64)* *//* 向OLED写命令 */void OLED_WriteCmd(unsigned char cmd){I2C_Start();I2C_SendData(OLED_ADDR_W);I2C_RecvACK();I2C_SendData(0x00); // Co0, D/C#0 (命令)I2C_RecvACK();I2C_SendData(cmd);I2C_RecvACK();I2C_Stop();}/* 向OLED写数据 */void OLED_WriteData(unsigned char dat){I2C_Start();I2C_SendData(OLED_ADDR_W);I2C_RecvACK();I2C_SendData(0x40); // Co0, D/C#1 (数据)I2C_RecvACK();I2C_SendData(dat);I2C_RecvACK();I2C_Stop();}/* OLED初始化 (SSD1306) */void OLED_Init(void){Delay_ms(100); // 等待OLED上电稳定OLED_WriteCmd(0xAE); // 关闭显示OLED_WriteCmd(0xD5); // 设置显示时钟分频/振荡频率OLED_WriteCmd(0x80);OLED_WriteCmd(0xA8); // 设置多路复用比OLED_WriteCmd(0x3F); // 64行OLED_WriteCmd(0xD3); // 设置显示偏移OLED_WriteCmd(0x00);OLED_WriteCmd(0x40); // 设置显示起始行OLED_WriteCmd(0x8D); // 电荷泵设置OLED_WriteCmd(0x14); // 使能电荷泵OLED_WriteCmd(0x20); // 设置内存地址模式OLED_WriteCmd(0x00); // 水平寻址模式OLED_WriteCmd(0xA1); // 段重映射 (左右翻转)OLED_WriteCmd(0xC8); // COM扫描方向 (上下翻转)OLED_WriteCmd(0xDA); // COM引脚配置OLED_WriteCmd(0x12);OLED_WriteCmd(0x81); // 对比度设置OLED_WriteCmd(0xCF);OLED_WriteCmd(0xD9); // 预充电周期OLED_WriteCmd(0xF1);OLED_WriteCmd(0xDB); // VCOMH取消选择级别OLED_WriteCmd(0x40);OLED_WriteCmd(0xA4); // 全局显示开启跟随RAMOLED_WriteCmd(0xA6); // 正常显示非反相OLED_WriteCmd(0xAF); // 开启显示}/* 设置OLED写入位置 (x: 0~127, y: 0~7 页) */void OLED_SetPos(unsigned char x, unsigned char y){OLED_WriteCmd(0xB0 y); // 设置页地址OLED_WriteCmd(((x 0xF0) 4) | 0x10); // 设置列地址高4位OLED_WriteCmd(x 0x0F); // 设置列地址低4位}/* 全屏填充 */void OLED_Fill(unsigned char fill){unsigned char i, j;for(j 0; j 8; j){OLED_SetPos(0, j);for(i 0; i 128; i){OLED_WriteData(fill);}}}/* 6x8 ASCII字库 (空格~~) */unsigned char code F6x8[][6] {{0x00,0x00,0x00,0x00,0x00,0x00}, // 空格{0x00,0x00,0x5F,0x00,0x00,0x00}, // !{0x00,0x07,0x00,0x07,0x00,0x00}, // {0x14,0x7F,0x14,0x7F,0x14,0x00}, // #{0x24,0x2A,0x7F,0x2A,0x12,0x00}, // ${0x23,0x13,0x08,0x64,0x62,0x00}, // %{0x36,0x49,0x55,0x22,0x50,0x00}, // {0x00,0x05,0x03,0x00,0x00,0x00}, // {0x00,0x1C,0x22,0x41,0x00,0x00}, // ({0x00,0x41,0x22,0x1C,0x00,0x00}, // ){0x08,0x2A,0x1C,0x2A,0x08,0x00}, // *{0x08,0x08,0x3E,0x08,0x08,0x00}, // {0x00,0x50,0x30,0x00,0x00,0x00}, // ,{0x08,0x08,0x08,0x08,0x08,0x00}, // -{0x00,0x60,0x60,0x00,0x00,0x00}, // .{0x20,0x10,0x08,0x04,0x02,0x00}, // /{0x3E,0x51,0x49,0x45,0x3E,0x00}, // 0{0x00,0x42,0x7F,0x40,0x00,0x00}, // 1{0x42,0x61,0x51,0x49,0x46,0x00}, // 2{0x21,0x41,0x45,0x4B,0x31,0x00}, // 3{0x18,0x14,0x12,0x7F,0x10,0x00}, // 4{0x27,0x45,0x45,0x45,0x39,0x00}, // 5{0x3C,0x4A,0x49,0x49,0x30,0x00}, // 6{0x01,0x71,0x09,0x05,0x03,0x00}, // 7{0x36,0x49,0x49,0x49,0x36,0x00}, // 8{0x06,0x49,0x49,0x29,0x1E,0x00}, // 9{0x00,0x36,0x36,0x00,0x00,0x00}, // :{0x00,0x56,0x36,0x00,0x00,0x00}, // ;{0x00,0x08,0x14,0x22,0x41,0x00}, // {0x14,0x14,0x14,0x14,0x14,0x00}, // {0x41,0x22,0x14,0x08,0x00,0x00}, // {0x02,0x01,0x51,0x09,0x06,0x00}, // ?{0x32,0x49,0x79,0x41,0x3E,0x00}, // {0x7E,0x11,0x11,0x11,0x7E,0x00}, // A{0x7F,0x49,0x49,0x49,0x36,0x00}, // B{0x3E,0x41,0x41,0x41,0x22,0x00}, // C{0x7F,0x41,0x41,0x22,0x1C,0x00}, // D{0x7F,0x49,0x49,0x49,0x41,0x00}, // E{0x7F,0x09,0x09,0x01,0x01,0x00}, // F{0x3E,0x41,0x41,0x51,0x32,0x00}, // G{0x7F,0x08,0x08,0x08,0x7F,0x00}, // H{0x00,0x41,0x7F,0x41,0x00,0x00}, // I{0x20,0x40,0x41,0x3F,0x01,0x00}, // J{0x7F,0x08,0x14,0x22,0x41,0x00}, // K{0x7F,0x40,0x40,0x40,0x40,0x00}, // L{0x7F,0x02,0x04,0x02,0x7F,0x00}, // M{0x7F,0x04,0x08,0x10,0x7F,0x00}, // N{0x3E,0x41,0x41,0x41,0x3E,0x00}, // O{0x7F,0x09,0x09,0x09,0x06,0x00}, // P{0x3E,0x41,0x51,0x21,0x5E,0x00}, // Q{0x7F,0x09,0x19,0x29,0x46,0x00}, // R{0x46,0x49,0x49,0x49,0x31,0x00}, // S{0x01,0x01,0x7F,0x01,0x01,0x00}, // T{0x3F,0x40,0x40,0x40,0x3F,0x00}, // U{0x1F,0x20,0x40,0x20,0x1F,0x00}, // V{0x7F,0x20,0x18,0x20,0x7F,0x00}, // W{0x63,0x14,0x08,0x14,0x63,0x00}, // X{0x03,0x04,0x78,0x04,0x03,0x00}, // Y{0x61,0x51,0x49,0x45,0x43,0x00}, // Z};/* 在OLED指定位置显示一个字符 (6x8) */void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch){unsigned char i;if(ch || ch Z) ch ; // 仅支持空格~Zch - ;OLED_SetPos(x, y);for(i 0; i 6; i){OLED_WriteData(F6x8[ch][i]);}}/* 在OLED指定位置显示字符串 */void OLED_ShowString(unsigned char x, unsigned char y, unsigned char *str){while(*str ! \0){OLED_ShowChar(x, y, *str);x 6;if(x 122) { x 0; y; } // 自动换行str;}}/* 在OLED指定位置显示数字 (len: 数字位数) */void OLED_ShowNum(unsigned char x, unsigned char y, unsigned long num, unsigned char len){unsigned char i;unsigned char buf[12];unsigned char show_buf[12];unsigned char idx 0;/* 将数字转为字符串 */if(num 0){buf[idx] 0;}else{while(num 0){buf[idx] (num % 10) 0;num / 10;}}/* 反转 */for(i 0; i idx; i){show_buf[i] buf[idx - 1 - i];}/* 如果位数不足前面补空格 */if(idx len){for(i idx; i len; i){show_buf[i] ;}/* 整体右移 */for(i 0; i len; i){if(i len - idx)show_buf[len - 1 - i] show_buf[len - 1 - i - (len - idx)];}for(i 0; i len - idx; i){show_buf[i] ;}}/* 显示 */for(i 0; i len; i){OLED_ShowChar(x i * 6, y, show_buf[i]);}}/* 刷新OLED显示本程序使用直接写方式此函数保留兼容 */void OLED_Refresh(void){/* 本程序采用直接写方式无需额外刷新 */}/* * 函数: CalcSpeed* 描述: 计算转速 (RPM)* 每转计数值 1000脉冲 × 4 4000* 转速 (位置变化量 / 4000) × 60 (RPM)* 每1秒计算一次* */void CalcSpeed(void){int delta;unsigned long abs_delta;unsigned long rpm;delta g_encoder_pos - g_encoder_last_pos;g_encoder_last_pos g_encoder_pos;if(delta 0){abs_delta (unsigned long)delta;g_direction 0; // CW 正转}else{abs_delta (unsigned long)(-delta);g_direction 1; // CCW 反转}/* RPM (delta_count / 4000) × 60 */rpm abs_delta * 60 / 4000;if(rpm 99999) rpm 99999;g_speed_rpm (unsigned int)rpm;}/* * 函数: UpdateDisplay* 描述: 更新OLED显示内容* */void UpdateDisplay(void){unsigned char buf[20];/* 第0行: 当前位置值 (有符号数) */if(g_encoder_pos 0){OLED_ShowString(30, 0, -);OLED_ShowNum(36, 0, (unsigned long)(-g_encoder_pos), 6);}else{OLED_ShowString(30, 0, );OLED_ShowNum(36, 0, (unsigned long)g_encoder_pos, 6);}/* 第2行: 转速 RPM */OLED_ShowNum(30, 2, (unsigned long)g_speed_rpm, 5);OLED_ShowString(66, 2, RPM);/* 第4行: 方向 */if(g_direction 0){OLED_ShowString(30, 4, CW (CW) );}else{OLED_ShowString(30, 4, CCW (CCW) );}/* 第6行: 脉冲计数值 */OLED_ShowNum(36, 6, (unsigned long)g_pulse_count, 8);}/* * 函数: Delay_ms* 描述: 软件延时 (近似)* */void Delay_ms(unsigned int ms){unsigned int i, j;for(i 0; i ms; i){for(j 0; j 1200; j){_nop_();}}}/* * 中断服务函数* *//* PWMA 中断 (中断号26) - 编码器计数更新 */void PWMA_ISR(void) interrupt 26{unsigned int current_cnt;if(PWMA_SR1 0x02) // 编码器更新中断{/* 读取当前计数值16位 */current_cnt ((unsigned int)PWMA_CNTRH 8) | PWMA_CNTRL;/* 将硬件计数值转换为有符号位置值 *//* PWMA_CR1的DIR位指示方向0向上(正转), 1向下(反转) */if(PWMA_CR1 0x10) // DIR1, 反转{/* 反转时计数值从ARR向下计数需要转换 */g_encoder_pos -(int)(0x10000 - current_cnt);}else // DIR0, 正转{g_encoder_pos (int)current_cnt;}/* 脉冲计数值 位置值的绝对值 / 4 (因为模式3每个脉冲计4次) */if(g_encoder_pos 0)g_pulse_count (unsigned int)(g_encoder_pos / 4);elseg_pulse_count (unsigned int)((-g_encoder_pos) / 4);g_pos_changed 1;PWMA_SR1 ~0x02; // 清中断标志}else{PWMA_SR1 0; // 清其他标志}}/* 定时器0中断 (中断号1) - 1秒定时 */void Timer0_ISR(void) interrupt 1{g_timer0_cnt;if(g_timer0_cnt 1000) // 1秒到{g_timer0_cnt 0;CalcSpeed(); // 计算转速}}文件2stc8h.h头文件片段——如果使用Keil自带头文件可省略如果您使用的是 Keil C51 STC 官方头文件包直接 #include stc8h.h 即可。如果手头没有以下是程序中用到的 XFR 寄存器定义的关键部分可添加到项目头文件中/* * STC8H8K64U 关键 XFR 寄存器定义用于编码器 I2C* 完整头文件请使用 STC-ISP 软件生成* */#ifndef __STC8H_EXTRA_H__#define __STC8H_EXTRA_H__/* ---------- PWMA 寄存器 (XFR 地址) ---------- */#define PWMA_CR1 (*(unsigned char volatile xdata *)0xFEC0)#define PWMA_CR2 (*(unsigned char volatile xdata *)0xFEC1)#define PWMA_SMCR (*(unsigned char volatile xdata *)0xFEC2)#define PWMA_IER (*(unsigned char volatile xdata *)0xFEC4)#define PWMA_SR1 (*(unsigned char volatile xdata *)0xFEC5)#define PWMA_SR2 (*(unsigned char volatile xdata *)0xFEC6)#define PWMA_CCMR1 (*(unsigned char volatile xdata *)0xFEC8)#define PWMA_CCMR2 (*(unsigned char volatile xdata *)0xFEC9)#define PWMA_CCER1 (*(unsigned char volatile xdata *)0xFECC)#define PWMA_CCER2 (*(unsigned char volatile xdata *)0xFECD)#define PWMA_CNTRH (*(unsigned char volatile xdata *)0xFECE)#define PWMA_CNTRL (*(unsigned char volatile xdata *)0xFECF)#define PWMA_PSCRH (*(unsigned char volatile xdata *)0xFED0)#define PWMA_PSCRL (*(unsigned char volatile xdata *)0xFED1)#define PWMA_ARRH (*(unsigned char volatile xdata *)0xFED2)#define PWMA_ARRL (*(unsigned char volatile xdata *)0xFED3)#define PWMA_ENO (*(unsigned char volatile xdata *)0xFEB1)#define PWMA_PS (*(unsigned char volatile xdata *)0xFEB2)/* ---------- I2C 寄存器 (XFR 地址) ---------- */#define I2CCFG (*(unsigned char volatile xdata *)0xFE80)#define I2CMSCR (*(unsigned char volatile xdata *)0xFE81)#define I2CMSST (*(unsigned char volatile xdata *)0xFE82)#define I2CSLCR (*(unsigned char volatile xdata *)0xFE83)#define I2CSLST (*(unsigned char volatile xdata *)0xFE84)#define I2CSLADR (*(unsigned char volatile xdata *)0xFE85)#define I2CTXD (*(unsigned char volatile xdata *)0xFE86)#define I2CRXD (*(unsigned char volatile xdata *)0xFE87)#define I2CMSAUX (*(unsigned char volatile xdata *)0xFE88)#endif程序说明项目 说明单片机 STC8H8K64U工作频率 11.0592MHz编码器接口 PWMA 高级PWM编码器模式3A相→P1.0B相→P1.2每转脉冲 1000 PPR模式3下每转计数值 1000 × 4 4000OLED接口 I2C硬件主机模式SCL→P1.5SDA→P1.4地址0x78显示内容 第0行当前位置值有符号第2行转速RPM第4行方向CW/CCW第6行脉冲计数值转速计算 每1秒计算一次RPM (Δ位置 / 4000) × 60中断使用 PWMA中断中断号26读取编码器计数值定时器0中断中断号1做1秒定时使用步骤打开 STC-ISP 软件选择单片机型号 STC8H8K64U设置系统时钟为 11.0592MHz生成头文件点击头文件选项卡生成 stc8h.h 放入项目在 Keil C51 中新建项目将上述 main.c 加入项目编译下载到单片机连接硬件编码器 A 相 → P1.0编码器 B 相 → P1.2OLED SCL → P1.5OLED SDA → P1.4OLED VCC → 3.3VGND → GND注意事项编码器输出电平如果编码器是 5V/24V 输出需要加电平转换电路如电阻分压或光耦隔离确保输入到 P1.0/P1.2 的电平不超过 3.6VSTC8H 为 3.3V/5V tolerant但建议 3.3V 逻辑电平。滤波设置程序中 PWMA_CCMR1/2 设置了滤波时钟数为 10可根据编码器实际输出质量调整值越大滤波越强但会丢失高速脉冲。编码器模式选择当前使用模式3SMS011每个脉冲计4次。如果编码器抖动较大可改为模式1或模式2每个脉冲计2次修改 PWMA_SMCR 0x01 或 0x02 即可。位置值溢出16位计数器最大 65535如果旋转圈数很多会溢出。如需更大范围可在中断中增加软件扩展计数如增加一个 long 变量累加溢出次数。?? 搜索 增量式编码器正反转程序 1任意一款单片机 2AB相正交脉冲 3当前位置值、转速RPM、方向CW/CCW、脉冲计?? 查找用时 24.9s | 总回答用时 97.2s