czvmkl
发表于 2020-9-19 08:07
驱动和控制是分开的,驱动板上接口都用排针引出,可以和其他各种STM32板子连接,灵活性很高
wuweigong
发表于 2020-9-20 09:05
谢谢楼主的无私奉献!
czvmkl
发表于 2020-9-20 13:28
接着17楼 第二个文件 stm32f10x_it.c
/******************************************************************************
* File Name : stm32f10x_it.c
* Author : MCD Application Team
* Version : V3.5.0
* Date : 18-August-2020
* @brief Main Interrupt Service Routines.主中断服务程序
******************************************************************************/
/*Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "stdbool.h"
bool Direction;
u16 Hall;
u16 time=0;
extern u16 motor_statue;
u16 My_PWM=1000;
int aim_speed;
/******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers */
/******************************************************************************/
void Hall_SW(void) //六步换向函数
{ motor_statue=1;
switch(Hall)
{ case 5:
/* Next step: Step 2 Configuration --------i-------------------- */
/* Channel3 configuration */
TIM1->CCR2=0; //AB电机UV线通
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
case 1:
/* Next step: Step 3 Configuration ---------------------------- */
/* Channel2 configuration */
TIM1->CCR2=0; //AC电机UW线通
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 3:
/* Next step: Step 4 Configuration ---------------------------- */
TIM1->CCR1=0; //BC 电机VW线通
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 2:
/* Next step: Step 5 Configuration ---------------------------- */
TIM1->CCR1=0; //BA 电机VU线通
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 6:
/* Next step: Step 6 Configuration ---------------------------- */
TIM1->CCR2=0;//CA 电机WU线通
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 4:
/* Next step: Step 1 Configuration ---------------------------- */
TIM1->CCR2=0; //CB 电机WV线通
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
default:
/* Next step: Step 1 Configuration ---------------------------- */
/* Channel1 configuration */
break;
}
}
void EXTI9_5_IRQHandler(void)//引脚中断进行换向
{
Hall=GPIO_ReadInputData(GPIOB); //读取引脚值
Hall=Hall&0x01c0;
Hall=Hall>>6;
if(!Direction)Hall=7-Hall; //反方向处理
Hall_SW();
if(EXTI_GetITStatus(EXTI_Line6)!= RESET)
{
EXTI_ClearITPendingBit(EXTI_Line6);
}
if(EXTI_GetITStatus(EXTI_Line7)!= RESET)
{
EXTI_ClearITPendingBit(EXTI_Line7);
}
if(EXTI_GetITStatus(EXTI_Line8)!= RESET)
{
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
void TIM2_IRQHandler(void)//TIM2中断函数
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
time++;
}
}
czvmkl
发表于 2020-9-21 18:34
第三个C文件 TIM1.c 高级定时器TIM1初始化配置
#include "stm32f10x.h"
#define CKTIM ((u32)72000000uL) //系统主频宏定义 72MHz
#define PWM_PRSC ((u8)0)//预分频值宏定义
#define PWM_FREQ ((u16) 14400) // 计数模式中央对齐时PWM为14.4KHz
#define PWM_PERIOD ((u16) (CKTIM / (u32)(2 * PWM_FREQ *(PWM_PRSC+1)))) //自动重载值宏定义
#define REP_RATE (0) //重复计数器寄存值宏定义
void TIM1_Configuration1(void)
{ TIM_TimeBaseInitTypeDef TIM1_TimeBaseStructure;
TIM_OCInitTypeDef TIM1_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM1时钟使能
TIM_DeInit(TIM1); //复位TIM1定时器
/*TIM1初始化配置*/
TIM1_TimeBaseStructure.TIM_Period=PWM_PERIOD;//设置自动重载寄存器值为2500
TIM1_TimeBaseStructure.TIM_Prescaler=0x0; //设置预分频为0,不分频
TIM1_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV2;//设置时钟分割
TIM1_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数方向向上计数
TIM1_TimeBaseStructure.TIM_RepetitionCounter=REP_RATE;//设置重复计数器寄存值为0
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);//根据上面指定参数对TIM1初始化配置
TIM_OCStructInit(&TIM1_OCInitStructure);//把TIM定时器输出通道初始化为默认值,互补通道是关闭的
/*TIM1的通道1,2,3的PWM模式初始化配置*/
TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出为PWM调制模式1
TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM1_OCInitStructure.TIM_Pulse = 0x505; //设置捕获比较寄存器值1285
TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM1_OCInitStructure); //初始化TIM1_CH1
TIM_OC2Init(TIM1, &TIM1_OCInitStructure); //初始化TIM1_CH2
TIM_OC3Init(TIM1, &TIM1_OCInitStructure); //初始化TIM1_CH3
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//TIM1_CH1预装载使能
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//TIM1_CH2预装载使能
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);//TIM1_CH3预装载使能
/* 使能启动TIM1定时器*/
TIM_ARRPreloadConfig(TIM1, ENABLE);//使能TIM1在ARR上的预装载寄存器
TIM_CtrlPWMOutputs(TIM1, DISABLE); //关闭TIM1的PWM输出
TIM_Cmd(TIM1, DISABLE); //开启TIM1定时器
}
czvmkl
发表于 2020-9-22 19:30
第四个C文件 TIM2.c: //定时器TIM2的初始化配置
#include "stm32f10x.h"
void TIM2_Configuration1(void)
{ TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//TIM2时钟使能
TIM_DeInit( TIM2);//复位TIM2定时器
/* TIM2初始化配置*/
TIM_TimeBaseStructure.TIM_Period=9; //设置自动装载寄存器值为9
TIM_TimeBaseStructure.TIM_Prescaler=3599;// 72M/(3599+1)/10=2KHz,以2K的频率产生中断
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;// 时钟分割
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数方向向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM2待处理标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能TIM2更新中断
TIM_Cmd(TIM2, ENABLE);//使能启动TIM2定时器
}
czvmkl
发表于 2020-10-3 08:46
国庆假期终于可以更新一下贴子了
czvmkl
发表于 2020-10-5 18:22
主程序main.c里面的个while大循环
while (1)
{
keytemp= key_con();//按键读取
if(keytemp==1) //启动
{
flag=!flag; //WK_UP一键启动停止
if(flag==1)
{TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
startcnt=0;}
else {TIM_Cmd(TIM1, DISABLE);
TIM_CtrlPWMOutputs(TIM1, DISABLE);}
}
if(keytemp==2) //停止
{
TIM_Cmd(TIM1, DISABLE);
TIM_CtrlPWMOutputs(TIM1, DISABLE);
}
if(keytemp==3)//速度加
{
if(time >100)
{
if(aim_speed <5000)
aim_speed+=10;
time =0;
}
}
else if(keytemp==4)//速度减
{
if(time>100)
{
if(aim_speed >200 )
aim_speed-=10;
time=0;
}
}
if(startcnt<36)//换相6次后启动
{
if(time>10)
{
Hall_SW();
Hall++;
if( Hall>6)
Hall=1;
time=0;
}
startcnt++;
}
else
{
startcnt=37;
for(i=0;i<100000;i++);
My_PWM = aim_speed;
}
}
czvmkl
发表于 2020-10-5 18:28
本帖最后由 czvmkl 于 2020-10-5 18:32 编辑
还有几个main函数里需要调用的函数,有感按键调速的程序都已经上传了,大家慢慢享用
void SysTick_Init(u8 SYSCLK) //SysTick初始化函数
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8; //SYSCLK的8分频 保存1us所需的计数次数
fac_ms=(u16)fac_us*1000; //1ms 需要计数的次数
}
void delay_ms(u16 nms) //利用SysTick自定义的延时毫秒函数
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; // nms毫秒需要装载的寄存器值 最大1864ms
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL=0x01; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~0x01; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
/*******************************************************************************
扫描按键,读取按键参数的函数
*******************************************************************************/
u8 key_con(void)
{ static u8 key;
key=0;
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))//如果按下WK_UP键,返回键值1 启停电机
{delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
{while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1);//等待WK_UP键松开
key=1;}
}
if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0))//如果PC0接地,返回键值2 电机停转
{ key=2;
}
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15))//如果按下KEY1键,返回键值3 电机加速
{ key=3;
}
if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5))//如果按下KEY0键,返回键值4 电机减速
{ key=4;
}
if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13))//如果PC13接地电机反转
{ Direction=1;
}
else Direction=0;
return key;
}
/*******************************************************************************
GPIO端口初始化函数
*******************************************************************************/
void GPIO_Configuration(void)
{ GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*配置5个按键端口*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD ,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_5|GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//IO口上拉输入
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//IO口下拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //配置wk_up键控制电机启停
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//IO口上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //配置KEY1加速按键
/* 配置Hall接口IO */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//IO口浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*霍尔信号线外部中断配置*/
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);//设置PB6与EXTI6中断线连接
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource7);//设置PB7与EXTI7中断线连接
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8);//设置PB8与EXTI8中断线连接
EXTI_InitStructure.EXTI_Line = EXTI_Line6|EXTI_Line7|EXTI_Line8;//待配置的中断线标号为6,7,8
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//上升沿和下降沿响应中断请求
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能中断线EXTI_Line6~8
EXTI_Init(&EXTI_InitStructure);
/*PA8,PA9,PA10为上半桥臂端口配置*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9 | GPIO_Pin_10 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*PB13,PB14,PB15 为下半桥臂端口配置*/
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
NVIC中断管理配置初始化函数
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//设置中断优先级分组值为1,即1位抢占式3位响应式
/*初始化霍尔中断优先级*/
NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;//设置中断通道为EXTI9_5(霍尔)
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; //响应优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能IRQ通道
NVIC_Init(&NVIC_InitStructure);
/*初始化TIM2中断优先级*/
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; //TIM2中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; //响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能TIM2中断
NVIC_Init(&NVIC_InitStructure);
}
czvmkl
发表于 2020-10-12 06:35
本帖最后由 czvmkl 于 2020-10-12 06:42 编辑
整合一下上面的原理图
liucw2056
发表于 2020-10-14 08:44
感谢分享!!很好的教程
czvmkl
发表于 2020-10-14 12:16
liucw2056 发表于 2020-10-14 08:44
感谢分享!!很好的教程
{:1_492:} {:1_492:}
guistar1983
发表于 2020-10-14 19:09
感谢楼主分享教程!也准备学习一点电子基础知识。感觉要花不少时间。
czvmkl
发表于 2020-10-14 19:23
无刷驱动技术也就是一层窗户纸, 不要怕,突破他就行了
czvmkl
发表于 2020-10-18 15:25
本帖最后由 czvmkl 于 2020-10-18 15:40 编辑
再来一个无刷驱动的电位器调速程序
(程序含详细注释)
czvmkl
发表于 2020-10-25 10:29
本帖最后由 czvmkl 于 2020-10-25 10:56 编辑
与程序配套的实物板子,主控用的STM32F103RCT6(原子哥的MINI STM32开发板做主控)
Gaven
发表于 2020-11-9 18:32
eem228eem228eem228
czvmkl
发表于 2020-12-7 19:49
Gaven 发表于 2020-11-9 18:32
顶起来 .
czvmkl
发表于 2020-12-25 14:47
本帖最后由 czvmkl 于 2020-12-25 16:11 编辑
再看一下无刷旋转六步换相过程1 AB通电, 2 AC通电
czvmkl
发表于 2020-12-25 16:16
3 BC通电, 4 BA通电
czvmkl
发表于 2020-12-25 16:23
5 CA通电, 6 CB通电