本帖最后由 suncat0504 于 2022-7-20 08:53 编辑
PIC18F57Q43 Curiosity Nano开发板的管脚构成图如下: 准备使用RF4~RF7控制一个2相4线的步进电机。电机参数如下: 控制时序:
实际测试时,发现这个相序控制效果不是太好,于是改用以下方式处理: uint8_t F_Rotation[4]={0x10,0x20,0x40,0x80};//正转表格 按照从0-3的顺序发送数据给步进电机的接口,可以让步进电机正转;按照从3-0的顺序发送数据给步进电机的接口,可以让步进电机反转。 在程序中使用Timer1设备,按照固定的间隔周期发送相序数据,驱动步进电机正反转。改变这个周期,就能改变步进电机的转速。关键代码如下: uint8_t F_Rotation[4]={0x10,0x20,0x40,0x80};//正转表格
uint8_t B_Rotation[4]={0x80,0x40,0x20,0x10};//反转表格
#define STEP_MAX 4
//// 方式B,根据电机参数说明
//uint8_t F_Rotation[8]={0x80,0xC0,0x40,0x60,0x20,0x30,0x10,0x90};//正转表格
//uint8_t B_Rotation[8]={0x80,0xC0,0x40,0x60,0x20,0x30,0x10,0x90};//反转表格
//#define STEP_MAX 8
// 步进电机正反转标志
uint8_t fb_flag=0;
// 步进电机当前驱动相序
uint8_t stepmotor_pos=0;
// 步进间隔计数周期
uint32_t step_period_ms=2;
// 定时器1的初始化配置
void TMR1_Initialize(void) {
//Set the Timer to the options selected in the GUI
//T1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
T1GCON = 0x00;
//GSS T1G_pin;
T1GATE = 0x00;
//CS FOSC/4;
T1CLK = 0x01;
//TMR1H 255;
TMR1H = 0xFF;
//TMR1L 6;
TMR1L = 0x06;
// Clearing IF flag before enabling the interrupt.
PIR3bits.TMR1IF = 0;
// Load the TMR value to reload variable
timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L);
// Enabling TMR1 interrupt.
PIE3bits.TMR1IE = 1;
// Set Default Interrupt Handler
TMR1_SetInterruptHandler(TMR1_DefaultInterruptHandler);
// CKPS 1:1; NOT_SYNC synchronize; TMR1ON enabled; T1RD16 disabled;
T1CON = 0x01;
}
// 定时器1中断,设计为1ms周期
void TMR1_DefaultInterruptHandler(void){
uint8_t next_step=0;
// add your TMR1 interrupt custom code
// or set custom function using TMR1_SetInterruptHandler()
LATFbits.LATF3 = ~LATFbits.LATF3;
if (fb_flag>0) {
// 每间隔固定时间让步进马达走一步
timer1_int_cnt++;
if (timer1_int_cnt==step_period_ms) {
timer1_int_cnt=0;
if (fb_flag==1) {
// 正转场合
stepmotor_pos=(stepmotor_pos+1)%STEP_MAX;
} else if (fb_flag==2) {
// 反转场合
stepmotor_pos=(stepmotor_pos+STEP_MAX-1)%STEP_MAX;
}
next_step=F_Rotation[stepmotor_pos];
LATF = (LATF & 0x0F) | next_step;
}
} else {
timer1_int_cnt=0;
LATF = LATF & 0x0F;
}
}
定时器1 的固定周期中断处理中,累加timer1_int_cnt,当满足计数周期时,取得下一个要发送的相序数据。 正转场合,是按照正向获取相序数据的:stepmotor_pos=(stepmotor_pos+1)%STEP_MAX; 反转场合,是按照反向获取相序数据的:stepmotor_pos=(stepmotor_pos+STEP_MAX-1)%STEP_MAX; 这样处理,可以保证正反转换时,保证相序的连续性。因为使用RF4-RF7作为2相四线步进电机的控制接口,使用RF3控制开发板上的LED0,所以发送控制数据时,使用以下代码,以保证RF的低四位接口数据不变。 LATF = (LATF & 0x0F) | next_step; 在主程序中,使用开发板仅有的一个按钮,来实现电机正转、反转、停转三种方式的交替转换。 if (!SW0_GetValue()) {
__delay_ms(50); // 消除抖动的处理
if (!SW0_GetValue()) {
// 指示灯显示变化
LED0_Toggle();
// 正反转标志0-stop.1-正转,2-反转
fb_flag=(fb_flag+1)%3;
// 串口输出信息
printf("BUTTON PRESSED\r\n");
// 等待按钮松开
while (!SW0_GetValue());
}
}
实际测试时,通过示波器的测量可以看到,LED0的闪烁周期是2.5ms左右,那么Timer1的中断周期就是1.25ms左右(根据MCC是设置为1ms的),同时意味着步进马达每两个相序数据之间的间隔周期为2.5ms(step_period_ms=2)。
通过视频可以看出,这个电机转速用于控制光强检测板,应该是可以的,可能还有点快。但这里仅仅是为了演示同定时器驱动步进电机的转动。实际应用的时候,可能是在主程序中,每次转动一点角度,并检测光强的。速度不必很快,也不需要是连续的。下一步准备测试ADC处理,通过光电器件或者太阳能板取得和光强相关的电压并进行AD转换,配合步进电机的转动,找到光强最大的角度。 简单的测试是完成了,但我还是想吐槽下:这个AVR开发板是我用过的第二块使用MPLAB X IDE开发的开发板。因为PIC18F57Q43的中文资料不多,只能一点一点啃英文资料,对于学俄语的我,很难啊。同时,MPLAB X IDE的MCC配置环境中全部是英文,并且好多短语。不同MCU的配置内容往往有不一样,学习起来,难度不是一般的高,我只能一点点摸索。
|