/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
/* MAIN.C file
摘要:
1.PD7延时反转,指示系统工作。
2.上电,按指定PWM输出换相,实现电机基本运转功能。
3.换相依据为HALl信号,采用PORTD中断功能完成.
总之,上电根据HALL状态换相,并在输出PWM信号后,电机会转动,
同时HALL信号不断改变,然后进入捕获中断,进行及时换相。
如此实现电机的运转控制。
2013.5.8
*/
#include "stm8s.h"
#define STM8_FREQ_MHZ 16
#define PWM_FREQUENCY 16000
static const u16 hArrPwmVal = ((u16)((STM8_FREQ_MHZ * (u32)1000000)/PWM_FREQUENCY));
//PWM信号周期
#define PWMOUT 20
//按15%占空比输出
const unsigned char PWM_EN1_TAB[6]={0x00,0x00,0x10,0x10,0x01,0x01};
//六步法中,CH1\CH2通道极性及使能配置
const unsigned char PWM_EN2_TAB[6]={0x01,0x01,0x00,0x00,0x0,0x00};
//六步法中,CH3通道极性及使能配置
//上桥臂开关控制端口定义
#define MCO1_PORT GPIOC
#define MCO1_PIN GPIO_PIN_1
#define MCO3_PORT GPIOC
#define MCO3_PIN GPIO_PIN_2
#define MCO5_PORT GPIOC
#define MCO5_PIN GPIO_PIN_3
//下桥臂开关控制端口定义
#define MCO0_PORT GPIOB
#define MCO0_PIN GPIO_PIN_0
#define MCO2_PORT GPIOB
#define MCO2_PIN GPIO_PIN_1
#define MCO4_PORT GPIOB
#define MCO4_PIN GPIO_PIN_2
//下桥臂低电平开关管导通
#define PWM_A_OFF MCO0_PORT->ODR |= (u8)MCO0_PIN;
#define PWM_B_OFF MCO2_PORT->ODR |= (u8)MCO2_PIN;
#define PWM_C_OFF MCO4_PORT->ODR |= (u8)MCO4_PIN;
#define PWM_A_ON MCO0_PORT->ODR &= (u8)(~MCO0_PIN);
#define PWM_B_ON MCO2_PORT->ODR &= (u8)(~MCO2_PIN);
#define PWM_C_ON MCO4_PORT->ODR &= (u8)(~MCO4_PIN);
//霍尔引脚定义
#define H1_PORT GPIOD->IDR
#define H1_PIN BIT2
#define H2_PORT GPIOD->IDR
#define H2_PIN BIT3
#define H3_PORT GPIOD->IDR
#define H3_PIN BIT4
unsigned char bHallSteps[2][8]={
{7,5,3,4,1,0,2,7},//正转
{7,2,0,1,4,3,5,7}//反转
};
/* Private vars and define */
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//换相子函数声明
void Commutation(unsigned char bHallStartStep,unsigned int OutPwmValue);
unsigned int outpwm=0;
//初始化按键,指示灯端口
void GPIO_int(void)
{
/* LEDs */
GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_HIGH_FAST);
}
//系统时钟配置:内部16M
void Clock_init(void)
{
/* Select fCPU = 16MHz */
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
}
//换相电路开关管IO初始化
void PWM_IO_init(void)
{
//PB012 下桥臂0有效 ,配置为高电平
GPIO_Init(MCO0_PORT, MCO0_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(MCO2_PORT, MCO2_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(MCO4_PORT, MCO4_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
//PC123 上桥臂1有效,配置为低电平
GPIO_Init(MCO1_PORT, MCO1_PIN,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(MCO3_PORT, MCO3_PIN,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(MCO5_PORT, MCO5_PIN,GPIO_MODE_OUT_PP_LOW_FAST);
}
void Tim1_init(void)
{
/* TIM1 Peripheral Configuration */
TIM1_DeInit();
TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, hArrPwmVal, 0);
TIM1_OC1Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);
TIM1_OC2Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);
TIM1_OC3Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);
TIM1_CCPreloadControl(DISABLE);
TIM1_Cmd(ENABLE);
}
//初始化HALL捕获输入定义器,采用PD口外部中断捕获输入
void HALLEXTI_INIT(void)
{
GPIO_Init(GPIOD, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4,GPIO_MODE_IN_PU_IT); //HALL端口模式配置
}
//根据HALL状态换相,启动电机运行
void HALL_START(void)
{
u8 bHStatus = 0,bHallStartStep;
// Read status of H1
if (H1_PORT & H1_PIN)
{
bHStatus |= BIT2;
}
// Read status of H2
if (H2_PORT & H2_PIN)
{
bHStatus |= BIT1;
}
// Read status of H3
if (H3_PORT & H3_PIN)
{
bHStatus |= BIT0;
}
bHallStartStep = bHallSteps[1][bHStatus];//得到换相步序
if (bHallStartStep == 7)//不该出现的HALL状态
{
return;
}
GPIOD->CR2|=BIT3|BIT2|BIT4;
EXTI->CR1|=BIT6|BIT7;
Commutation(bHallStartStep,outpwm);//输出PWM信号,启动电机
}
@far@interruptvoid EXTI_PORTD_IRQHandler(void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
u8 bHStatus =0,i,bHallStartStep;
bHStatus=(GPIO_ReadInputData(GPIOD)>>2)&0x07;
for(i=0;i<50;i++);//滤波时间
i=(GPIO_ReadInputData(GPIOD)>>2)&0x07;
if(bHStatus!=i)return;
bHStatus=0;
// Read status of H1
if (H1_PORT & H1_PIN)
{
bHStatus |= BIT2;
}
// Read status of H2
if (H2_PORT & H2_PIN)
{
bHStatus |= BIT1;
}
// Read status of H3
if (H3_PORT & H3_PIN)
{
bHStatus |= BIT0;
}
bHallStartStep = bHallSteps[1][bHStatus];//得到换相步序
if (bHallStartStep == 7)
{ //故障,停止输出
TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM输出
PWM_A_OFF;
PWM_B_OFF;
PWM_C_OFF;
return;
}
EXTI->CR1|=BIT6|BIT7;
Commutation(bHallStartStep,outpwm);//输出PWM信号,启动电机
return;
}
void ChongD(void)
{
unsigned int tem_c=0;
PWM_A_ON;PWM_B_ON;PWM_C_ON;
for(tem_c=0;tem_c<50000;tem_c++);
PWM_A_OFF;PWM_B_OFF;PWM_C_OFF;
}
main()
{
unsigned int tem_c=0;
unsigned char step=0;
for(tem_c=0;tem_c<50000;tem_c++);//上电延时,等待系统稳定
Clock_init();//指示灯端口初始化
GPIO_int();//时钟配置
PWM_IO_init();//开关管控制端口初始化
Tim1_init();//高级定时器配置
HALLEXTI_INIT();//HALL端口初始化配置
ChongD();
outpwm=hArrPwmVal*PWMOUT/100;//固定占空比的PWM值
HALL_START();//根据HALL状态输出PWM状态,启动电机运行
enableInterrupts();
while (1);
{
for(tem_c=0;tem_c<50000;tem_c++);//延时时间
GPIO_WriteReverse(GPIOD,GPIO_PIN_7);//PD7指示灯反转
}
}
//换向输出PWM值,
//bHallStartStep:当前换相步序0-5,OutPwmValue 输出PWM值
void Commutation(unsigned char bHallStartStep,unsigned int OutPwmValue)
{
TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM输出
if(bHallStartStep!=3&&bHallStartStep!=4)
PWM_A_OFF;
if(bHallStartStep!=0&&bHallStartStep!=5)
PWM_B_OFF;
if(bHallStartStep!=1&&bHallStartStep!=2)
PWM_C_OFF;
//根据换相步序,打开不同的开关管,并施加正确的PWM信号
if(bHallStartStep==0)//AB
{
TIM1->CCR3H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR3L = (uint8_t)(OutPwmValue);
PWM_B_ON;
}
else if(bHallStartStep==1) //AC
{
TIM1->CCR3H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR3L = (uint8_t)(OutPwmValue);
PWM_C_ON;
}
else if(bHallStartStep==2) //BC
{
TIM1->CCR2H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR2L = (uint8_t)(OutPwmValue);
PWM_C_ON;
}
else if(bHallStartStep==3) //BA
{
TIM1->CCR2H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR2L = (uint8_t)(OutPwmValue);
PWM_A_ON;
}
else if(bHallStartStep==4)//CA
{
TIM1->CCR1H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR1L = (uint8_t)(OutPwmValue);
PWM_A_ON;
}
else if(bHallStartStep==5) //CB
{
TIM1->CCR1H = (uint8_t)(OutPwmValue >> 8);
TIM1->CCR1L = (uint8_t)(OutPwmValue);
PWM_B_ON;
}
TIM1->CCER1=PWM_EN1_TAB[bHallStartStep];
TIM1->CCER2=PWM_EN2_TAB[bHallStartStep];
TIM1->BKR|=TIM1_BKR_MOE;//使能PWM输出
}
#ifdef USE_FULL_ASSERT
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif