用stc32配合oled屏做了个剪线机,长度可调,可显示剪切次数
下面是代码,欢迎指导改正。
- // 剪线机 时钟24MHz OLED显示(K1暂停+K2开始版)
- #include "stc.h" // STC32G 寄存器定义(需适配24MHz)
- #include "oled.h" // OLED驱动(128x64 I2C)
- #include "iic.h"
- #include <intrins.h>
-
- // 宏定义(优化精度和保护阈值)
- #define DELAY_TIME 2000
- #define STEPS_PER_CM 56.5f // 每厘米步数(根据实际电机校准)
- #define MIN_DISTANCE 10 // 最小剪线长度(cm)
- #define MAX_DISTANCE 100 // 最大剪线长度(cm)
- #define DEFAULT_DISTANCE 70 // 默认长度(cm)
- #define SERVO_OPEN 600 // 舵机打开(0.6ms,安全范围)
- #define SERVO_CUT 1500 // 舵机剪切(1.5ms,中间位置)
- #define PWM_CYCLE 20000 // 舵机PWM周期(20ms,标准舵机要求)
- #define PULSE_MIN 500 // 舵机最小脉冲(避免损坏)
- #define PULSE_MAX 2500 // 舵机最大脉冲
- #define KEY_DELAY 20 // 按键消抖延时(ms)
- #define STEP_PULSE_US 400 // 步进电机脉冲宽度(us)
-
- // 全局变量(新增pause暂停标志,优化状态管理)
- bit start = 0; // 启动标志(1=运行,0=待机)
- bit stop = 0; // 紧急停止标志(最高优先级,复位所有)
- bit pause = 0; // 暂停标志(1=暂停,0=正常)
- bit moving = 0; // 电机运行标志
- bit cut_flag = 0; // 剪切触发标志(单次剪切完成)
- unsigned long steps_completed = 0; // 已运行步数
- unsigned int target_distance = DEFAULT_DISTANCE; // 目标剪线长度(cm)
- unsigned long total_steps = 0; // 总需步数(target_distance * STEPS_PER_CM)
- unsigned int run_count = 0; // 运行次数统计
- unsigned char PWM = 10; // 初始脉宽1.5ms(对应90°),范围:10(0.5ms)~50(2.5ms)
- unsigned int count = 0; // 计数器变量,用于计时中断周期
-
- // 引脚定义(明确按键功能)
- sbit K1 = P1^0; // 暂停按键(仅运行中有效)
- sbit K2 = P1^1; // 开始按键(待机/暂停状态有效)
- sbit K3 = P1^4; // 增加长度按键(+5cm,仅待机/暂停有效)
- sbit K4 = P1^5; // 减少长度按键(-5cm,仅待机/暂停有效)
- sbit SG_PWM = P2^0; // 舵机PWM输出引脚(定时器0控制)
- sbit DIR = P2^3; // 步进电机方向引脚(0=正转,1=反转)
- sbit STEP = P2^4; // 步进电机脉冲引脚
- sbit EN = P2^5; // 步进电机使能引脚(1=失能,0=使能)
-
- // 函数声明
- void sys_init(void); // 系统初始化
- void key_scan(void); // 按键扫描(带消抖)
- void key_process(unsigned char key); // 按键功能处理
- void stepper_single_step(void); // 步进电机单步驱动
- void run_stepper_motor(void); // 电机运行+剪切逻辑
- void oled_update(void); // OLED实时更新
- void delay_us(unsigned int us); // 微秒延时(24MHz适配)
- void Timer0_Init(void); // 定时器0初始化(补充声明)
- extern void delay_ms(unsigned int ms); // 复用oled.c的毫秒延时
-
-
- /************************** 系统初始化 **************************/
- void sys_init(void) {
- // 1. 时钟与端口配置
- WTST = 0; // CPU无等待周期
- EAXFR = 1; // 允许访问扩展寄存器
- CKCON = 0x00; // XRAM访问速度稳定
- P0PU = 0xFF; // 所有端口上拉(抗干扰)
- P1PU = 0xFF;
- P2PU = 0xFF;
- P3PU = 0xFF;
-
- // 2. 引脚模式配置
- P1M0 = 0x00; P1M1 = 0x00; // P1口(按键)准双向输入
- P2M0 = 0x1B; P2M1 = 0x00; // P2.0/P2.3/P2.4/P2.5推挽输出
- P3M0 = 0x00; P3M1 = 0x00; // 其他端口默认
-
- // 3. 电机初始化(失能状态)
- EN = 1; // 电机失能
- DIR = 0; // 默认正转
- STEP = 0; // 脉冲初始低电平
-
- // 4. 全局变量初始化
- start = 0;
- stop = 0;
- pause = 0;
- moving = 0;
- cut_flag = 0;
- steps_completed = 0;
- target_distance = DEFAULT_DISTANCE;
- total_steps = (unsigned long)(target_distance * STEPS_PER_CM);
- run_count = 0;
-
- // 5. 外设初始化
- Timer0_Init(); // 初始化定时器0(生成50us中断)
- OLED_Init(); // OLED初始化
- OLED_BuffClear();// 清空缓冲区
-
- // 6. OLED初始显示(明确状态)
- OLED_BuffShowString(0, 0, "Long: ", 0);
- OLED_BuffShowNum(64, 0, target_distance, 3); // 3位数字对齐
- OLED_BuffShowString(96, 0, "cm", 0);
- OLED_BuffShowString(0, 2, "No: ", 0);
- OLED_BuffShowNum(64, 2, run_count, 3);
- OLED_BuffShowString(96, 2, "Stop", 0); // 初始待机状态
- OLED_BuffShow();
- }
-
- /************************** 按键扫描(带消抖) **************************/
- void key_scan(void) {
- static unsigned char key_state = 0; // 0=空闲,1=消抖中,2=处理中
- static unsigned char key_val = 0; // 按键值(1=K1,2=K2,3=K3,4=K4)
- static unsigned int key_timer = 0; // 消抖计时
-
- if (key_state == 0) {
- // 检测按键按下
- if (K1 == 0) key_val = 1;
- else if (K2 == 0) key_val = 2;
- else if (K3 == 0) key_val = 3;
- else if (K4 == 0) key_val = 4;
- else return;
-
- key_state = 1;
- key_timer = 0;
- } else if (key_state == 1) {
- // 消抖等待(20ms)
- key_timer++;
- delay_ms(1);
- if (key_timer >= KEY_DELAY) {
- // 确认按键仍按下
- switch (key_val) {
- case 1: if (K1 == 0) key_state = 2; break;
- case 2: if (K2 == 0) key_state = 2; break;
- case 3: if (K3 == 0) key_state = 2; break;
- case 4: if (K4 == 0) key_state = 2; break;
- default: key_state = 0; break;
- }
- }
- } else if (key_state == 2) {
- // 执行按键功能
- key_process(key_val);
- // 等待按键释放(避免长按重复触发)
- while (!(K1 && K2 && K3 && K4 )) delay_ms(1);
- key_state = 0;
- }
- }
-
- /************************** 按键功能处理(核心修改) **************************/
- void key_process(unsigned char key) {
- switch (key) {
- // 1. K1:暂停按键(仅运行中有效)
- case 1:
- if (start && !pause &&!stop ) { // 只有运行中才能暂停
- pause = 1;
- moving = 0;
- EN = 1; // 电机失能
- PWM = 10 ; // 舵机复位
- run_count= 0;
- OLED_BuffClearLine(2); // 清空状态行(第4行
- OLED_BuffShowString(0, 2, "No: ", 0);
- OLED_BuffShowNum(64, 2, run_count, 0); // 保留计数
- OLED_BuffShowString(96, 2, "Stop", 0);
- OLED_BuffShow();
- }
- break;
-
- // 2. K2:开始按键(待机/暂停状态有效)
- case 2:
-
- if (!start || pause) { // 待机或暂停状态均可启动
- start = 1;
- pause = 0; // 取消暂停
- cut_flag = 0;
- // 若未完成步数,继续运行;否则重置步数(新一次剪切)
- if (steps_completed >= total_steps) {
- steps_completed = 0;
- }
- OLED_BuffClearLine(2);
- OLED_BuffShowString(0, 2, "No: ", 0);
- OLED_BuffShowNum(64, 2, run_count, 0);
- OLED_BuffShowString(96, 2, "Run ", 0); // 空格对齐,避免残留
- OLED_BuffShow();
- }
- break;
-
- // 3. K3:增加长度(+5cm,仅待机/暂停有效)
- case 3:
- if (!start || pause) { // 非运行状态才能调整
- if (target_distance < MAX_DISTANCE) {
- target_distance += 5;
- total_steps = (unsigned long)(target_distance * STEPS_PER_CM);
- OLED_BuffClearLine(0);
- OLED_BuffShowString(0, 0, "Long: ", 0);
- OLED_BuffShowNum(64, 0, target_distance, 3); // 强制3位显示
- OLED_BuffShowString(96, 0, "cm", 0);
- OLED_BuffShow();
- }
- }
- break;
-
- // 4. K4:减少长度(-5cm,仅待机/暂停有效)
- case 4:
- if (!start || pause) { // 非运行状态才能调整
- if (target_distance > MIN_DISTANCE) {
- target_distance -= 5;
- total_steps = (unsigned long)(target_distance * STEPS_PER_CM);
- OLED_BuffClearLine(0);
- OLED_BuffShowString(0, 0, "Long: ", 0);
- OLED_BuffShowNum(64, 0, target_distance, 3); // 强制3位显示
- OLED_BuffShowString(96, 0, "cm", 0);
- OLED_BuffShow();
- }
- }
- break;
- }
- }
-
- /************************** 步进电机单步驱动 **************************/
- void stepper_single_step(void) {
- STEP = 1;
- delay_us(STEP_PULSE_US);
- STEP = 0;
- delay_us(STEP_PULSE_US);
- }
-
- /************************** 电机运行+剪切逻辑(适配暂停功能) **************************/
- void run_stepper_motor(void) {
- // 运行条件:启动=1、无紧急停止、无暂停、未完成剪切
- if (start && !stop && !pause && !cut_flag && steps_completed < total_steps) {
-
- EN = 0; // 使能电机
- moving = 1; // 标记电机运行中
- stepper_single_step();
- steps_completed++;
-
- // 步数完成→执行剪切
- if (steps_completed >= total_steps) {
- moving = 0;
- EN = 1; // 电机失能
- PWM = 30; // 剪切
- delay_ms(500); // 保持500ms
- PWM = 10; // 复位
- delay_ms(500); // 复位等待
- run_count++; // 计数+1
- OLED_BuffClearLine(2); // 清空计数行(第2行)
- OLED_BuffShowString(0, 2, "No: ", 0);
- OLED_BuffShowNum(64, 2, run_count, 3);
- OLED_BuffShowString(96, 2, "Run ", 0);
- OLED_BuffShow();
- OLED_BuffShow();
- cut_flag = 0; // 单次剪切完成
- delay_ms(500); // 延时等待
- steps_completed = 0; // 重置步数,自动启动下一次
- }
- }
- }
-
- /**************************
- * 定时器0初始化:50us中断一次(24MHz 1T模式)
- **************************/
- void Timer0_Init(void) {
- AUXR |= 0x80; // 定时器0时钟1T模式(加速模式)
- TMOD &= 0xF0; // 定时器0工作模式:模式0(16位自动重装)
- TL0 = 0x10; // 50us中断初值:TL0=0x10(64336 = 0xFC10)
- TH0 = 0xFC; // 50us中断初值:TH0=0xFC
- TF0 = 0; // 清除定时器0溢出标志
- TR0 = 1; // 启动定时器0
- ET0 = 1; // 使能定时器0中断
- EA = 1; // 开启总中断
- }
-
- /**************************
- * 定时器0中断服务程序:生成PWM波形
- **************************/
- void Timer0_Isr(void) interrupt 1 {
- count++; // 每50us计数一次
-
- // 输出PWM高/低电平(脉宽由PWM变量控制)
- SG_PWM = (count <= PWM) ? 1 : 0;
-
- // 20ms周期结束,计数器复位(400 * 50us = 20ms)
- if (count >= 400) {
- count = 0; // 清零计数器,开始下一个周期
- }
- }
-
-
-
- /************************** 延时函数 **************************/
- void delay_us(unsigned int us) {
- unsigned int i;
- for (i = 0; i < us * 3; i++) { // 24MHz下≈1us
- _nop_(); _nop_(); _nop_(); _nop_();
- }
- }
-
- /************************** 主函数 **************************/
- void main(void) {
- sys_init();
-
- while (1) {
- key_scan(); // 按键扫描
- run_stepper_motor(); // 核心控制逻辑
- }
- }
复制代码
|