[STM32F1] 利用STM32F103精确控制步进电机

[复制链接]
2317|54
 楼主| 欢乐家园 发表于 2022-8-22 23:54 | 显示全部楼层
3.time.c程序
  1. #include "timer.h"
  2. /**************************
  3. * 函数名:GPIO_Config
  4. * 描述  :无
  5. * 输入  :无
  6. * 输出  :无
  7. * 调用  :主函数
  8. * 返回值:无
  9. ****************************/
  10. void GPIO_Config(void)
  11. {
  12.                 GPIO_InitTypeDef GPIO_InitStructure;
  13.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA
  14.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
  15.                
  16.             /* Timer2 Channel 1, PA0 */
  17.             GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
  18.             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出
  19.             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20.             GPIO_Init(GPIOA, &GPIO_InitStructure);
  21.                  
  22.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;
  23.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
  24.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
  25.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
  26.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
  27.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
  28.                 GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
  29.                 GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
  30.        
  31.          
  32.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  33.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式
  34.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
  35.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
  36.                
  37.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  38.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  39.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
  40.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
  41.                 GPIO_Init(GPIOB, &GPIO_InitStructure);                   //
  42.                 GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
  43.                
  44.                 //GPIO_ResetBits  GPIO_SetBits
  45. }

  46. //================================================================================
  47. /**************************
  48. * 函数名:TIM2_Master__TIM3_Slave_Configuration
  49. * 描述  :主从定时器配置
  50. * 输入  :电机转速speed,转角angle
  51. * 输出  :无
  52. * 调用  :主函数
  53. * 返回值:无
  54. ****************************/
  55. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse)
  56. {
  57.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  58.         TIM_OCInitTypeDef TIM_OCInitStructure;
  59.        
  60.         u16 nPDTemp ;
  61.         u16 pulse_number;
  62.         float p=PulseFrequency;
  63.         TIM_Cmd(TIM2, DISABLE);
  64.         nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)
  65.         pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)
  66.        
  67.         // 时基配置:配置PWM输出定时器——TIM2
  68.         /* Time base configuration */
  69.         TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp
  70.         TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz
  71.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响
  72.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
  73.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
  74.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  75.        
  76.         // 输出配置:配置PWM输出定时器——TIM2
  77.         /* PWM1 Mode configuration: Channel1 */   
  78.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 1
  79.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
  80.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
  81.         TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
  82.         TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化
  83.         TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器
  84.         TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器
  85.        
  86.         // 时基配置:配置脉冲计数寄存器——TIM3
  87.         TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     
  88.         TIM_TimeBaseStructure.TIM_Prescaler = 0;
  89.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  90.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  91.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  92.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  93.         // 输出配置:配置输出比较非主动模式定时器——TIM3
  94.         // Output Compare Active Mode configuration: Channel1
  95.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      
  96.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  97.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  98.         TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   
  99.         TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  100.         // 配置TIM2为主定时器
  101.         // Select the Master Slave Mode
  102.         TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能
  103.         // Master Mode selection  
  104.         TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出
  105.        
  106.         // 配置TIM3为从定时器
  107.         // Slave Mode selection: TIM3
  108.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式   TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能
  109.         TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源    TIM_TS_ITR1-TIM 内部触发 1
  110.         TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式   TIM_TS_ITR1-TIM 内部触发 1
  111.         TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3     TIM 捕获/比较 1 中断源          
  112.        
  113.         TIM_Cmd(TIM2, ENABLE);
  114.         TIM_Cmd(TIM3, ENABLE);
  115. }

  116. /****************************************************
  117. * 函数名:Output_Pulse
  118. * 描述  :无
  119. * 输入  :无
  120. * 输出  :无
  121. * 返回值:无
  122. ******************************************************/
  123. void Output_Pulse(u16 Num)
  124. {
  125.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
  126.                 TIM3->CCR1 = Num;
  127.                 TIM3->CNT = 0;
  128.                 TIM_Cmd(TIM3, ENABLE);
  129.                 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
  130.                 TIM_Cmd(TIM2, ENABLE);
  131. }

  132. /****************************************************
  133. * 函数名:angle_set
  134. * 描述  :无
  135. * 输入  :无
  136. * 输出  :无
  137. * 返回值:无
  138. ******************************************************/
  139. void angle_set(u8 dir,u8 angle)
  140. {
  141.         if(dir==0)
  142.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
  143.         else
  144.                                 GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
  145.        
  146.         Output_Pulse(angle*6400);
  147. }

 楼主| 欢乐家园 发表于 2022-8-22 23:55 | 显示全部楼层
4.time.h程序
  1. #ifndef __TIMER_H
  2. #define        __TIMER_H
  3. #include "main.h"
  4. extern unsigned char Flag;
  5. extern unsigned char TIM2_Pulse_TIM3_Counter_OK;
  6. void GPIO_Config(void);
  7. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);
  8. void Frequence_Setting(u32 PulseFrequency);
  9. void Output_Pulse(u16 Num);
  10. void angle_set(u8 dir,u8 angle);
  11. #endif
 楼主| 欢乐家园 发表于 2022-8-22 23:56 | 显示全部楼层
5.usart1.c程序
  1. #include <main.h>
  2. #include <usart1.h>
  3. #include <string.h>
  4. #include <math.h>

  5. /******************************************************
  6. * 函数名:USART1_Config
  7. * 描述  :USART1 GPIO 配置,工作模式配置
  8. * 输入  :无
  9. * 输出  : 无
  10. * 调用  :外部调用
  11. ***************************************************** */
  12. void USART1_Config(void)
  13. {
  14.         GPIO_InitTypeDef GPIO_InitStructure;
  15.         USART_InitTypeDef USART_InitStructure;
  16.        
  17.         /* config USART1 clock */
  18.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  20.         /* USART1 GPIO config */
  21.         /* Configure USART1 Tx (PA.09) as alternate function push-pull */
  22.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  23.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  24.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  25.         GPIO_Init(GPIOA, &GPIO_InitStructure);   
  26.         /* Configure USART1 Rx (PA.10) as input floating */
  27.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  28.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  29.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  30.        
  31.         /* USART1 mode config */
  32.         USART_InitStructure.USART_BaudRate = 115200;
  33.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  34.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  35.         USART_InitStructure.USART_Parity = USART_Parity_No ;
  36.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  37.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  38.         USART_Init(USART1, &USART_InitStructure);
  39.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  40.        
  41.         USART_Cmd(USART1, ENABLE);
  42. }

  43. /******************************************************
  44. * 函数名:fputc
  45. * 描述  :重定向c库函数printf到USART1
  46. * 输入  :无
  47. * 输出  :无
  48. * 调用  :由printf调用
  49. ***************************************************** */
  50. int fputc(int ch, FILE *f)
  51. {
  52.         /* 将Printf内容发往串口 */
  53.         USART_SendData(USART1, (unsigned char) ch);
  54.         while (!(USART1->SR & USART_FLAG_TXE));
  55.        
  56.         return (ch);
  57. }

  58. /*-------------------------------------------------------------------------------*/
  59. /******************************************************
  60. * 函数名:USART1_IRQHandler
  61. * 描述  :USART1中断服务函数
  62. * 输入  :无
  63. * 输出  :无
  64. * 调用  :中断调用
  65. ***************************************************** */
  66. u8 Res;
  67. extern int a;
  68. u16 USART_RX_STA=0;       //接收状态标记         
  69. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
  70. void USART1_IRQHandler(void)                        //串口1中断服务程序
  71.         {
  72.                
  73.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据
  74.                
  75.                 if((USART_RX_STA&0x8000)==0)//接收未完成
  76.                         {
  77.                         if(USART_RX_STA&0x4000)//接收到了0x0d
  78.                                 {
  79.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
  80.                                 else USART_RX_STA|=0x8000;        //接收完成了
  81.                                 }
  82.                         else //还没收到0X0D
  83.                                 {       
  84.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
  85.                                 else
  86.                                         {
  87.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  88.                                         USART_RX_STA++;
  89.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
  90.                                         }                 
  91.                                 }
  92.                         }               
  93.                                 a=1;         
  94.         }
  95. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  96.         OSIntExit();                                                                                           
  97. #endif

  98. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
 楼主| 欢乐家园 发表于 2022-8-22 23:56 | 显示全部楼层
6.usart1.h程序
  1. #ifndef __USART1_H
  2. #define        __USART1_H
  3. #include <main.h>
  4. #include <stdio.h>

  5. #define USART_REC_LEN                          200          //定义最大接收字节数 200
  6. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
  7. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
  8. extern u16 USART_RX_STA;                         //接收状态标记
  9. int simple_atoi(char *source);
  10. void USART1_Config(void);
  11. #endif /* __USART1_H */
 楼主| 欢乐家园 发表于 2022-8-22 23:57 | 显示全部楼层
源代码:
链接:https://pan.baidu.com/s/1PkmxkoeHfSfX06Gnj4Dr3A
提取码:eas7
Uriah 发表于 2022-9-30 09:30 | 显示全部楼层

紫外光复位保护电路是不行的
Bblythe 发表于 2022-9-30 12:29 | 显示全部楼层

让尽可能多的变量使用直接寻址,提高速度
万图 发表于 2022-12-25 08:27 | 显示全部楼层

STM32芯片中有多个工作时钟源的外设很常见
帛灿灿 发表于 2022-12-25 11:26 | 显示全部楼层

需要将阻焊漆(阻焊油墨)覆盖在最外层的PCB设计布线上
Bblythe 发表于 2022-12-25 12:29 | 显示全部楼层

让尽可能多的变量使用直接寻址,提高速度
周半梅 发表于 2022-12-25 14:25 | 显示全部楼层

要将多余空间去除。对于第一个字符从第一行开始向下扫描,把那些一行中所有的点的灰度值全为0的点去掉,直到扫描到有一行不全为0时为止。
Pulitzer 发表于 2022-12-25 15:28 | 显示全部楼层

每个Strategy交由Spring管理,并在构造后注册
童雨竹 发表于 2022-12-25 17:24 | 显示全部楼层

标志寄存器用于反应处理器的状态和运算结果的某些特征以及控制指令的执行。
Wordsworth 发表于 2022-12-25 18:27 | 显示全部楼层

硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部