找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1946|回复: 0
收起左侧

使用单片机PWM使能L298N驱动TT马达,麦克拉姆轮小车驱动

[复制链接]
ID:744239 发表于 2020-8-15 16:41 | 显示全部楼层 |阅读模式
由于学习的需要,我们需要制作一个物料搬运小车。
经过与小伙伴的一番商讨之后,我们决定使用麦克拉姆轮和TT马达作为小车的底盘驱动。
电机驱动器我们选用的是L298N(便宜又简单。)
以下是个人写的一些代码,简单的封装几个小车前进后退,左右直走的函数。
麦克拉姆轮排列方式为X型。

单片机源程序如下:

  1. #include "motor.h"
  2. #include "stm32f10x.h"
  3. #include "stm32f10x_rcc.h"
  4. #include "delay.h"

  5. /************电机 A B C D 的使能输入PWM函数初始化部分************/

  6. static void GENERAL_TIM_GPIO_Config(void)
  7. {
  8.   GPIO_InitTypeDef GPIO_InitStructure;

  9.   // 输出比较通道A GPIO 初始化
  10.         RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
  11.   GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;
  12.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  13.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  14.   GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
  15.         
  16.         // 输出比较通道B GPIO 初始化
  17.         RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
  18.   GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH2_PIN;
  19.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  20.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  21.   GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
  22.         
  23.         // 输出比较通道C GPIO 初始化
  24.         RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
  25.   GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH3_PIN;
  26.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  27.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  28.   GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);
  29.         
  30.         // 输出比较通道D GPIO 初始化
  31.         RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);
  32.   GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH4_PIN;
  33.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  34.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  35.   GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
  36. }


  37. /* ----------------   PWM信号 周期和占空比的计算--------------- */
  38. // ARR :自动重装载寄存器的值
  39. // CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
  40. // PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
  41. // 占空比P=CCR/(ARR+1)

  42. static void GENERAL_TIM_Mode_Config(void)
  43. {
  44.   // 开启定时器时钟,即内部时钟CK_INT=72M
  45.         GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);

  46. /*--------------------时基结构体初始化-------------------------*/
  47.         // 配置周期,这里配置为100K
  48.         
  49.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  50.         // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
  51.         TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;        
  52.         // 驱动CNT计数器的时钟 = Fck_int/(psc+1)
  53.         TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;        
  54.         // 时钟分频因子 ,配置死区时间时需要用到
  55.         TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;               
  56.         // 计数器计数模式,设置为向上计数
  57.         TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;               
  58.         // 重复计数器的值,没用到不用管
  59.         TIM_TimeBaseStructure.TIM_RepetitionCounter=0;        
  60.         // 初始化定时器
  61.         TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);

  62.         /*--------------------输出比较结构体初始化-------------------*/        

  63. // 占空比配置, 这里可用于调节电机转速

  64.   uint16_t CCR1_Val = 7;
  65.         uint16_t CCR2_Val = 7;
  66.         uint16_t CCR3_Val = 7;
  67.         uint16_t CCR4_Val = 7;
  68.         
  69.         TIM_OCInitTypeDef  TIM_OCInitStructure;
  70.         // 配置为PWM模式1
  71.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  72.         // 输出使能
  73.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  74.         // 输出通道电平极性配置        
  75.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  76.         
  77.         // 输出比较通道 1
  78.         TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  79.         TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
  80.         TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
  81.         
  82.         // 输出比较通道 2
  83.         TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
  84.         TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
  85.         TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
  86.         
  87.         // 输出比较通道 3
  88.         TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
  89.         TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
  90.         TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
  91.         
  92.         // 输出比较通道 4
  93.         TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
  94.         TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
  95.         TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
  96.         
  97.         // 使能计数器
  98.         TIM_Cmd(GENERAL_TIM, ENABLE);
  99. }



  100. /************电机 A B C D 的IN输入函数初始化部分************/

  101. void Motor_Config(void)
  102. {
  103.         GPIO_InitTypeDef GPIO_InitStructure;   
  104.   RCC_APB2PeriphClockCmd( MOTOR_INA1_CLK|MOTOR_INA2_CLK|
  105.                                 MOTOR_INB1_CLK|MOTOR_INB2_CLK|
  106.                                 MOTOR_INC1_CLK|MOTOR_INC2_CLK|
  107.                                 MOTOR_IND1_CLK|MOTOR_IND2_CLK, ENABLE);  
  108.         GPIO_InitStructure.GPIO_Pin = MOTOR_INA1_PIN|MOTOR_INA2_PIN|
  109.                                       MOTOR_INB1_PIN|MOTOR_INB2_PIN|
  110.                                       MOTOR_INC1_PIN|MOTOR_INC2_PIN|
  111.                                       MOTOR_IND1_PIN|MOTOR_IND2_PIN;
  112.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
  113.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  114.         GPIO_Init(MOTOR_INA1_PORT, &GPIO_InitStructure);
  115.         GPIO_Init(MOTOR_INA2_PORT, &GPIO_InitStructure);
  116.         GPIO_Init(MOTOR_INB1_PORT, &GPIO_InitStructure);
  117.         GPIO_Init(MOTOR_INB2_PORT, &GPIO_InitStructure);
  118.         GPIO_Init(MOTOR_INC1_PORT, &GPIO_InitStructure);
  119.         GPIO_Init(MOTOR_INC2_PORT, &GPIO_InitStructure);
  120.         GPIO_Init(MOTOR_IND1_PORT, &GPIO_InitStructure);
  121.         GPIO_Init(MOTOR_IND2_PORT, &GPIO_InitStructure);
  122.         
  123. }

  124. void Motor_A_STOP(void)
  125. {
  126.         IN1(High);
  127.         IN2(High);
  128. }

  129. void Motor_A_PRun(void)
  130. {
  131.         IN1(Low);
  132.         IN2(High);
  133. }

  134. void Motor_A_NRun(void)
  135. {
  136.         IN1(High);
  137.         IN2(Low);
  138. }

  139. void Motor_B_STOP(void)
  140. {
  141.         IN3(High);
  142.         IN4(High);
  143. }

  144. void Motor_B_PRun(void)
  145. {
  146.         IN3(Low);
  147.         IN4(High);
  148. }

  149. void Motor_B_NRun(void)
  150. {
  151.         IN3(High);
  152.         IN4(Low);
  153. }

  154. void Motor_C_STOP(void)
  155. {
  156.         IN5(High);
  157.         IN6(High);
  158. }

  159. void Motor_C_PRun(void)
  160. {
  161.         IN5(Low);
  162.         IN6(High);
  163. }

  164. void Motor_C_NRun(void)
  165. {
  166.         IN5(High);
  167.         IN6(Low);
  168. }

  169. void Motor_D_STOP(void)
  170. {
  171.         IN7(High);
  172.         IN8(High);
  173. }

  174. void Motor_D_PRun(void)
  175. {
  176.         IN7(Low);
  177.         IN8(High);
  178. }

  179. void Motor_D_NRun(void)
  180. {
  181.         IN7(High);
  182.         IN8(Low);
  183. }

  184. /********小车前进后退和左右直走及停下函数部分——(麦克纳木轮排布方式为X型)*********/
  185. /********具体麦克纳木伦摆放方式可以看一下redame.txt文件********/

  186. //小车前进,ABCD电机正转
  187. void Car_Forward (void)
  188. {

  189.                 //A电机正转
  190.           Motor_A_PRun();
  191.                
  192.                 //B电机正转
  193.           Motor_B_PRun();
  194.         
  195.                 //C电机正转
  196.     Motor_C_PRun();
  197.                
  198.                 //D电机正转
  199.           Motor_D_PRun();
  200.         
  201.                
  202. }

  203. //小车后退,ABCD电机反转
  204. void Car_Back_Off (void)
  205. {

  206.                 //A电机反转
  207.                   Motor_A_NRun();
  208.                
  209.                 //B电机反转
  210.                   Motor_B_NRun();
  211.                
  212.                 //C电机反转
  213.             Motor_C_NRun();
  214.                
  215.                 //D电机反转
  216.                   Motor_D_NRun();
  217.         
  218. }

  219. //小车左直走,A,D电机反转,B,C电机正转
  220. void Car_Go_Straight_Left (void)
  221. {
  222.   
  223.                 //A电机反转
  224.           Motor_A_NRun();
  225.                
  226.                 //B电机正转
  227.           Motor_B_PRun();
  228.                
  229.                 //C电机正转
  230.     Motor_C_PRun();
  231.                
  232.                 //D电机反转
  233.           Motor_D_NRun();

  234. }

  235. //小车右直走,A,D电机正转,B,C电机反转
  236. void Car_Go_Straight_Right (void)
  237. {
  238.   
  239.                 //A电机正转
  240.            Motor_A_PRun();
  241.                
  242.                 //B电机反转
  243.           Motor_B_NRun();
  244.                
  245.                 //C电机反转
  246.      Motor_C_NRun();
  247.                
  248.                 //D电机正转
  249.            Motor_A_PRun();
  250.         
  251. }

  252. //小车停下,A,B,C,D电机都不转
  253. void Car_Stop (void)
  254. {
  255.   
  256.                 //A电机不转
  257.           Motor_A_STOP();
  258.                
  259.                 //B电机不转
  260.           Motor_B_STOP();
  261.                
  262.                 //C电机不转
  263.     Motor_C_STOP();
  264.                
  265.                 //D电机不转
  266.           Motor_D_STOP();
  267.         
  268.         
  269. }

  270. void GENERAL_TIM_Init(void)
  271. {
  272.         GENERAL_TIM_GPIO_Config();
  273.         GENERAL_TIM_Mode_Config();               
  274. }
复制代码
简单讲一下代码内容:使用的是四路通用计时器进行L298N的使能,然后再用IO输出信号,带动马达。(比较简单的原理)
再顺便附带一下头文件。
  1. #ifndef __MOTOR1_H
  2. #define __MOTOR1_H


  3. #include "stm32f10x.h"
  4. #include "stm32f10x_gpio.h"

  5. /************电机 A B C D 的使能输入PWM宏定义部分************/
  6. /************通用定时器TIM参数定义,只限TIM2、3、4、5********/

  7. // 当使用不同的定时器的时候,对应的GPIO是不一样的,可以自行更改
  8. // 我们这里使用的是TIM3,可以根据实际情况更改

  9. #define            GENERAL_TIM                   TIM3

  10. #define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
  11. #define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM3
  12. #define            GENERAL_TIM_Period            (10-1)
  13. #define            GENERAL_TIM_Prescaler         (72-1)
  14. //由于目前不知道PWM频率配置多少合适,所以这里暂时随便配置的一个数
  15. // 频率计算公式为: 72M / ARR*(PSC+1)
  16. //占空比计算公式为:CCR/(ARR+1)


  17. // TIM3 输出比较通道A
  18. #define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
  19. #define            GENERAL_TIM_CH1_PORT          GPIOA
  20. #define            GENERAL_TIM_CH1_PIN           GPIO_Pin_6

  21. // TIM3 输出比较通道B
  22. #define            GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
  23. #define            GENERAL_TIM_CH2_PORT          GPIOA
  24. #define            GENERAL_TIM_CH2_PIN           GPIO_Pin_7

  25. // TIM3 输出比较通道C
  26. #define            GENERAL_TIM_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
  27. #define            GENERAL_TIM_CH3_PORT          GPIOB
  28. #define            GENERAL_TIM_CH3_PIN           GPIO_Pin_0

  29. // TIM3 输出比较通道D
  30. #define            GENERAL_TIM_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
  31. #define            GENERAL_TIM_CH4_PORT          GPIOB
  32. #define            GENERAL_TIM_CH4_PIN           GPIO_Pin_1




  33. /************电机 A B C D 的IN输入函数初始化部分************/

  34. //TT_MOTOR  输出比较通道A
  35. #define MOTOR_INA1_PIN          GPIO_Pin_6              //定义输出位置宏,便于移植
  36. #define MOTOR_INA1_PORT         GPIOB                   //定义输出端口宏,便于移植
  37. #define MOTOR_INA1_CLK          RCC_APB2Periph_GPIOB   

  38. #define MOTOR_INA2_PIN          GPIO_Pin_7              //定义输出位置宏,便于移植
  39. #define MOTOR_INA2_PORT         GPIOB                   //定义输出端口宏,便于移植
  40. #define MOTOR_INA2_CLK          RCC_APB2Periph_GPIOB   

  41. //TT_MOTOR  输出比较通道B
  42. #define MOTOR_INB1_PIN          GPIO_Pin_8              //定义输出位置宏,便于移植
  43. #define MOTOR_INB1_PORT         GPIOB                   //定义输出端口宏,便于移植
  44. #define MOTOR_INB1_CLK          RCC_APB2Periph_GPIOB   

  45. #define MOTOR_INB2_PIN          GPIO_Pin_9              //定义输出位置宏,便于移植
  46. #define MOTOR_INB2_PORT         GPIOB                   //定义输出端口宏,便于移植
  47. #define MOTOR_INB2_CLK          RCC_APB2Periph_GPIOB   

  48. //TT_MOTOR  输出比较通道C
  49. #define MOTOR_INC1_PIN          GPIO_Pin_12             //定义输出位置宏,便于移植
  50. #define MOTOR_INC1_PORT         GPIOB                   //定义输出端口宏,便于移植
  51. #define MOTOR_INC1_CLK          RCC_APB2Periph_GPIOB   

  52. #define MOTOR_INC2_PIN          GPIO_Pin_13             //定义输出位置宏,便于移植
  53. #define MOTOR_INC2_PORT         GPIOB                   //定义输出端口宏,便于移植
  54. #define MOTOR_INC2_CLK          RCC_APB2Periph_GPIOB   

  55. //TT_MOTOR  输出比较通道D
  56. #define MOTOR_IND1_PIN          GPIO_Pin_14             //定义输出位置宏,便于移植
  57. #define MOTOR_IND1_PORT         GPIOB                   //定义输出端口宏,便于移植
  58. #define MOTOR_IND1_CLK          RCC_APB2Periph_GPIOB   

  59. #define MOTOR_IND2_PIN          GPIO_Pin_15             //定义输出位置宏,便于移植
  60. #define MOTOR_IND2_PORT         GPIOB                   //定义输出端口宏,便于移植
  61. #define MOTOR_IND2_CLK          RCC_APB2Periph_GPIOB   


  62. #define High    1
  63. #define Low     0

  64. #define IN1(a) if (a)  \
  65.         GPIO_SetBits(MOTOR_INA1_PORT,MOTOR_INA1_PIN );\
  66. else  \
  67.         GPIO_ResetBits(MOTOR_INA1_PORT,MOTOR_INA1_PIN)

  68. #define IN2(a) if (a)  \
  69.         GPIO_SetBits(MOTOR_INA2_PORT,MOTOR_INA2_PIN);\
  70. else  \
  71.         GPIO_ResetBits(MOTOR_INA2_PORT,MOTOR_INA2_PIN)

  72. #define IN3(a) if (a)  \
  73.         GPIO_SetBits(MOTOR_INB1_PORT,MOTOR_INB1_PIN);\
  74. else  \
  75.         GPIO_ResetBits(MOTOR_INB1_PORT,MOTOR_INB1_PIN)

  76. #define IN4(a) if (a)  \
  77.         GPIO_SetBits(MOTOR_INB2_PORT,MOTOR_INB2_PIN);\
  78. else  \
  79.         GPIO_ResetBits(MOTOR_INB2_PORT,MOTOR_INB2_PIN)


  80. #define IN5(a) if (a)  \
  81.         GPIO_SetBits(MOTOR_INC1_PORT,MOTOR_INC1_PIN);\
  82. else  \
  83.         GPIO_ResetBits(MOTOR_INC1_PORT,MOTOR_INC1_PIN)

  84. #define IN6(a) if (a)  \
  85.         GPIO_SetBits(MOTOR_INC2_PORT,MOTOR_INC2_PIN);\
  86. else  \
  87.         GPIO_ResetBits(MOTOR_INC2_PORT,MOTOR_INC2_PIN)

  88. #define IN7(a) if (a)  \
  89.         GPIO_SetBits(MOTOR_IND1_PORT,MOTOR_IND1_PIN);\
  90. else  \
  91.         GPIO_ResetBits(MOTOR_IND1_PORT,MOTOR_IND1_PIN)

  92. #define IN8(a) if (a)  \
  93.         GPIO_SetBits(MOTOR_IND2_PORT,MOTOR_IND2_PIN);\
  94. else  \
  95.         GPIO_ResetBits(MOTOR_IND2_PORT,MOTOR_IND2_PIN)


  96. static void GENERAL_TIM_GPIO_Config(void);
  97. static void GENERAL_TIM_Mode_Config(void);
  98. void GENERAL_TIM_Init(void);


  99. void Motor_Config(void);

  100. void Motor_A_STOP(void);
  101. void Motor_A_PRun(void);
  102. void Motor_A_NRun(void);

  103. void Motor_B_STOP(void);
  104. void Motor_B_PRun(void);
  105. void Motor_B_NRun(void);

  106. void Motor_C_STOP(void);
  107. void Motor_C_PRun(void);
  108. void Motor_C_NRun(void);

  109. void Motor_D_STOP(void);
  110. void Motor_D_PRun(void);
  111. void Motor_D_NRun(void);

  112. void Car_Forward (void);
  113. void Car_Back_Off (void);
  114. void Car_Go_Straight_Left (void);
  115. void Car_Go_Straight_Right (void);
  116. void Car_Stop (void);

  117. #endif
复制代码

主函数和那些延时函数什么的,可以根据个人兴趣爱好编写。
今天就说这些了,有什么不对的地方 欢迎各位大佬批评指正。
个人初次接触单片机,小白一枚。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表