金牌会员
- 积分
- 2876
- 金钱
- 2876
- 注册时间
- 2016-7-17
- 在线时间
- 404 小时
|
楼主 |
发表于 2017-1-6 08:32:30
|
显示全部楼层
[mw_shl_code=applescript,true]/*********************************************************************
GPIOA0-7显示a-dp,PC14=N1,PC15=N2,PB2=N3,PB12=N4,PB9=N5
1=ON,0=OFF
使用8MHzHSI,其它频率请自己修改时间设定
*********************************************************************/
#include "stm32f10x.h"
#define H_on //定义工作方式H-on L-on,否则为H-pwm L-on
/*延时函数**************************************/
void delay(unsigned int i) //50对应27us,100对应52us,250对应127us,500对应252us,1000对应502us,10000对应5ms,100000对应50ms
{
for(;i!=0;i--);
}
unsigned int step,cycle,cc[61]={0},rr1=0;
#ifdef H_on
//H-on L-pwm方式***********************************************************************************************************************
void TIM4_IRQHandler(void) //中断函数中实现延时换相
{
unsigned int k,j,zc=0;
switch(step) //工作顺序step 23(UW)-11(VW)-33(VU)-21(WU)-13(WV)-31(UV)
{
case 11:k=TIM4->CCR1;for(j=0;j<20;j++){if(GPIOB->IDR&0x0040)zc++;};break;
case 13:k=TIM4->CCR1;for(j=0;j<20;j++){if(!(GPIOB->IDR&0x0040))zc++;};break;
case 21:k=TIM4->CCR2;for(j=0;j<20;j++){if(GPIOB->IDR&0x0080)zc++;};break;
case 23:k=TIM4->CCR2;for(j=0;j<20;j++){if(!(GPIOB->IDR&0x0080))zc++;};break;
case 31:k=TIM4->CCR3;for(j=0;j<20;j++){if(GPIOB->IDR&0x0100)zc++;};break;
case 33:k=TIM4->CCR3;for(j=0;j<20;j++){if(!(GPIOB->IDR&0x0100))zc++;};break;
}
if(zc>=18) //连续检测到多次过零为真实过零,否则退出
{
if(k>cc[0]) //周期等于两次过零的间隔
zc=k-cc[0]; //计算过零时间间隔
else
zc=65536-cc[0]+k;
cc[0]=k; //cc[0]记录本次过零捕获CCR值,准备下次使用
//PA15、PB3、4、5可用,对应S7、8、9
j=TIM1->CCR1; //读当前占空比
if(!j) //如果j=0接着读,直到读到有效值
j=TIM1->CCR2;
if(!j)
j=TIM1->CCR3;
GPIOA->BSRR|=1<<15; //GPIOA_Pin15置为高电平
rr1++;
if(rr1>6) //对占空比变化速度加以限制
{
if((GPIOB->IDR&1<<3)&&(j<500))
j++; //S7键加占空比
if((GPIOB->IDR&1<<5)&&(j>40))
j--; //S9键减占空比
if(j<40)
j++;
rr1=0;
}
//发生过零捕获后应等待30度再换相,即两次捕获时间间隔的一半
if(zc<1600) //过零间隔小于1600(转速高于约300rpm)才延时,否则过零直接换相
{
k=zc/2;
if(k>20) //k小于等于20不延时
{
TIM2->PSC=79;
TIM2->ARR=k-20; //延时减去200usRC延迟
TIM2->CR1=9; //启动TIM2,单次工作
while(!TIM2->SR); //等待溢出
TIM2->SR=0; //清除标志
}
}
switch(step) //工作顺序step (UV)23-(UW)11-(VW)33-(VU)21-(WU)13-(WV)31
{
case 11:GPIOA->BRR|=1<<8;GPIOA->BSRR|=1<<9;TIM4->CCER=0x0300;step=33;break;
case 13:TIM1->CCR1=0;TIM1->CCR2=j;TIM4->CCER=0x0100;step=31;break;
case 21:GPIOA->BRR|=1<<9;GPIOA->BSRR|=1<<10;TIM4->CCER=0x0003;step=13;break;
case 23:TIM1->CCR2=0;TIM1->CCR3=j;TIM4->CCER=0x0001;step=11;break;
case 31:GPIOA->BRR|=1<<10;GPIOA->BSRR|=1<<8;TIM4->CCER=0x0030;step=23;break;
case 33:TIM1->CCR3=0;TIM1->CCR1=j;TIM4->CCER=0x0010;step=21;break;
}
for(j=1;j<60;j++) //原过零间隔记录向后移动一次,去除最高位,为新cc[1]留出位置,计算平均转速
{
cc[j+1]=cc[j];
}
cc[1]=zc;
cycle=cc[1];
for(j=2;j<61;j++)
{
cycle+=cc[j];
}
cycle/=60;
}
TIM4->SR=0;
}
#else
//H-pwm L-on方式********************************************************************************************************************
void TIM4_IRQHandler(void)
{
unsigned int k;
switch(step) //工作顺序step 23(UW)-11(VW)-33(VU)-21(WU)-13(WV)-31(UV)
{
case 11:k=TIM4->CCR1;break;
case 13:k=TIM4->CCR1;break;
case 21:k=TIM4->CCR2;break;
case 23:k=TIM4->CCR2;break;
case 31:k=TIM4->CCR3;break;
case 33:k=TIM4->CCR3;break;
}
if(k>cc1) //周期等于两次过零的差值
cycle=k-cc1; //计算过零时间间隔
else
cycle=65536-cc1+k;
cc1=k; //记录本次过零时间
//发生过零捕获后应等待30度再换相,即两次捕获时间间隔的一半
if(cycle<1600) //cycle大于等于1600(转速低于300rpm)直接换向,转速高时才延时
{
k=cycle/2;
if(k>20) //k小于等于20不延时
{
TIM2->PSC=79;
TIM2->ARR=k-20; //延时减去200usRC延迟
TIM2->CR1=9; //启动TIM2,单次工作
while(!TIM2->SR); //等待溢出
// TIM2->CR1=0; //停止TIM2
// TIM2->EGR=1;
TIM2->SR=0; //清除标志
}
}
switch(step) //工作顺序step 23(UW)-11(VW)-33(VU)-21(WU)-13(WV)-31(UV)
{
case 11:TIM1->CCER&=!1;TIM1->CCER|=1<<4;TIM4->CCER=0x0300;step=33;break;
case 13:GPIOB->BSRR=1<<13;GPIOB->BRR =1<<14;TIM4->CCER=0x0100;step=31;break;
case 21:TIM1->CCER&=!1<<4;TIM1->CCER|=1<<8;TIM4->CCER=0x0003;step=13;break;
case 23:GPIOB->BSRR=1<<14;GPIOB->BRR =1<<15;TIM4->CCER=0x0001;step=11;break;
case 31:TIM1->CCER&=!1<<8;TIM1->CCER|=1;TIM4->CCER=0x0030;step=23;break;
case 33:GPIOB->BSRR=1<<15;GPIOB->BRR =1<<13;TIM4->CCER=0x0010;step=21;break;
}
// TIM4->EGR=1;
//PA15、PB3、4、5可用,对应S7、8、9
GPIOA->BSRR|=1<<15; //GPIOA_Pin15置为高电平
k=TIM1->CCR1;
rr1++;
if((rr1>=119)||(k<=150))
{
if((GPIOB->IDR&1<<3)&&(k<500))
k++; //S7键加占空比
if((GPIOB->IDR&1<<5)&&(k>50))
k--; //S9键减占空比
if(k<100)
k++;
TIM1->CCR1=k; //设置占空比
TIM1->CCR2=k; //设置占空比
TIM1->CCR3=k; //设置占空比
rr1=0;
}
TIM4->SR=0;
}
#endif
/*************************************************************************************************************
*************************************************主程序开始***************************************************
*************************************************************************************************************/
int main(void)
{
unsigned int k;
//初始设置
RCC->APB2ENR=0x0A1D; //开启TIM1和ADC1、GPIOA、B、C、AFIO时钟
RCC->APB2RSTR=0x0A1D; //复位
RCC->APB2RSTR=0; //复位结束
RCC->APB1ENR=0x00000005; //开启TIM2、4时钟
RCC->APB1RSTR=0x00000005; //复位
RCC->APB1RSTR=0; //复位结束
#ifdef H_on
//H-on L-owm方式
GPIOA->CRL=0x22222222; //设置PA0-7为推挽输出,速度2MHz
GPIOA->CRH=0x222AA222; //PA11、12为复用推挽输出,其余为推挽输出,速度2MHz
GPIOA->ODR=0x003F; //显示0,其余低电平
GPIOB->ODR=0x13C4; //PB3、4、5为下拉输入,PB6、7、8为上拉输入,PB2、9、12输出高电平
GPIOB->CRL=0x88888200; //设置PB0、1为模拟输入,PB2为推挽输出,速度2MHz,其余上下拉输入
GPIOB->CRH=0xAAA2DD28; //设置PB8上拉输入,PB9推挽输出,速度2MHz,PB10、11为复用OD输出,10MHz,PB12推挽输出,PB13-15复用推挽输出,速度2MHz
#else
//H-pwm L-on方式
GPIOA->CRL=0x22222222; //设置PA0-7为推挽输出,速度2MHz
GPIOA->CRH=0x244AAAAA; //设置PA8-12为复用推挽输出,PA15推挽输出,速度2MHz,其余输入
GPIOA->ODR=0x003F; //显示0,其余低电平
GPIOB->ODR=0xF3C4; //PB3、4、5为下拉输入,PB6、7、8为上拉输入,PB13、14、15输出高电平
GPIOB->CRL=0x88888200; //设置PB0、1为模拟输入,PB2为推挽输出,速度2MHz,PB3-5为上下拉输入,PB6-7为上下拉输入
GPIOB->CRH=0x2222DD28; //设置PB8上下拉输入,PB9推挽输出,速度2MHz,PB10、11为复用OD输出,10MHz,PB12-15推挽输出,速度2MHz
#endif
GPIOC->CRH=0x22844444; //设置PC13为上拉输入,PC14、15为推挽输出,速度2MHz,其余输入
GPIOC->ODR=0xE000; //PC13为上拉输入
//TIM1_CH1 =PA8 (U+),TIM1_CH2 =PA9 (V+),TIM1_CH3 =PA10(W+)
//TIM1_CH1N=PB13(U-),TIM1_CH2N=PB14(V-),TIM1_CH3N=PB15(W-)
//BEMF比较U=TIM4_CH3,V=TIM4_CH1,W=TIM4_CH2
#ifdef H_on
//**********************H-on L-pwm方式启动段********************************************************************************
TIM1->CCMR1=0x6060; //设置TIM1_CH1、CH2为PWM1模式
TIM1->CCMR2=0x0060; //设置TIM1_CH3为PWM1模式
TIM1->CCER=0x0CCC; //TIM1_OC1、2、3,高电平有效,OC1N、2N、3N低电平有效,开启OC1N、2N、3N输出
TIM1->ARR=499; //设置计数周期,频率16KHz
TIM1->CCR1=0; //设置启动最低占空比0%
TIM1->CCR2=0; //设置启动最低占空比0%
TIM1->CCR3=0; //设置启动最低占空比0%
TIM1->BDTR=0x8000; //TIM1主输出使能
TIM1->CR1|=1<<0; //启动TIM1,使得TIM1_CH1N、2N、3N输出高电平
//电机预定位,准备启动
TIM1->CCR1=69; //打开TIM_CH1NPWM,U-
GPIOA->BSRR|=1<<10; //GPIOA_Pin10高电平,打开W+,WU通电
delay(500000); //保持约250ms
TIM1->CCR1=0; //关闭TIM_CH1NPWM,关闭U-
delay(500000); //断电,保持约250ms
TIM1->CCR2=69; //打开TIM_CH2NPWM,打开V-,WV通电
delay(500000); //保持约250ms
GPIOA->BRR|=1<<10; //GPIOA_Pin10低电平,关闭W+
delay(200000); //断电,保持约100ms,电机定位
//启动和自由加速段,转速至当前最高速度80%以下,防止速度过快丢步
for(k=30000;k>20000;k-=200)
{
GPIOA->BSRR|=1<<8; //GPIOA_Pin8高电平,打开U+
delay(k); //UV通电
TIM1->CCR2=0; //关闭TIM_CH2NPWM,V-
TIM1->CCR3=69; //打开TIM_CH3NPWM,W-
delay(k); //UW通电
GPIOA->BRR|=1<<8; //GPIOA_Pin8低电平,关闭U+
GPIOA->BSRR|=1<<9; //GPIOA_Pin9高电平,V+
delay(k); //VW通电
TIM1->CCR3=0; //关闭TIM_CH3NPWM,W-
TIM1->CCR1=69; //打开TIM_CH1NPWM,U-
delay(k); //VU通电
GPIOA->BRR|=1<<9; //GPIOA_Pin8低电平,关闭V+
GPIOA->BSRR|=1<<10; //GPIOA_Pin10高电平,打开W+
delay(k); //WU通电
TIM1->CCR1=0; //关闭TIM_CH1NPWM,关闭U-
TIM1->CCR2=69; //打开TIM_CH2NPWM,V-
delay(k); //WV通电
GPIOA->BRR|=1<<10; //GPIOA_Pin10低电平,关闭W+
}
GPIOA->BSRR|=1<<8; //GPIOA_Pin8高电平,打开U+,UV通电
#else
//**********************H-pwm L-on方式启动段******************************************************
TIM1->CCMR1=0x6060; //设置TIM1_CH1、CH2为PWM1模式
TIM1->CCMR2=0x0060; //设置TIM1_CH3为PWM1模式
TIM1->CCER=0x0888; //TIM1_OC1、2、3,高电平有效,OCxN低电平有效,禁止输出
TIM1->ARR=499; //设置计数周期,频率16KHz
TIM1->CCR1=49; //设置启动最低占空比=10%
TIM1->CCR2=49; //设置启动最低占空比=10%
TIM1->CCR3=49; //设置启动最低占空比=10%
TIM1->BDTR=0x8000; //TIM1主输出使能
//电机预定位,准备启动
TIM1->CCER|=1<<8; //打开TIM_CH3PWM
TIM1->CR1|=1<<0; //启动TIM1
GPIOB->BRR=1<<13; //GPIOB_Pin13低电平,WU通电
delay(500000); //保持约250ms
GPIOB->BSRR=1<<13; //GPIOB_Pin13高电平
delay(500000); //断电,保持约250ms
GPIOB->BRR=1<<14; //GPIOB_Pin14低电平,WV通电
delay(500000); //保持约250ms
TIM1->CCER&=!1<<8; //关闭TIM1_CH3
delay(200000); //断电,保持约100ms,电机定位
//启动和自由加速段,转速至当前最高速度80%以下,防止速度过快丢步
for(k=30000;k>20000;k-=200)
{
TIM1->CCER|=1; //打开TIM_CH1
GPIOB->BRR=1<<14; //GPIOB_Pin14低电平
delay(k); //45000对应保持约45.2ms,221rpm,UV通电
GPIOB->BSRR =1<<14; //GPIOB_Pin14高电平
GPIOB->BRR=1<<15; //GPIOB_Pin15低电平
delay(k); //UW通电
TIM1->CCER&=!1; //关闭TIM1_CH1
TIM1->CCER|=1<<4; //打开TIM_CH2
delay(k); //VW通电
GPIOB->BSRR=1<<15; //GPIOB_Pin15高电平
GPIOB->BRR=1<<13; //GPIOB_Pin13低电平
delay(k); //VU通电
TIM1->CCER&=!1<<4; //关闭TIM1_CH2
TIM1->CCER|=1<<8; //打开TIM_CH3
delay(k); //WU通电
GPIOB->BSRR=1<<13; //GPIOB_Pin13高电平
GPIOB->BRR=1<<14; //GPIOB_Pin14低电平
delay(k); //WV通电
TIM1->CCER&=!1<<8; //关闭TIM1_CH3
}
TIM1->CCER|=1; //打开TIM1_CH1PWM,UV通电
#endif
//准备换向****************************************************************************************************************************
step=23; //设定工作状态标记
TIM4->CCMR1=0xF1F1; //允许CH1、2触发捕获,采样频率fSAMPLING=fDTS/32,N=8,每一个边沿都触发一次捕获
TIM4->CCMR2=0x00F1; //允许CH3触发捕获,采样频率fSAMPLING=fDTS/32,N=8,每一个边沿都触发一次捕获
TIM4->ARR=0xFFFF; //设置重装载值
TIM4->PSC=79; //TIM4预分频80
TIM4->DIER=0x000E; //允许TIM4_CH1、2、3捕获中断
NVIC->ISER[0]=0x40000000; //开启TIM4中断
TIM4->CCER=0x0030; //开启W相TIM4_CH2捕获,设定下降沿
TIM4->CR1=0x0201; //启动TIM4,采样频率tDTS=4*tCK_INT
//显示电机转速,只保留个位显示,防止显示错误*******************************************************************************************
GPIOC->BRR=1<<14; //关闭GPIOC_Pin14=N1
GPIOC->BRR=1<<15; //关闭GPIOC_Pin15=N2
GPIOB->BRR=1<<2; //关闭GPIOB_Pin2=N3
GPIOB->BRR=1<<12; //关闭GPIOB_Pin12=N4
AFIO->MAPR=0x02000000; //关闭JTAG-DP,保留SW-DP
while(1)
{
unsigned int zero,result,display[5];
result=500000/cycle; //实测周期变换为转速
for(k=0;k<5;k++) //16进制变为10进制
{
display[k]=result%10; //display[]得到result个位数
result/=10; //除以10并自动舍去小数位
}
for(k=0;k<5;k++) //10进制数转化为数码管段位
{switch(display[k])
{
case 0:display[k]=0x0000003F;break;
case 1:display[k]=0x00000006;break;
case 2:display[k]=0x0000005B;break;
case 3:display[k]=0x0000004F;break;
case 4:display[k]=0x00000066;break;
case 5:display[k]=0x0000006D;break;
case 6:display[k]=0x0000007D;break;
case 7:display[k]=0x00000007;break;
case 8:display[k]=0x0000007F;break;
case 9:display[k]=0x0000006F;break;
default:display[k]=0x00000071;
}
}
for(k=0;k<=20;k++) //防止示数抖动频繁,延长一个数据显示时间
{
if (display[4]!=0x0000003F) //最高位为0消隐
{
GPIOA->BRR|=0x0000007F; //关闭全部显示
GPIOA->BSRR|=display[4];
GPIOC->BSRR=1<<14; //开启GPIOC_Pin14=N1
delay(5000);
GPIOC->BRR=1<<14; //关闭GPIOC_Pin14=N1
zero=1; //最高位不为0
}
else zero=0; //最高位为0,消隐
if(zero||(display[3]!=0x3F)) //前一位消隐且本位为0消隐
{
GPIOA->BRR|=0x0000007F; //关闭全部显示
GPIOA->BSRR|=display[3];
GPIOC->BSRR=1<<15; //开启GPIOC_Pin15=N2
delay(5000);
GPIOC->BRR=1<<15; //关闭GPIOC_Pin15=N2
zero=1; //最高位不为0
}
else zero=0; //最高位为0,消隐
if(zero||(display[2]!=0x3F)) //前一位消隐且本位为0消隐
{
GPIOA->BRR|=0x0000007F; //关闭全部显示
GPIOA->BSRR|=display[2];
GPIOB->BSRR=1<<2; //开启GPIOB_Pin2=N3
delay(5000);
GPIOB->BRR=1<<2; //关闭GPIOB_Pin2=N3
zero=1; //最高位不为0
}
else zero=0; //最高位为0,消隐
if(zero||(display[1]!=0x3F)) //前一位消隐且本位为0消隐
{
GPIOA->BRR|=0x0000007F; //关闭全部显示
GPIOA->BSRR|=display[1];
GPIOB->BSRR=1<<12; //开启GPIOB_Pin12=N4
delay(5000);
GPIOB->BRR=1<<12; //关闭GPIOB_Pin12=N4
}
GPIOA->BRR|=0x0000007F; //关闭全部显示
GPIOA->BSRR|=display[0];
GPIOB->BSRR=1<<9; //开启GPIOB_Pin9=N5
delay(5000);
GPIOB->BRR=1<<9;
}
}
}
[/mw_shl_code] |
|