我们看看步进电机的驱动函数:
step_motor.C
#include "step_motor.h"
void Step_Motor_Run(u8 step,u8 dir,u8 speed,u16 angle,u8 sta)
//step是节拍数,dir是方向 speed是速度 ganle是角度 sta是运行或停止
{
u16 j ;
u8 i = 0 ;
if(sta==1)
{
if(dir==0)//顺时针转
{
//28BYJ-48电机一个脉冲转过的角度:5.625/64,4096个脉冲转1圈
//90°就是1024个脉冲,angle度对应的脉冲=(64/45)*angle*8
for(j=0;j<64*angle/45;j++)
{
for(i=0;i<8;i+=8/step) //step是步进--就是节拍数
{
switch(i) //8拍8步
{
case 0:MOTOR_IN1=1;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=0;break;
//第一步,A 色=0,其他=1,输入刚好相反
case 1:MOTOR_IN1=1;MOTOR_IN2=1;MOTOR_IN3=0;MOTOR_IN4=0;break;
//第二步,A 色=0,B 色=0,其他=1,输入刚好相反
case 2:MOTOR_IN1=0;MOTOR_IN2=1;MOTOR_IN3=0;MOTOR_IN4=0;break;
//第三步,A 色=1,B 色=0,其他=1,输入刚好相反
case 3:MOTOR_IN1=0;MOTOR_IN2=1;MOTOR_IN3=1;MOTOR_IN4=0;break;
//第四步,A 色=1,B 色=0,B 色=0,其他=1,输入刚好相反
case 4:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=1;MOTOR_IN4=0;break;
//第五步,A 色=1,B 色=1,C 色=0,D 色=1,输入刚好相反
case 5:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=1;MOTOR_IN4=1;break;
case 6:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=1;break;
case 7:MOTOR_IN1=1;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=1;break;
}
delay_ms(speed);
}
}
}
else//逆时针转,把上面的switch倒过来
{
for(j=0;j<64*angle/45;j++)
{
for(i=0;i<8;i+=8/step) //step是步进--就是节拍数
{
switch(i) //8拍8步
{
case 0:MOTOR_IN1=1;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=1;break;
//第一步,A 色=0,其他=1,输入刚好相反
case 1:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=1;break;
//第二步,A 色=0,B 色=0,其他=1,输入刚好相反
case 2:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=1;MOTOR_IN4=1;break;
//第三步,A 色=1,B 色=0,其他=1,输入刚好相反
case 3:MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=1;MOTOR_IN4=0;break;
//第四步,A 色=1,B 色=0,B 色=0,其他=1,输入刚好相反
case 4:MOTOR_IN1=0;MOTOR_IN2=1;MOTOR_IN3=1;MOTOR_IN4=0;break;
//第五步,A 色=1,B 色=1,C 色=0,D 色=1,输入刚好相反
case 5:MOTOR_IN1=0;MOTOR_IN2=1;MOTOR_IN3=0;MOTOR_IN4=0;break;
case 6:MOTOR_IN1=1;MOTOR_IN2=1;MOTOR_IN3=0;MOTOR_IN4=0;break;
case 7:MOTOR_IN1=1;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=0;break;
}
delay_ms(speed);
}
}
}
}
else//sta==0 ,电机停止
{
MOTOR_IN1=0;MOTOR_IN2=0;MOTOR_IN3=0;MOTOR_IN4=0;//电机停止
}
}
#ifndef __STEP_MOTOR_
#define __STEP_MOTOR_
#include "config.h"
#define MOTOR_IN1 P10
#define MOTOR_IN2 P11
#define MOTOR_IN3 P13
#define MOTOR_IN4 P14
#define STEPMOTOR_MAXSPEED1
#define STEPMOTOR_MINSPEED5
void Step_Motor_Run(u8 step,u8 dir,u8 speed,u16 angle,u8 sta);
//step是节拍数,dir是方向 speed是速度 ganle是角度 sta是运行或停止
#endif
看看主函数:
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-03-03) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "key.h"
#include "step_motor.h"
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
u8 key=0;//保存按键值
u8 run=0;//1运行0停止
u8 dir=0;//0是逆时针1是顺时针
u8 speed = STEPMOTOR_MAXSPEED;
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
USBLIB_OUT_Done(); //查询方式处理USB接收的数据
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
key = KEY_Scan(0); //mode=0 单击 mode=1 长按
if(key==KEY1_PRESS) run=!run; //K1控制启停
else if(key==KEY2_PRESS) dir=!dir;//K2控制方向
else if(key==KEY3_PRESS) //K3控制减速
{
speed++;
if(speed>STEPMOTOR_MINSPEED )
speed= STEPMOTOR_MINSPEED;
}
else if(key==KEY4_PRESS) //K4控制加速
{
speed--;
if(speed<STEPMOTOR_MAXSPEED )
speed= STEPMOTOR_MAXSPEED;
}
Step_Motor_Run(8,dir,speed,1,run);//第4个变量是角度
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
14.1-外部中断实验-简介1-外部中断实验-简介
本讲主要内容
1.实验介绍
2.硬件设计
3.软件设计
4.实验现象
1.2 实验目的
使用K1和K2配置外部中断功能,K3和K4配置普通I0口中断功能,K1-K4控制LED1-LED4亮灭。
我的实验板HC6800-ES V2.0 K1 对应P5.1 K2对应P5.2 K3对应P3.2 K4对应P3.3,所以我要把K3和K4配置外部中断功能,K1和K2配置普通I0口中断功能,K1-K4控制LED1-LED4亮灭。
重点是软件配置:
简单说:4个开关是高阻输入 使能上拉
P20---P23设置为推挽输出 使能上拉
使能系统时钟
使能外部中断1外部中断2
IO口中断我们是这样:K1对应P51 和K2 对应P50 要允许IO口下降沿中断
按上面的设置,生成框架:
特别注意普通IO口中断的设置:
直接在管脚IO口设置选择就OK
这里IO口中断,键的判断:
看看port.c:
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: port.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-03-04) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h"
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "key.h"
#include "led.h"
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// P2口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT2_Init(void)
{
SetP2nInitLevelHigh(PIN_ALL); //设置P2初始化电平
SetP2nQuasiMode(PIN_7 | PIN_6 | PIN_5 | PIN_4); //设置P2.7,P2.6,P2.5,P2.4为准双向口模式
SetP2nPushPullMode(PIN_3 | PIN_2 | PIN_1 | PIN_0); //设置P2.3,P2.2,P2.1,P2.0为推挽输出模式
EnableP2nPullUp(PIN_3 | PIN_2 | PIN_1 | PIN_0); //使能P2.3,P2.2,P2.1,P2.0内部上拉电阻
DisableP2nPullUp(PIN_7 | PIN_6 | PIN_5 | PIN_4); //关闭P2.7,P2.6,P2.5,P2.4内部上拉电阻
DisableP2nPullDown(PIN_ALL); //关闭P2内部下拉电阻
DisableP2nSchmitt(PIN_ALL); //使能P2施密特触发
SetP2nSlewRateNormal(PIN_ALL); //设置P2一般翻转速度
SetP2nDrivingNormal(PIN_ALL); //设置P2一般驱动能力
SetP2nDigitalInput(PIN_ALL); //使能P2数字信号输入功能
//<<AICUBE_USER_PORT2_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_PORT2_INITIAL_END>>
}
////////////////////////////////////////
// P3口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT3_Init(void)
{
SetP3nInitLevelHigh(PIN_ALL); //设置P3初始化电平
SetP3nQuasiMode(PIN_7 | PIN_6 | PIN_5 | PIN_2); //设置P3.7,P3.6,P3.5,P3.2为准双向口模式
SetP3nHighZInputMode(PIN_4 | PIN_3 | PIN_1 | PIN_0); //设置P3.4,P3.3,P3.1,P3.0为高阻输入模式
EnableP3nPullUp(PIN_4 | PIN_3); //使能P3.4,P3.3内部上拉电阻
DisableP3nPullUp(PIN_7 | PIN_6 | PIN_5 | PIN_2 | PIN_1 | PIN_0); //关闭P3.7,P3.6,P3.5,P3.2,P3.1,P3.0内部上拉电阻
DisableP3nPullDown(PIN_ALL); //关闭P3内部下拉电阻
DisableP3nSchmitt(PIN_ALL); //使能P3施密特触发
SetP3nSlewRateNormal(PIN_ALL); //设置P3一般翻转速度
SetP3nDrivingNormal(PIN_ALL); //设置P3一般驱动能力
SetP3nDigitalInput(PIN_ALL); //使能P3数字信号输入功能
//<<AICUBE_USER_PORT3_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_PORT3_INITIAL_END>>
}
////////////////////////////////////////
// P5口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT5_Init(void)
{
SetP5nInitLevelHigh(PIN_ALL); //设置P5初始化电平
SetP5nQuasiMode(PIN_7 | PIN_6 | PIN_5 | PIN_4 | PIN_3 | PIN_2); //设置P5.7,P5.6,P5.5,P5.4,P5.3,P5.2为准双向口模式
SetP5nHighZInputMode(PIN_1 | PIN_0); //设置P5.1,P5.0为高阻输入模式
EnableP5nPullUp(PIN_1 | PIN_0); //使能P5.1,P5.0内部上拉电阻
DisableP5nPullUp(PIN_7 | PIN_6 | PIN_5 | PIN_4 | PIN_3 | PIN_2); //关闭P5.7,P5.6,P5.5,P5.4,P5.3,P5.2内部上拉电阻
DisableP5nPullDown(PIN_ALL); //关闭P5内部下拉电阻
DisableP5nSchmitt(PIN_ALL); //使能P5施密特触发
SetP5nSlewRateNormal(PIN_ALL); //设置P5一般翻转速度
SetP5nDrivingNormal(PIN_ALL); //设置P5一般驱动能力
SetP5nDigitalInput(PIN_ALL); //使能P5数字信号输入功能
SetP5nFallingInt(PIN_1 | PIN_0); //设置P5.1,P5.0为下降沿中断
EnableP5nInt(PIN_1 | PIN_0); //使能P5.1,P5.0口中断
SetP5IntPriority(0); //设置中断为最低优先级
//<<AICUBE_USER_PORT5_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_PORT5_INITIAL_END>>
}
////////////////////////////////////////
// P5中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT5_ISR(void) interrupt P5INT_VECTOR
{
//<<AICUBE_USER_PORT5_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
uint8_t intf;
intf = CheckP5nFlag(PIN_ALL); //读取中断请求标志
ClearP5nFlag(PIN_ALL); //清除中断请求标志
if(intf & 0X01)//判断是否P50按下01就是P50,02就是P51,04就是P52,08--P53,10--P54
{
delay_ms(10);
if(intf & 0X01)
{
printf_usb("K2(P50)按下!\r\n"); // 发送字符串“K2(P50)按下!”
LED2=!LED2; //LED1反转
}
}
else if(intf & 0X02)//判断是否P51按下01就是P50,02就是P51,04就是P52,08--P53,10--P54
{
delay_ms(10);
if(intf & 0X02)
{
printf_usb("K1(P51)按下!\r\n"); // 发送字符串“K1(P51)按下!”
LED1=!LED1; //LED1反转
}
}
//<<AICUBE_USER_PORT5_ISR_CODE1_END>>
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>