最近参加一个农业机器人的比赛,由于今年的题目是蔬菜幼苗自动搬运,因此搬运部分需要用到一个三轴运动的装置,我们参考了3D打印机的原理,上面通过步进电机控制丝杆和皮带从而带动我们的抓手来抓举幼苗。因为比赛的幼苗和幼苗的基质比较小,这个过程需要精度比较高,查询了一些资料后,我想到了用dma来给STM32单片机的定时器寄存器ARR发送数据来精准控制输出pwm的数量,从而可以精准控制步进电机转动的度数,可以十分方便的计算出到某个位置需要的脉冲。
上图为我们的装置的三维图。
stm32的DMA功能不需要使用中断,这是我选用这个方式的主要原因,因为我们这个项目所需要的步进电机比较多 ,如果通过中断的方式必然会使我们的程序比较混乱,而通过DMA的功能不占用CPU的运行,直接在目标地址之间发送数据。只要我们设置一个数组,将数组的最后一位设置为0,数组的长度就为pwm脉冲的数量,数组的数据就为ARR的值(即控制输出pwm的频率大小),十分方便。但这个方法有一个缺点就是如此长的数组比较占内存空间,这个可以通过共用一个数组和减少细分等方法解决。
单片机源程序如下:
- #include "led.h"
- #include "delay.h"
- #include "key.h"
- #include "sys.h"
- #include "usart.h"
- #include "timer.h"
- #include "dma.h"
- /************************************************
- dma + pwm 测试代码
-
- ************************************************/
- #define size 8000
- u16 send_buf[size];
- u32 i;
- void pwm_out(int step_count,int arr)
- {
- for(i=0;i<step_count;i++)
- {
- if(i < step_count-1)
- send_buf[i]=arr;
- else
- send_buf[i]=0;
- }
- MYDMA_Enable(DMA1_Channel6,step_count);
- }
- int main(void)
- {
- u8 count = 5;
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
- LED_Init(); //LED端口初始化
- MYDMA_Config(DMA1_Channel6, (u32)&TIM3->ARR, (u32)send_buf, size);
- TIM3_PWM_Init(2000,100-1); //不分频。PWM频率=72000000/900=80Khz PA6
- TIM_SetCompare1(TIM3,500);
- pwm_out(1000,1000);
-
-
- while(1)
- {
-
- if(TIM3->ARR==0)
- {
- pwm_out(1000,1000);
- }
- delay_ms(50000);
-
- }
- }
复制代码
下载:
dma控制pwm测试代码.7z
(186.23 KB, 下载次数: 321)
|