本帖最后由 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的配置内容往往有不一样,学习起来,难度不是一般的高,我只能一点点摸索。
|