1.7、enum、#define和typedef的注意点

本文详细介绍了枚举(enum)的基本特性及其与#define的区别,并对比了typedef的功能与限制,帮助读者理解这些C/C++语言特性在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、enum默认常量在前一个值的基础上加1


2、enum类型的变量只能取定义时的离散值


3、enum color

   {

        GREEN,

        RED,

        BULE

   };

   GREEN == 0, RED == 1, BULE == 2


4、enum定义的常量才是真正意义的常量


5、枚举类型和#define的区别

   (1)#define宏常量只是简单的进行值替换,枚举常量是真正意义上的常量

   (2)#define宏常量无法被调试枚举常量可以(GDB)

   (3)#define宏常量无类型信息,枚举常量是一种特定类型的常量


6、typedef用于给一个已经存在的数据类型重命名


7、typedef并没有产生新的类型


8、typedef重定义的类型不能进行unsigned和signed扩展


9、#define为简单的字符串替换,无别名的概念

#include <STC8HX.h> // 定义步进电机控制引脚 #define MOTOR_IN1 P3_5 #define MOTOR_IN2 P3_4 #define MOTOR_IN3 P3_3 #define MOTOR_IN4 P3_2 // 定义按键引脚(下拉到GND,短接VCC触发,高电平有效) #define KEY_PIN P1_7 // 定义状态指示LED #define LED_PIN P1_6 // 系统状态LED(绿色) #define STATUS_LED P1_5 // 电机状态LED(黄色) #define KEY_LED P1_4 // 按键状态LED(红色) // 系统参数 #define DEBOUNCE_TIME 20 // 按键消抖时间(ms) #define STEP_DELAY 20 // 步进延时(ms),控制电机速度 #define TOTAL_STEPS 800 // 总步数 #define MODE_SWITCH_DELAY 300 // 模式切换延时(ms) // 工作模式定义 typedef enum { MODE_STOP, // 停止模式 MODE_FORWARD, // 正转模式 MODE_BACKWARD, // 反转模式 MODE_TEST // 测试模式 } SystemMode; // 全局变量定义 static SystemMode currentMode = MODE_STOP; // 当前工作模式 static unsigned char keyState = 0; // 按键状态机 static unsigned int keyTimer = 0; // 按键消抖计时 static unsigned int currentStep = 0; // 当前电机步数 static bit motorRunning = 0; // 电机运行标志 static unsigned int lastPressTime = 0; // 按键连击计数 static bit modeSwitchAllowed = 1; // 模式切换允许标志 static unsigned int systemTimer = 0; // 系统计时器 static unsigned char lastDirection = 0; // 上次运行方向(0=正转,1=反转) static unsigned char loopCounter = 0; // 循环计数器 // 双相励磁方式(双4拍) code unsigned char phaseTable[4] = { 0b0011, // IN1+IN2 0b0110, // IN2+IN3 0b1100, // IN3+IN4 0b1001 // IN4+IN1 }; // 函数声明 void SystemInit(void); void MotorInit(void); void KeyInit(void); void LedInit(void); void DelayMs(unsigned int ms); void MotorStep(unsigned char phase); void MotorStop(void); void RunMotorForward(void); void RunMotorBackward(void); void CheckKey(void); void EnterTestMode(void); void ExitTestMode(void); void ProcessTestMode(void); void UpdateLEDStatus(void); void AllowModeSwitch(void); // 主函数 void main(void) { SystemInit(); // 系统初始化 while (1) { CheckKey(); // 检测按键 UpdateLEDStatus(); // 更新LED状态 switch (currentMode) { case MODE_STOP: MotorStop(); break; case MODE_FORWARD: RunMotorForward(); break; case MODE_BACKWARD: RunMotorBackward(); break; case MODE_TEST: ProcessTestMode(); break; } DelayMs(10); // 小延时 systemTimer++; // 系统计时器递增 } } // 系统初始化 void SystemInit(void) { // 配置电机引脚为推挽输出 P3M1 = 0x00; P3M0 = 0x3C; // P3.5-P3.2推挽输出 // 配置按键LED引脚 P1M1 = 0x80; // P1.7设为高阻输入模式 P1M0 = 0x00; // P1.7设为浮空输入模式 // 初始化变量 MotorInit(); KeyInit(); LedInit(); // 系统启动指示(LED闪烁) for (loopCounter = 0; loopCounter < 3; loopCounter++) { LED_PIN = 1; STATUS_LED = 1; KEY_LED = 1; DelayMs(200); LED_PIN = 0; STATUS_LED = 0; KEY_LED = 0; DelayMs(200); } modeSwitchAllowed = 1; lastDirection = 0; // 初始方向设为正转 } // 电机初始化 void MotorInit(void) { MotorStop(); currentStep = 0; motorRunning = 0; } // 按键初始化 void KeyInit(void) { P1PU &= ~0x80; // 禁用P1.7内部上拉 keyState = 0; keyTimer = 0; lastPressTime = 0; } // LED初始化 void LedInit(void) { LED_PIN = 0; // 系统LED熄灭 STATUS_LED = 0; // 状态LED熄灭 KEY_LED = 0; // 按键LED熄灭 } // 毫秒级延时 void DelayMs(unsigned int ms) { unsigned int i, j; for (i = 0; i < ms; i++) for (j = 0; j < 120; j++); } // 电机步进控制 void MotorStep(unsigned char phase) { unsigned char pattern = phaseTable[phase % 4]; MOTOR_IN1 = (pattern & 0x01); MOTOR_IN2 = (pattern & 0x02); MOTOR_IN3 = (pattern & 0x04); MOTOR_IN4 = (pattern & 0x08); DelayMs(STEP_DELAY); } // 停止电机 void MotorStop(void) { MOTOR_IN1 = 0; MOTOR_IN2 = 0; MOTOR_IN3 = 0; MOTOR_IN4 = 0; motorRunning = 0; AllowModeSwitch(); // 停止后允许模式切换 } // 检测按键(优化方向控制) void CheckKey(void) { static bit lastKeyState = 0; // 上次按键状态 bit currentKeyState = KEY_PIN; // 按键消抖 if (currentKeyState != lastKeyState) { keyTimer = 0; lastKeyState = currentKeyState; } else if (keyTimer >= DEBOUNCE_TIME) { // 按键按下(高电平触发) if (currentKeyState == 1 && !keyState) { keyState = 1; KEY_LED = 1; // 亮按键LED // 按1次:切换方向(确保交替正反转) if (modeSwitchAllowed && !motorRunning) { if (currentMode == MODE_STOP) { // 从停止状态启动,默认为正转 currentMode = MODE_FORWARD; currentStep = 0; motorRunning = 1; lastDirection = 0; // 记录方向为正转 } else if (lastDirection == 0) { // 上次为正转,本次切反转 currentMode = MODE_BACKWARD; currentStep = TOTAL_STEPS; // 反转从最大步数开始 motorRunning = 1; lastDirection = 1; // 记录方向为反转 } else { // 上次为反转,本次切正转 currentMode = MODE_FORWARD; currentStep = 0; // 正转从0开始 motorRunning = 1; lastDirection = 0; // 记录方向为正转 } modeSwitchAllowed = 0; // 禁止立即再次切换 } // 连续按3次:进入测试模式 else { if (++lastPressTime >= 3) { EnterTestMode(); lastPressTime = 0; } } } // 按键释放 else if (currentKeyState == 0 && keyState) { keyState = 0; KEY_LED = 0; // 熄灭按键LED lastPressTime = 0; // 释放后重置计数 } } else { keyTimer++; } } // 允许模式切换(带延时) void AllowModeSwitch(void) { static unsigned int switchTimer = 0; if (!modeSwitchAllowed) { if (switchTimer < MODE_SWITCH_DELAY / 10) { switchTimer++; } else { modeSwitchAllowed = 1; switchTimer = 0; } } } // 更新LED状态 void UpdateLEDStatus(void) { switch (currentMode) { case MODE_STOP: LED_PIN = 1; // 系统LED亮 STATUS_LED = 0; // 状态LED灭 break; case MODE_FORWARD: LED_PIN = 0; // 系统LED灭 STATUS_LED = 1; // 状态LED亮(正转) break; case MODE_BACKWARD: LED_PIN = 1; // 系统LED亮 STATUS_LED = 1; // 状态LED亮(反转) break; case MODE_TEST: LED_PIN = (systemTimer % 50) < 25; // 快速闪烁 STATUS_LED = LED_PIN; break; } } // 进入测试模式 void EnterTestMode(void) { currentMode = MODE_TEST; currentStep = 0; motorRunning = 1; // 测试模式LED指示 for (loopCounter = 0; loopCounter < 5; loopCounter++) { LED_PIN = 1; STATUS_LED = 1; DelayMs(100); LED_PIN = 0; STATUS_LED = 0; DelayMs(100); } } // 退出测试模式 void ExitTestMode(void) { currentMode = MODE_STOP; MotorStop(); } // 处理测试模式 void ProcessTestMode(void) { static unsigned char testPhase = 0; switch (testPhase) { case 0: // 正转阶段 if (currentStep < TOTAL_STEPS) { RunMotorForward(); } else { testPhase = 1; MotorStop(); DelayMs(500); } break; case 1: // 反转阶段 if (currentStep > 0) { RunMotorBackward(); } else { testPhase = 0; MotorStop(); DelayMs(1000); } break; } } // 正转电机 void RunMotorForward(void) { if (currentStep < TOTAL_STEPS && motorRunning) { MotorStep(currentStep % 4); currentStep++; } else { if (currentMode != MODE_TEST) { MotorStop(); } } } // 反转电机(关键修复) void RunMotorBackward(void) { if (currentStep > 0 && motorRunning) { MotorStep(3 - (currentStep % 4)); // 反转相位 currentStep--; // 步数递减 } else { if (currentMode != MODE_TEST) { MotorStop(); } } } 以上代码只能一直正转,我的逻辑是停止-正转-停止-反转-停止,以及测试模式
最新发布
07-04
#include <STC8HX.h> #include <stdlib.h> // 提供 abs() 函数声明 /* 全局常量定义 */ #define BLOCK_SIZE 64 // EEPROM块大小 #define TOTAL_STEPS 500 // 总步数 #define EEPROM_START_ADDR 0x0000 // EEPROM起始地址 #define EEPROM_SIZE 512 // EEPROM大小(字节) #define EEPROM_WRITE_TIMEOUT 1000 // 写超时时间(ms) #define MIN_SAVE_DELTA 50 // 最小保存位置变化量[^1] /* 引脚定义 */ #define LED_PIN P3_1 #define STEP_A_PIN P3_5 #define STEP_B_PIN P3_4 #define STEP_C_PIN P3_3 #define STEP_D_PIN P3_2 #define RS_485_PIN P5_4 #define BUTTON_PIN P1_7 #define LIMIT_UP_PIN P3_7 #define LIMIT_DOWN_PIN P3_6 /* EEPROM命令定义 */ #define CMD_IDLE 0x00 // 空闲命令 #define CMD_READ 0x01 // 读命令 #define CMD_PROGRAM 0x02 // 写命令 #define CMD_ERASE 0x03 // 擦除命令 /* 系统状态定义 */ typedef enum { SYS_STATE_INIT = 0, // 初始化状态 SYS_STATE_IDLE = 1, // 空闲状态 SYS_STATE_WORK = 2, // 工作状态 SYS_STATE_TEST = 3, // 测试状态 SYS_STATE_ERROR = 4, // 错误状态 } SystemState; /* 电机状态定义 */ typedef enum { MOTOR_STATE_STOP = 0, // 停止状态 MOTOR_STATE_FWD = 1, // 正转状态(向上) MOTOR_STATE_REV = 2, // 反转状态(向下) } MotorState; /* 步进电机4相8拍控制表 (修正相位序列) */ code unsigned char stepTable[8] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09 // 正确相位序列[^2] }; /* 全局变量 */ volatile SystemState gSystemState = SYS_STATE_INIT; // 系统状态 volatile MotorState gMotorState = MOTOR_STATE_STOP; // 电机状态 volatile unsigned char gStepIndex = 0; // 步进序列索引 volatile unsigned int gCurrentPosition = 0; // 当前位置 volatile unsigned int gTargetPosition = 0; // 目标位置 volatile unsigned int gStepDelay = 30; // 步进延时(ms) volatile unsigned int gSystemTimer = 0; // 系统计时器 volatile unsigned int gButtonTimer = 0; // 按钮计时器 volatile unsigned char gButtonPressCount = 0; // 按钮按下次数 volatile bit gButtonState = 0; // 按钮状态 volatile bit gButtonLastState = 0; // 按钮上次状态 volatile unsigned int gAccelSteps = 50; // 加速/减速步数 volatile unsigned int gMaxSpeed = 5; // 最大速度(最小延时) volatile unsigned int gMinSpeed = 20; // 最小速度(最大延时) volatile unsigned char eepromBuffer[BLOCK_SIZE]; // EEPROM缓冲区 volatile unsigned int gLastSavedPosition = 0; // 上次保存位置[^1] /* 函数声明 */ void SystemInit(void); void MotorControl(void); void ButtonScan(void); void ProcessButton(void); void MoveToTarget(void); void CheckLimits(void); void SetLedState(unsigned char state, unsigned int blinkRate); void EEPROM_Init(void); bit EEPROM_Write(unsigned int addr, unsigned char dat); unsigned char EEPROM_Read(unsigned int addr); bit EEPROM_EraseSector(unsigned int addr); unsigned int EEPROM_CalculateCRC(unsigned int startAddr, unsigned int length); void EEPROM_WriteMulti(unsigned int addr, unsigned char *pData, unsigned int length); void EEPROM_ReadMulti(unsigned int addr, unsigned char *pData, unsigned int length); unsigned int CalculateSpeed(unsigned int current, unsigned int target); void SavePositionToEeprom(void); void LoadPositionFromEeprom(void); void PowerOffMotor(void); void Watchdog_Init(void); void Watchdog_Feed(void); void main(void) { Watchdog_Init(); // 初始化看门狗 SystemInit(); // 系统初始化 // 从EEPROM加载位置 LoadPositionFromEeprom(); gLastSavedPosition = gCurrentPosition; // 初始化保存位置 // 主循环 while (1) { Watchdog_Feed(); // 喂狗 ButtonScan(); // 扫描按钮 ProcessButton(); // 处理按钮事件 CheckLimits(); // 检查限位开关 MoveToTarget(); // 移动到目标位置 // 根据位置变化决定是否保存 if (labs((long)gCurrentPosition - (long)gLastSavedPosition) > MIN_SAVE_DELTA) { SavePositionToEeprom(); } // 根据系统状态执行操作 switch (gSystemState) { case SYS_STATE_INIT: gTargetPosition = TOTAL_STEPS; // 移动到上限位 gMotorState = MOTOR_STATE_FWD; gSystemState = SYS_STATE_WORK; break; case SYS_STATE_WORK: if (gMotorState == MOTOR_STATE_STOP) { gTargetPosition = gCurrentPosition; } break; case SYS_STATE_TEST: // 测试模式逻辑 break; case SYS_STATE_ERROR: SetLedState(1, 200); // 错误状态闪烁LED PowerOffMotor(); // 关闭电机 break; } } } void SystemInit(void) { // 1. 时钟配置 CLKDIV = 0x01; // 系统时钟分频 // 2. 初始化IO口模式 P3M1 &= ~0x20; P3M0 |= 0x20; // P3_5推挽输出 P3M1 &= ~0x10; P3M0 |= 0x10; // P3_4推挽输出 P3M1 &= ~0x08; P3M0 |= 0x08; // P3_3推挽输出 P3M1 &= ~0x04; P3M0 |= 0x04; // P3_2推挽输出 P3M1 &= ~0x02; P1M0 |= 0x02; // P1_6推挽输出(LED) P1M1 |= 0x80; P1M0 &= ~0x80; // P1_7输入(按钮) P3M1 |= 0x80; P3M0 &= ~0x80; // P3_7输入(上限位) P3M1 |= 0x40; P3M0 &= ~0x40; // P3_6输入(下限位) // 3. 初始化输出状态 P3 = 0x00; // 步进电机初始为0 LED_PIN = 0; // LED初始熄灭 // 4. 定时器0初始化 (步进控制) TMOD = 0x01; // 设置定时器0为模式1 TH0 = 0xFC; // 定时初值,约1ms TL0 = 0x66; ET0 = 1; // 使能定时器0中断 TR0 = 1; // 启动定时器0 // 5. 开启总中断 EA = 1; // 6. 初始化EEPROM EEPROM_Init(); } void MotorControl(void) { static unsigned int stepTimer = 0; if(gMotorState != MOTOR_STATE_STOP) { if(gSystemTimer - stepTimer > gStepDelay) { stepTimer = gSystemTimer; // 计算当前速度(S曲线算法) gStepDelay = CalculateSpeed(gCurrentPosition, gTargetPosition); // 电机转动控制 if(gMotorState == MOTOR_STATE_FWD) { gStepIndex = (gStepIndex + 1) % 8; gCurrentPosition++; if(gCurrentPosition >= TOTAL_STEPS) gCurrentPosition = TOTAL_STEPS; } else { gStepIndex = (gStepIndex + 7) % 8; gCurrentPosition--; if(gCurrentPosition <= 0) gCurrentPosition = 0; } // 输出步进信号 P3 = (P3 & 0xE0) | stepTable[gStepIndex]; // 到达目标位置处理 if((gMotorState == MOTOR_STATE_FWD && gCurrentPosition >= gTargetPosition) || (gMotorState == MOTOR_STATE_REV && gCurrentPosition <= gTargetPosition)) { gMotorState = MOTOR_STATE_STOP; P3 &= 0xE0; // 关闭所有步进相 } } } } unsigned int CalculateSpeed(unsigned int current, unsigned int target) { int distance = target > current ? target - current : current - target; unsigned int speed; // 距离目标较远,使用最大速度 if (distance > gAccelSteps * 2) { return gMaxSpeed; } // 计算当前处于加速区、匀速区还是减速区 if (current < target) { // 正向运动 if (distance > gAccelSteps) { // 加速区 speed = gMinSpeed - (gMinSpeed - gMaxSpeed) * distance / (gAccelSteps * 2); } else { // 减速区 speed = gMaxSpeed + (gMinSpeed - gMaxSpeed) * (gAccelSteps - distance) / gAccelSteps; } } else { // 反向运动 if (distance > gAccelSteps) { // 加速区 speed = gMinSpeed - (gMinSpeed - gMaxSpeed) * distance / (gAccelSteps * 2); } else { // 减速区 speed = gMaxSpeed + (gMinSpeed - gMaxSpeed) * (gAccelSteps - distance) / gAccelSteps; } } // 确保速度在有效范围内 if (speed < gMaxSpeed) speed = gMaxSpeed; if (speed > gMinSpeed) speed = gMinSpeed; return speed; } void ButtonScan(void) { static unsigned int debounceTimer = 0; if(gSystemTimer - debounceTimer > 20) { debounceTimer = gSystemTimer; gButtonLastState = gButtonState; gButtonState = BUTTON_PIN; // 检测按钮上升沿 if(gButtonState == 0 && gButtonLastState == 1) { gButtonPressCount++; gButtonTimer = gSystemTimer; } // 长按检测 if(gButtonState == 0 && gSystemTimer - gButtonTimer > 3000) { // 长按3秒,恢复出厂设置 gButtonPressCount = 0; gCurrentPosition = 0; gTargetPosition = 0; gSystemState = SYS_STATE_INIT; SetLedState(1, 200); // 闪烁LED表示重置 } } } void ProcessButton(void) { if(gButtonPressCount > 0 && gSystemTimer - gButtonTimer > 500) { switch (gButtonPressCount) { case 1: // 短按1次 - 切换工作/测试模式 if (gSystemState == SYS_STATE_WORK) { gSystemState = SYS_STATE_TEST; SetLedState(1, 500); // LED中速闪烁表示测试模式 } else if (gSystemState == SYS_STATE_TEST) { gSystemState = SYS_STATE_WORK; SetLedState(0, 0); // LED常亮表示工作模式 } break; case 2: // 短按2次 - 电机正转(向上) if (gSystemState == SYS_STATE_WORK || gSystemState == SYS_STATE_TEST) { if (gMotorState == MOTOR_STATE_STOP) { gTargetPosition = TOTAL_STEPS; gMotorState = MOTOR_STATE_FWD; } else if (gMotorState == MOTOR_STATE_FWD) { gMotorState = MOTOR_STATE_STOP; } } break; case 3: // 短按3次 - 电机反转(向下) if (gSystemState == SYS_STATE_WORK || gSystemState == SYS_STATE_TEST) { if (gMotorState == MOTOR_STATE_STOP) { gTargetPosition = 0; gMotorState = MOTOR_STATE_REV; } else if (gMotorState == MOTOR_STATE_REV) { gMotorState = MOTOR_STATE_STOP; } } break; } gButtonPressCount = 0; } } void MoveToTarget(void) { if (gMotorState == MOTOR_STATE_STOP && gTargetPosition != gCurrentPosition) { if (gTargetPosition > gCurrentPosition) { gMotorState = MOTOR_STATE_FWD; } else { gMotorState = MOTOR_STATE_REV; } } } void Timer0_ISR(void) interrupt 1 { // 重新加载初值 TH0 = 0xFC; TL0 = 0x66; gSystemTimer++; // 系统计时器递增 MotorControl(); // 步进电机控制 } void CheckLimits(void) { // 上限位触发 if(LIMIT_UP_PIN == 0 && gMotorState == MOTOR_STATE_FWD) { gCurrentPosition = TOTAL_STEPS; gMotorState = MOTOR_STATE_STOP; PowerOffMotor(); // 安全关闭电机 } // 下限位触发 if(LIMIT_DOWN_PIN == 0 && gMotorState == MOTOR_STATE_REV) { gCurrentPosition = 0; gMotorState = MOTOR_STATE_STOP; PowerOffMotor(); // 安全关闭电机 } } void SetLedState(unsigned char blink, unsigned int blinkRate) { static unsigned int ledTimer = 0; static bit ledState = 0; if(blink) { if(gSystemTimer - ledTimer > blinkRate) { ledTimer = gSystemTimer; ledState = !ledState; LED_PIN = ledState; } } else { LED_PIN = 1; // 常亮 } } void PowerOffMotor(void) { // 安全关闭电机:所有低边导通释放能量 P3 = (P3 & 0xE0) | 0x0F; // 所有相低边导通 P3 &= 0xE0; // 关闭所有相 } void Watchdog_Init(void) { // 使能看门狗,2秒超时 WDT_CONTR = 0x34; // 预分频16, 使能看门狗 } void Watchdog_Feed(void) { // 喂狗操作 WDT_CONTR |= 0x10; // 清除看门狗计数器 } void EEPROM_Init(void) { // 使能EEPROM操作 IAP_CONTR = 0x80; // 允许IAP操作,设置等待时间 IAP_TPS = 0xAA; // 保护密钥 } bit EEPROM_EraseSector(unsigned int addr) { unsigned int timeout = 0; // 检查地址范围 if (addr >= EEPROM_START_ADDR + EEPROM_SIZE) { return 0; // 地址超出范围 } // 设置扇区地址 IAP_ADDRH = (unsigned char)(addr >> 8); IAP_ADDRL = (unsigned char)(addr & 0xFF); // 发送擦除命令 IAP_CMD = CMD_ERASE; // 触发命令 EA = 0; // 关中断 IAP_TRIG = 0x5A; IAP_TRIG = 0xA5; _nop_(); EA = 1; // 开中断 // 等待操作完成 while ((IAP_CONTR & 0x20) == 0) { // 等待ERR标志清零 timeout++; if (timeout > EEPROM_WRITE_TIMEOUT) { return 0; // 超时失败 } } return 1; // 擦除成功 } bit EEPROM_Write(unsigned int addr, unsigned char dat) { unsigned int timeout = 0; unsigned int sectorAddr = addr & 0xFE00; // 计算扇区地址 // 检查地址范围 if (addr >= EEPROM_START_ADDR + EEPROM_SIZE) { return 0; // 地址超出范围 } // 设置写入地址 IAP_ADDRH = (unsigned char)(addr >> 8); IAP_ADDRL = (unsigned char)(addr & 0xFF); // 设置写入数据 IAP_DATA = dat; // 发送写命令 IAP_CMD = CMD_PROGRAM; // 触发命令 EA = 0; // 关中断 IAP_TRIG = 0x5A; IAP_TRIG = 0xA5; _nop_(); EA = 1; // 开中断 // 等待操作完成 while ((IAP_CONTR & 0x20) == 0) { // 等待ERR标志清零 timeout++; if (timeout > EEPROM_WRITE_TIMEOUT) { return 0; // 超时失败 } } // 验证写入数据 if (EEPROM_Read(addr) != dat) { return 0; // 验证失败 } return 1; // 写入成功 } unsigned char EEPROM_Read(unsigned int addr) { unsigned char dat; // 检查地址范围 if (addr >= EEPROM_START_ADDR + EEPROM_SIZE) { return 0xFF; // 地址超出范围 } // 设置读取地址 IAP_ADDRH = (unsigned char)(addr >> 8); IAP_ADDRL = (unsigned char)(addr & 0xFF); // 发送读命令 IAP_CMD = CMD_READ; // 触发命令 EA = 0; // 关中断 IAP_TRIG = 0x5A; IAP_TRIG = 0xA5; _nop_(); EA = 1; // 开中断 // 读取数据 dat = IAP_DATA; return dat; } void SavePositionToEeprom(void) { unsigned char data[4]; unsigned int crc; // 准备数据 data[0] = gCurrentPosition & 0xFF; data[1] = (gCurrentPosition >> 8) & 0xFF; data[2] = TOTAL_STEPS & 0xFF; data[3] = (TOTAL_STEPS >> 8) & 0xFF; // 写入数据(地址0开始的4个字节) EEPROM_WriteMulti(0, data, 4); // 写入CRC校验值(地址45) crc = EEPROM_CalculateCRC(0, 4); // 计算CRC EEPROM_Write(4, crc & 0xFF); // 写入低字节 EEPROM_Write(5, (crc >> 8) & 0xFF); // 写入高字节 } void LoadPositionFromEeprom(void) { unsigned char data[4]; unsigned int storedCRC, calculatedCRC; // 读取数据 EEPROM_ReadMulti(0, data, 4); // 读取存储的CRC校验值 storedCRC = EEPROM_Read(4) | (EEPROM_Read(5) << 8); // 计算当前数据的CRC校验值 calculatedCRC = EEPROM_CalculateCRC(0, 4); // 验证CRC if (storedCRC == calculatedCRC) { // CRC校验通过,恢复数据 gCurrentPosition = data[0] | (data[1] << 8); // 确保位置合理 if (gCurrentPosition > TOTAL_STEPS) { gCurrentPosition = TOTAL_STEPS; } } else { // CRC校验失败,使用默认值 gCurrentPosition = 0; } } 根据以上内容,重新设计一个电机能够正转反转,到上下限位的位置停止,按下按键能够到另一个限位位置,首先要能找到限位,简化设计,按键还是只有一个是轻触按钮,两个霍尔传感器HAL3144,一个LED,可以自己设置总步数电机速度,帮忙写好注解
07-02
#include <STC8HX.h> #include <stdio.h> // 定义步进电机控制引脚 #define MOTOR_IN1 P3_5 #define MOTOR_IN2 P3_4 #define MOTOR_IN3 P3_3 #define MOTOR_IN4 P3_2 // 定义按键引脚(下拉到GND,短接VCC触发,高电平有效) #define KEY_PIN P1_7 // 定义状态指示LED #define LED_PIN P1_6 // 系统状态LED #define LIMIT_LED P1_5 // 限位状态LED #define KEY_LED P1_4 // 按键状态LED // 定义限位传感器引脚 #define LIMIT_UP P2_0 #define LIMIT_DOWN P2_1 // 系统参数 #define DEBOUNCE_TIME 20 // 按键消抖时间(ms) #define LONG_PRESS_TIME 3000 // 长按3s #define TEST_TIMER 2000 // 测试模式计时2s #define STEP_DELAY_MIN 5 // 最小延时 #define STEP_DELAY_MAX 50 // 最大延时 #define TOTAL_STEPS 2000 // 总步数 // 工作模式定义 typedef enum { MODE_INIT, // 初始化模式 MODE_WORK, // 工作模式 MODE_TEST // 测试模式 } SystemMode; // 测试步骤定义 typedef enum { TEST_STEP_0, // 初始步骤 TEST_STEP_1, // 步骤1:电机正转到上限位 TEST_STEP_2, // 步骤2:电机反转到下限位 TEST_STEP_3 // 步骤3:完成测试 } TestStep; // 全局变量定义 static SystemMode currentMode = MODE_INIT; // 当前系统模式 static TestStep testStep = TEST_STEP_0; // 测试模式步骤 static unsigned char keyState = 0; // 按键状态机 static unsigned int keyPressCount = 0; // 按键按下次数 static unsigned int keyTimer = 0; // 按键计时 static unsigned int systemTimer = 0; // 系统计时 static unsigned int testTimer = 0; // 测试模式计时 static unsigned int currentStep = 0; // 当前电机步数 static bit motorPaused = 0; // 电机暂停标志 static bit limitUpTrigger = 0; // 上限位触发标志 static bit limitDownTrigger = 0; // 下限位触发标志 static unsigned char loopCounter; // 循环计数器 // 双相励磁方式(双4拍) code unsigned char phaseTable[4] = { 0b0011, // IN1+IN2 0b0110, // IN2+IN3 0b1100, // IN3+IN4 0b1001 // IN4+IN1 }; // 函数声明 void SystemInit(void); void MotorInit(void); void KeyInit(void); void LedInit(void); void UartInit(void); void DelayMs(unsigned int ms); void MotorStep(unsigned char phase); void MotorStop(void); void CheckKey(void); void EnterTestMode(void); void ExitTestMode(void); void ProcessTestMode(void); void RunMotorForward(void); void RunMotorBackward(void); void CheckLimits(void); void ProcessWorkMode(void); void DebugPrint(const char* format, ...); void UpdateLimitLED(void); // 更新限位状态LED // 串口发送字符 void putchar(char c) { while (!TI); TI = 0; SBUF = c; } // 主函数 void main(void) { SystemInit(); // 系统初始化 DebugPrint("System started!\r\n"); while (1) { CheckKey(); // 检测按键 CheckLimits(); // 检测限位状态 UpdateLimitLED(); // 更新限位LED状态 systemTimer++; // 系统计时器累加 switch (currentMode) { case MODE_INIT: DebugPrint("Mode: INIT\r\n"); // 初始化完成后进入工作模式 currentMode = MODE_WORK; break; case MODE_WORK: DebugPrint("Mode: WORK\r\n"); ProcessWorkMode(); break; case MODE_TEST: DebugPrint("Mode: TEST, Step: %d\r\n", testStep); ProcessTestMode(); break; } DelayMs(10); // 小延时 } } // 系统初始化 void SystemInit(void) { // 配置电机引脚为推挽输出 P3M1 = 0x00; P3M0 = 0x3C; // P3.5-P3.2推挽输出 // 配置按键LED引脚 P1M1 = 0xF0; // P1.7-P1.4高阻输入 P1M0 = 0x70; // P1.6-P1.4推挽输出(LED) // 配置限位传感器引脚为输入 P2M1 = 0x03; // P2.0-P2.1高阻输入 P2M0 = 0x00; // 初始化串口 UartInit(); DebugPrint("Initializing system...\r\n"); // 初始化变量 MotorInit(); KeyInit(); LedInit(); // 系统启动指示 for (loopCounter = 0; loopCounter < 3; loopCounter++) { LED_PIN = 1; LIMIT_LED = 1; KEY_LED = 1; DelayMs(100); LED_PIN = 0; LIMIT_LED = 0; KEY_LED = 0; DelayMs(100); } DebugPrint("System initialized successfully!\r\n"); } // 电机初始化 void MotorInit(void) { MotorStop(); currentStep = 0; motorPaused = 1; limitUpTrigger = 0; limitDownTrigger = 0; DebugPrint("Motor initialized\r\n"); } // 按键初始化(使用外部下拉电阻,禁用内部上拉) void KeyInit(void) { // P1PU &= ~0x80; // 确保内部上拉电阻禁用 keyState = 0; keyPressCount = 0; keyTimer = 0; DebugPrint("Key initialized with external pull-down\r\n"); } // LED初始化 void LedInit(void) { LED_PIN = 0; // 系统LED初始熄灭 LIMIT_LED = 0; // 限位LED初始熄灭 KEY_LED = 0; // 按键LED初始熄灭 DebugPrint("LED initialized\r\n"); } // 串口初始化(9600bps@11.0592MHz) void UartInit(void) { SCON = 0x50; // 8位数据,可变波特率 AUXR |= 0x40; // 定时器1时钟为Fosc,即1T AUXR &= 0xFE; // 串口1选择定时器1为波特率发生器 TMOD &= 0x0F; // 清除定时器1模式位 TMOD |= 0x20; // 设定定时器1为8位自动重装方式 TL1 = 0xE0; // 设定定时初值 TH1 = 0xE0; // 设定定时器重装值 ET1 = 0; // 禁止定时器1中断 TR1 = 1; // 启动定时器1 TI = 1; // 使能发送 DebugPrint("UART initialized at 9600bps\r\n"); } // 毫秒级延时 void DelayMs(unsigned int ms) { unsigned int i, j; for (i = 0; i < ms; i++) for (j = 0; j < 120; j++); } // 电机步进控制 void MotorStep(unsigned char phase) { unsigned char pattern = phaseTable[phase % 4]; MOTOR_IN1 = (pattern & 0x01); MOTOR_IN2 = (pattern & 0x02); MOTOR_IN3 = (pattern & 0x04); MOTOR_IN4 = (pattern & 0x08); DebugPrint("Motor step: %d, Pattern: 0x%02X\r\n", phase, pattern); } // 停止电机 void MotorStop(void) { MOTOR_IN1 = 0; MOTOR_IN2 = 0; MOTOR_IN3 = 0; MOTOR_IN4 = 0; motorPaused = 1; DebugPrint("Motor stopped\r\n"); } // 检测按键(高电平触发) void CheckKey(void) { static bit lastKeyState = 0; // 初始为低电平(下拉状态) bit currentKeyState = KEY_PIN; // 输出当前按键状态(调试用) DebugPrint("KEY_PIN state: %d, last: %d, timer: %d\r\n", currentKeyState, lastKeyState, keyTimer); // 按键消抖 if (currentKeyState != lastKeyState) { keyTimer = 0; lastKeyState = currentKeyState; DebugPrint("Key state changed: %d\r\n", currentKeyState); } else if (keyTimer >= DEBOUNCE_TIME) { // 按键按下(高电平触发) if (currentKeyState == 1 && !keyState) { keyState = 1; keyPressCount++; LED_PIN = 1; // 系统LED亮 KEY_LED = 1; // 按键LED亮 DebugPrint("Key pressed! Count: %d\r\n", keyPressCount); } // 按键释放 else if (currentKeyState == 0 && keyState) { keyState = 0; LED_PIN = 0; // 系统LED熄灭 KEY_LED = 0; // 按键LED熄灭 DebugPrint("Key released\r\n"); } } else { keyTimer++; } } // 检测限位状态 void CheckLimits(void) { static bit lastLimitUp = 0; static bit lastLimitDown = 0; bit currentLimitUp = LIMIT_UP; bit currentLimitDown = LIMIT_DOWN; // 输出原始限位引脚状态(调试用) DebugPrint("Limit pins - Up: %d, Down: %d\r\n", currentLimitUp, currentLimitDown); // 上限位消抖 if (currentLimitUp != lastLimitUp) { keyTimer = 0; lastLimitUp = currentLimitUp; DebugPrint("LimitUp changed: %d\r\n", currentLimitUp); } else if (keyTimer >= DEBOUNCE_TIME) { // 限位触发时为低电平(接地) limitUpTrigger = !currentLimitUp; DebugPrint("LimitUp state: %d\r\n", limitUpTrigger); } // 下限位消抖 if (currentLimitDown != lastLimitDown) { keyTimer = 0; lastLimitDown = currentLimitDown; DebugPrint("LimitDown changed: %d\r\n", currentLimitDown); } else if (keyTimer >= DEBOUNCE_TIME) { limitDownTrigger = !currentLimitDown; DebugPrint("LimitDown state: %d\r\n", limitDownTrigger); } } // 更新限位状态LED void UpdateLimitLED(void) { // 当两个限位都触发时LED常亮 if (limitUpTrigger && limitDownTrigger) { LIMIT_LED = 1; DebugPrint("Both limits triggered! LED on\r\n"); } else { LIMIT_LED = 0; } } // 进入测试模式 void EnterTestMode(void) { currentMode = MODE_TEST; testStep = TEST_STEP_1; testTimer = 0; keyPressCount = 0; MotorStop(); DebugPrint("Entering TEST mode\r\n"); // 使用全局变量loopCounter替代局部变量i for (loopCounter = 0; loopCounter < 5; loopCounter++) { LED_PIN = 1; LIMIT_LED = 1; KEY_LED = 1; DelayMs(50); LED_PIN = 0; LIMIT_LED = 0; KEY_LED = 0; DelayMs(50); } } // 退出测试模式 void ExitTestMode(void) { currentMode = MODE_WORK; testStep = TEST_STEP_0; testTimer = 0; MotorStop(); DebugPrint("Exiting TEST mode\r\n"); LED_PIN = 1; LIMIT_LED = 1; KEY_LED = 1; DelayMs(300); LED_PIN = 0; LIMIT_LED = 0; KEY_LED = 0; } // 处理测试模式 void ProcessTestMode(void) { testTimer++; // 更新测试计时器 switch (testStep) { case TEST_STEP_1: DebugPrint("Test Step 1: Moving forward to upper limit\r\n"); if (limitUpTrigger) { testStep = TEST_STEP_2; MotorStop(); testTimer = 0; LED_PIN = 1; LIMIT_LED = 1; KEY_LED = 1; DelayMs(300); LED_PIN = 0; LIMIT_LED = 0; KEY_LED = 0; DebugPrint("Upper limit triggered, moving to Step 2\r\n"); } else { RunMotorForward(); } break; case TEST_STEP_2: DebugPrint("Test Step 2: Moving backward\r\n"); if (testTimer >= TEST_TIMER) { testStep = TEST_STEP_3; testTimer = 0; MotorStop(); DebugPrint("Timer expired, moving to Step 3\r\n"); } else { RunMotorBackward(); } break; case TEST_STEP_3: DebugPrint("Test Step 3: Completing test\r\n"); if (testTimer >= TEST_TIMER) { ExitTestMode(); DebugPrint("Test completed\r\n"); } break; } } // 正转电机 void RunMotorForward(void) { if (currentStep < TOTAL_STEPS && !motorPaused) { MotorStep(currentStep % 4); currentStep++; motorPaused = 0; DebugPrint("Motor forward: Step %d\r\n", currentStep); } else { motorPaused = 1; DebugPrint("Motor forward paused\r\n"); } } // 反转电机 void RunMotorBackward(void) { if (currentStep < TOTAL_STEPS && !motorPaused) { MotorStep(3 - (currentStep % 4)); currentStep++; motorPaused = 0; DebugPrint("Motor backward: Step %d\r\n", currentStep); } else { motorPaused = 1; DebugPrint("Motor backward paused\r\n"); } } // 处理工作模式 void ProcessWorkMode(void) { if (keyPressCount > 0 && keyState == 0) { DebugPrint("Work mode key press detected: Count %d\r\n", keyPressCount); switch (keyPressCount) { case 1: // 电机保持上限位 DebugPrint("Key 1 pressed\r\n"); if (!limitUpTrigger) { RunMotorForward(); DebugPrint("Moving forward to upper limit\r\n"); } else { MotorStop(); DebugPrint("Already at upper limit, stopping\r\n"); } break; case 2: // 电机正转到上限位 DebugPrint("Key 2 pressed\r\n"); RunMotorForward(); DebugPrint("Moving forward continuously\r\n"); break; case 3: // 进入测试模式 DebugPrint("Key 3 pressed\r\n"); EnterTestMode(); break; } keyPressCount = 0; } } // 调试打印函数 void DebugPrint(const char* format, ...) { va_list args; va_start(args, format); vprintf(format, args); va_end(args); } 根据我写的代码,按键按下没有反应以及led只有一个亮
07-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值