赞
踩
目录
第一章 绪论 1
基于 stm32 微控制器的绘图机器人研究设计的目的 1
基于 stm32 微控制器的绘图机器人研究设计的设计功能 1
第二章 系统整体方案设计 2
第三章 硬件设计 4
硬件电路资源使用设计 4
1.1 STM32F103RBT6 片上资源 4
1.2 外围芯片资源 4
机械结构设计 5
通信原理 9
第四章 软件设计 11
上位机程序设计 11
1.1 二值化算法 11
1.2 轮廓化算法 13
1.3 描边算法 14
1.4 串口通信数据格式 16
下位机程序设计 17
2.1 缓冲区算法 17
2.2 Bresenham 直线算法 17
2.3 坐标轴的确定 19
第五章 系统调试与实验结果 21
系统调试 21
实验结果 24
参 考 文 献 25
致 谢 26
附 录 27
通信原理
图 3-6 组装实物图
下位机采用 STM32 作为控制器。STM32 使用 CH340G 与计算机端串口连接,不仅提 供到 PC 的串行连接,还提供主控供电。STM32 通过 2 个计时器输出 3 路 PWM 方波,通 过 3 个 GPIO 引脚输出数字电平或数字式脉冲信号。开发环境为 MDK。
把足够功率和频率的脉冲波按照一定的顺序传到步进电机,才能驱动步进电机转动。
步进电机驱动模块接收控制 PWM 信号、方向(DIR)电平和使能(EN)信号,并按照步 进电机分配方式所要求的状态顺序来产生各相控信号,步进电机驱动模块输出信号数与电 机相数相同。DRV8825 每接收一个 PWM 脉冲信号,DRV8825 就输出一个由 DIR、EN、 STEP 综合决定的步进电机驱动信号。信号的产生特点在 MDK 中编写,使 STM32 产生控 制脉冲信号和方向电平。步进电机驱动模块采用 DRV8825。DRV8825 是一款带过流保护和 转换器的 DMOS 微步驱动器,在“STEP”中输入一个脉冲,即可驱动电动机产生微步。 只要控制 STEP 和 DIR 就可以了,STEP 是控制脉冲输入端,DIR 是方向电平输入端;3 个 模式选择端 MS1、MS2、MS3 全部接地即使用 32 细分,如果要求更高的精度,可通过选 其他模式,如选择 1/32 步迸模式,电机转一圈就要送 6400 个微步才能完成。控制脉冲发 生器和驱动器的结构示意图如图 2-7 所示。
图 3-7 控制脉冲发生器和驱动器的结构
第四章 软件设计
绘图机器人运行中步进电机使用脉冲控制,STM32 发出与 42 步进电机前进距离的对 应控制信号和 PWM 信号。两点确定一条线段,由于串口速度较慢所以采用 div 参数增加细 分的方式减少串口数据传输量。给出两点 STM32 就会通过 Bresenham 直线算法,计算出其 间的各个点,再通过前后两点的位置关系完成绘图任务。
#include "bsp.h" void SW_GPIO_Config(void) //限位开关GPIO初始化 校准用限位 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(TOPSWITCHCLK|RCC_APB2Periph_AFIO,ENABLE ); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU ; GPIO_InitStructure.GPIO_Pin=TOPSWITCHPIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(TOPSWITCHPORT,&GPIO_InitStructure); RCC_APB2PeriphClockCmd(LEFTSWITCHCLK|RCC_APB2Periph_AFIO,ENABLE ); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU ; GPIO_InitStructure.GPIO_Pin=LEFTSWITCHPIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(LEFTSWITCHPORT,&GPIO_InitStructure); { // GPIO_EXTILineConfig(TOP_SWITCH_PORT_SOURCE, TOP_SWITCH_PIN_SOURCE); // GPIO_EXTILineConfig(LEFT_SWITCH_PORT_SOURCE, LEFT_SWITCH_PIN_SOURCE); // // EXTI_InitTypeDef EXTI_InitStructure; // EXTI_InitStructure.EXTI_Line = LEFT_SWITCH_INT_EXTI_LINE; // EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // EXTI_InitStructure.EXTI_LineCmd = ENABLE; // EXTI_Init(&EXTI_InitStructure); // // EXTI_InitStructure.EXTI_Line = TOP_SWITCH_INT_EXTI_LINE; // EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // EXTI_InitStructure.EXTI_LineCmd = ENABLE; // EXTI_Init(&EXTI_InitStructure); // // NVIC_InitTypeDef NVIC_InitStructure; // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // // NVIC_InitStructure.NVIC_IRQChannel = TOP_SWITCH_INT_EXTI_IRQ; //TOPSW外部中断线 // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); // // NVIC_InitStructure.NVIC_IRQChannel = LEFT_SWITCH_INT_EXTI_IRQ; //LEFTSW外部中断线 // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); } } void MOT_GPIO_Config(void)//MOT pwm、GPIO初始化函数 { //Tim2 --- ch1 A0 GPIO_InitTypeDef TOP_TIMGPIO_InitStructure; RCC_APB2PeriphClockCmd (AFIOCLK ,ENABLE ); RCC_APB1PeriphClockCmd (TOP_MotSCLK,ENABLE ); TOP_TIMGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP ; TOP_TIMGPIO_InitStructure .GPIO_Pin =TOP_MotSPIN; TOP_TIMGPIO_InitStructure .GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(TOP_MotSPORT,&TOP_TIMGPIO_InitStructure); //TOP D--B6 GPIO_InitTypeDef TOP_DGPIO_InitStructure; RCC_APB2PeriphClockCmd (TOP_MotDCLK ,ENABLE ); TOP_DGPIO_InitStructure .GPIO_Mode =GPIO_Mode_Out_PP ; TOP_DGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; TOP_DGPIO_InitStructure .GPIO_Pin =TOP_MotDPIN; GPIO_Init(TOP_MotDPORT,&TOP_DGPIO_InitStructure); //Tim2 --- ch2 A1 GPIO_InitTypeDef BOT_TIMGPIO_InitStructure; RCC_APB2PeriphClockCmd (AFIOCLK ,ENABLE ); RCC_APB1PeriphClockCmd (BOT_MotSCLK,ENABLE ); BOT_TIMGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP ; BOT_TIMGPIO_InitStructure .GPIO_Pin =BOT_MotSPIN; BOT_TIMGPIO_InitStructure .GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(BOT_MotSPORT,&BOT_TIMGPIO_InitStructure); //BOT D--A8 GPIO_InitTypeDef BOT_DGPIO_InitStructure; RCC_APB2PeriphClockCmd (BOT_MotDCLK ,ENABLE ); BOT_DGPIO_InitStructure .GPIO_Mode =GPIO_Mode_Out_PP ; BOT_DGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; BOT_DGPIO_InitStructure .GPIO_Pin =BOT_MotDPIN; GPIO_Init(BOT_MotDPORT,&BOT_DGPIO_InitStructure); GPIO_InitTypeDef EGPIO_InitStructure; RCC_APB2PeriphClockCmd (MotECLK ,ENABLE ); EGPIO_InitStructure .GPIO_Mode =GPIO_Mode_Out_PP ; EGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; EGPIO_InitStructure .GPIO_Pin =MotEPIN; GPIO_Init(MotEPORT,&EGPIO_InitStructure); MOT_DISEN; GPIO_InitTypeDef DJ_GPIO_InitStructure; RCC_APB2PeriphClockCmd (AFIOCLK ,ENABLE ); RCC_APB1PeriphClockCmd (DJ_MotCLK,ENABLE ); DJ_GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP ; DJ_GPIO_InitStructure .GPIO_Pin =DJ_MotPIN; DJ_GPIO_InitStructure .GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(DJ_MotPORT,&DJ_GPIO_InitStructure); } void PWM_Config(u32 PWM1Freq)//Tim2 -PWM { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; u16 tim_period; u16 tim_pulse; tim_period=(u16)(TIM2_COUNTER_CLK/PWM1Freq-1); tim_pulse =(tim_period+1)*0.5;//默认占空比为50% TIM_TimeBaseStructure.TIM_Prescaler =0;//预分频为1 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;//向上计数 TIM_TimeBaseStructure.TIM_Period = tim_period; //定时周期 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2 ,&TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse =tim_pulse; TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; TIM_OC1Init(TIM2 ,&TIM_OCInitStructure); TIM_OC2Init(TIM2 ,&TIM_OCInitStructure); // TIM2->CCER&=~1 ;//通道1关闭 // TIM2->CCER&=~(1<<4) ;//通道2关闭 TIM_OC1PolarityConfig (TIM2,TIM_OCPreload_Enable ); TIM_OC2PolarityConfig (TIM2,TIM_OCPreload_Enable ); TIM_ARRPreloadConfig (TIM2,ENABLE ); TIM_Cmd (TIM2,ENABLE ); TIM2->DIER |=(u32)1;//tim2中断使能 // TIM2->CR2 &=~(u32)7<<4; } void DJ_PWM_Config(u32 PWM1Freq)//Tim4 -ch4 { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; u16 tim_period; u16 tim_pulse; tim_period=(u16)(TIM4_COUNTER_CLK/PWM1Freq-1); tim_pulse =(tim_period+1)*0.08;//默认占空比为8 x0.08 TIM_TimeBaseStructure.TIM_Prescaler =1000;//预分频为1 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;//向上计数 TIM_TimeBaseStructure.TIM_Period = tim_period; //定时周期 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse =tim_pulse; TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; TIM_OC4Init(TIM4 ,&TIM_OCInitStructure); TIM_OC1PolarityConfig (TIM4,TIM_OCPreload_Enable ); //TIM_OC4PolarityConfig (TIM4,TIM_OCPreload_Enable ); TIM_ARRPreloadConfig (TIM4,ENABLE ); TIM_Cmd (TIM4,ENABLE ); TIM4->CCER|=(1<<12) ;//通道4打开 //TIM2->DIER |=(u32)1;//tim2中断使能 // TIM2->CR2 &=~(u32)7<<4; } void DJ_PWM_Change(u8 t,u32 PWM1Freq) { u16 tim_period; u16 tim_pulse; tim_period=(u16)(TIM4_COUNTER_CLK/PWM1Freq-1); tim_pulse =(tim_period+1)*t/1000;//默认占空比为8 x0.08 DJ_TIM ->CCR4 = tim_pulse; } void TIM_NVIC_Config(void)//TIM2中断初始化 { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空模式 GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口的工作参数 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; // 配置波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 配置 针数据字长 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 配置停止位 USART_InitStructure.USART_Parity = USART_Parity_No ; // 配置校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 配置硬件流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 配置工作模式,收发一起 USART_Init(DEBUG_USARTx, &USART_InitStructure); // 完成串口的初始化配置 USART_NVIC_Config(); // 串口中断优先级配置 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口接收中断 USART_Cmd(DEBUG_USARTx, ENABLE); // 使能串口 } void Usart_SendByte( USART_TypeDef * pUSARTx, u8 ch)//发送一个字节 { USART_SendData(pUSARTx,ch); // 发送一个字节数据到USART while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); // 等待发送数据寄存器为空 } void Usart_SendArray( USART_TypeDef * pUSARTx, u8 *array, u16 num) //发送8位数组 { uint8_t i; for(i=0; i<num; i++) { Usart_SendByte(pUSARTx,array[i]); //发送一个字节数据到USART } while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET); //等待发送完成 } /***************** 发送字符串 **********************/ void Usart_SendString( USART_TypeDef * pUSARTx, u8 *str) { unsigned int k=0; do { Usart_SendByte( pUSARTx, *(str + k) ); k++; } while(*(str + k)!='\0'); while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET); /* 等待发送完成 */ } /***************** 发送一个16位数 **********************/ void Usart_SendHalfWord( USART_TypeDef * pUSARTx, u16 ch) { uint8_t temp_h, temp_l; /* 取出高八位 */ temp_h = (ch&0XFF00)>>8; /* 取出低八位 */ temp_l = ch&0XFF; /* 发送高八位 */ USART_SendData(pUSARTx,temp_h); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); /* 发送低八位 */ USART_SendData(pUSARTx,temp_l); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。