发新帖我要提问
123
返回列表
打印
[STM32F1]

利用STM32F103精确控制步进电机

[复制链接]
楼主: 欢乐家园
手机看帖
扫描二维码
随时随地手机跟帖
41
欢乐家园|  楼主 | 2022-8-22 23:54 | 只看该作者 回帖奖励 |倒序浏览
3.time.c程序
#include "timer.h"
/**************************
* 函数名:GPIO_Config
* 描述  :无
* 输入  :无
* 输出  :无
* 调用  :主函数
* 返回值:无
****************************/
void GPIO_Config(void)
{
                GPIO_InitTypeDef GPIO_InitStructure;
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
               
            /* Timer2 Channel 1, PA0 */
            GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_Init(GPIOA, &GPIO_InitStructure);
                 
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
                GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
                GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
                GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
                GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
                GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
       
         
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
                GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
               
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
                GPIO_Init(GPIOB, &GPIO_InitStructure);                   //
                GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
               
                //GPIO_ResetBits  GPIO_SetBits
}

//================================================================================
/**************************
* 函数名:TIM2_Master__TIM3_Slave_Configuration
* 描述  :主从定时器配置
* 输入  :电机转速speed,转角angle
* 输出  :无
* 调用  :主函数
* 返回值:无
****************************/
void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_OCInitTypeDef TIM_OCInitStructure;
       
        u16 nPDTemp ;
        u16 pulse_number;
        float p=PulseFrequency;
        TIM_Cmd(TIM2, DISABLE);
        nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)
        pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)
       
        // 时基配置:配置PWM输出定时器——TIM2
        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp
        TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
       
        // 输出配置:配置PWM输出定时器——TIM2
        /* PWM1 Mode configuration: Channel1 */   
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 1
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
        TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
        TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化
        TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器
        TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器
       
        // 时基配置:配置脉冲计数寄存器——TIM3
        TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
        // 输出配置:配置输出比较非主动模式定时器——TIM3
        // Output Compare Active Mode configuration: Channel1
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   
        TIM_OC1Init(TIM3, &TIM_OCInitStructure);

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

/****************************************************
* 函数名:Output_Pulse
* 描述  :无
* 输入  :无
* 输出  :无
* 返回值:无
******************************************************/
void Output_Pulse(u16 Num)
{
                GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
                TIM3->CCR1 = Num;
                TIM3->CNT = 0;
                TIM_Cmd(TIM3, ENABLE);
                TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
                TIM_Cmd(TIM2, ENABLE);
}

/****************************************************
* 函数名:angle_set
* 描述  :无
* 输入  :无
* 输出  :无
* 返回值:无
******************************************************/
void angle_set(u8 dir,u8 angle)
{
        if(dir==0)
                                GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
        else
                                GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
       
        Output_Pulse(angle*6400);
}

使用特权

评论回复
42
欢乐家园|  楼主 | 2022-8-22 23:55 | 只看该作者
4.time.h程序
#ifndef __TIMER_H
#define        __TIMER_H
#include "main.h"
extern unsigned char Flag;
extern unsigned char TIM2_Pulse_TIM3_Counter_OK;
void GPIO_Config(void);
void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);
void Frequence_Setting(u32 PulseFrequency);
void Output_Pulse(u16 Num);
void angle_set(u8 dir,u8 angle);
#endif

使用特权

评论回复
43
欢乐家园|  楼主 | 2022-8-22 23:56 | 只看该作者
5.usart1.c程序
#include <main.h>
#include <usart1.h>
#include <string.h>
#include <math.h>

/******************************************************
* 函数名:USART1_Config
* 描述  :USART1 GPIO 配置,工作模式配置
* 输入  :无
* 输出  : 无
* 调用  :外部调用
***************************************************** */
void USART1_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        /* config USART1 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

        /* USART1 GPIO config */
        /* Configure USART1 Tx (PA.09) as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);   
        /* Configure USART1 Rx (PA.10) as input floating */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        /* USART1 mode config */
        USART_InitStructure.USART_BaudRate = 115200;
        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(USART1, &USART_InitStructure);
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
       
        USART_Cmd(USART1, ENABLE);
}

/******************************************************
* 函数名:fputc
* 描述  :重定向c库函数printf到USART1
* 输入  :无
* 输出  :无
* 调用  :由printf调用
***************************************************** */
int fputc(int ch, FILE *f)
{
        /* 将Printf内容发往串口 */
        USART_SendData(USART1, (unsigned char) ch);
        while (!(USART1->SR & USART_FLAG_TXE));
       
        return (ch);
}

/*-------------------------------------------------------------------------------*/
/******************************************************
* 函数名:USART1_IRQHandler
* 描述  :USART1中断服务函数
* 输入  :无
* 输出  :无
* 调用  :中断调用
***************************************************** */
u8 Res;
extern int a;
u16 USART_RX_STA=0;       //接收状态标记         
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
void USART1_IRQHandler(void)                        //串口1中断服务程序
        {
               
                Res =USART_ReceiveData(USART1);        //读取接收到的数据
               
                if((USART_RX_STA&0x8000)==0)//接收未完成
                        {
                        if(USART_RX_STA&0x4000)//接收到了0x0d
                                {
                                if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else USART_RX_STA|=0x8000;        //接收完成了
                                }
                        else //还没收到0X0D
                                {       
                                if(Res==0x0d)USART_RX_STA|=0x4000;
                                else
                                        {
                                        USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
                                        }                 
                                }
                        }               
                                a=1;         
        }
#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntExit();                                                                                           
#endif

/******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/

使用特权

评论回复
44
欢乐家园|  楼主 | 2022-8-22 23:56 | 只看该作者
6.usart1.h程序
#ifndef __USART1_H
#define        __USART1_H
#include <main.h>
#include <stdio.h>

#define USART_REC_LEN                          200          //定义最大接收字节数 200
#define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA;                         //接收状态标记
int simple_atoi(char *source);
void USART1_Config(void);
#endif /* __USART1_H */

使用特权

评论回复
45
欢乐家园|  楼主 | 2022-8-22 23:57 | 只看该作者
源代码:
链接:https://pan.baidu.com/s/1PkmxkoeHfSfX06Gnj4Dr3A
提取码:eas7

使用特权

评论回复
46
Uriah| | 2022-9-30 09:30 | 只看该作者

紫外光复位保护电路是不行的

使用特权

评论回复
47
Bblythe| | 2022-9-30 12:29 | 只看该作者

让尽可能多的变量使用直接寻址,提高速度

使用特权

评论回复
48
万图| | 2022-12-25 08:27 | 只看该作者

STM32芯片中有多个工作时钟源的外设很常见

使用特权

评论回复
49
帛灿灿| | 2022-12-25 11:26 | 只看该作者

需要将阻焊漆(阻焊油墨)覆盖在最外层的PCB设计布线上

使用特权

评论回复
50
Bblythe| | 2022-12-25 12:29 | 只看该作者

让尽可能多的变量使用直接寻址,提高速度

使用特权

评论回复
51
周半梅| | 2022-12-25 14:25 | 只看该作者

要将多余空间去除。对于第一个字符从第一行开始向下扫描,把那些一行中所有的点的灰度值全为0的点去掉,直到扫描到有一行不全为0时为止。

使用特权

评论回复
52
Pulitzer| | 2022-12-25 15:28 | 只看该作者

每个Strategy交由Spring管理,并在构造后注册

使用特权

评论回复
53
童雨竹| | 2022-12-25 17:24 | 只看该作者

标志寄存器用于反应处理器的状态和运算结果的某些特征以及控制指令的执行。

使用特权

评论回复
54
Wordsworth| | 2022-12-25 18:27 | 只看该作者

硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则