BJX 302A BLDC驱动器——4外设应用程序

TIMER0  产生几个固定时基,后续程序使用,一定不能等待的方式做延时。

  1 void T0_IRQHandler(void) interrupt 1
  2 {
  3     TIMER0_CLR_INT_FLAG;          //清除定时器0中断标志
  4 
  5     //LED0 = ~LED0;       //取反LED0
  6     if(MotorState >= 2)   //换相计时
  7     {
  8       SwStepCounter();
  9     }
 10     Time10usFlg = 1;
 11     Cnt10us++;
 12     if(Cnt10us >= 100)
 13     {
 14       Cnt10us = 0;
 15       Time1msFlg = 1;
 16       Cnt1ms++;
 17       if(Cnt1ms >=10)
 18       {
 19         Cnt1ms = 0;
 20         Time10msFlg = 1;
 21         Cnt10ms++;
 22         if(Cnt10ms>= 10)
 23         {
 24           Cnt10ms = 0;
 25           Time100msFlg = 1;
 26           Cnt100ms++;
 27           if(Cnt100ms>=10)
 28           {
 29             Cnt100ms = 0;
 30             Time1sFlg = 1;
 31           }
 32         }
 33       }
 34     }
 35 }
 36 

GPIO 用于检测换档键和启动按键,

  1 void CheckSwIo(void)
  2 {
  3   if(!IoSpeed)     //速度检测   S2
  4   {
  5     if(SwCkSpeedCnt < 5)
  6     {
  7       SwCkSpeedCnt++;
  8     }
  9     if(SwCkSpeedCnt == 3)
 10     {
 11       SwPuse |= 0x01;
 12       //SwCkSpeedCnt
 13     }
 14   }
 15   else
 16   {
 17     SwCkSpeedCnt = 0;
 18   }
 19 
 20   if(!IoStart)       //启动检测   S1
 21   {
 22     if(SwCkStartCnt < 5)
 23     {
 24       SwCkStartCnt ++;
 25     }
 26     if(SwCkStartCnt == 3)
 27     {
 28       SwPuse |= 0x02;
 29     }
 30   }
 31   else
 32   {
 33     SwCkStartCnt = 0;
 34   }
 35 }

ADC 用于获取目标通道的ADC值,采用手动触发的方式,后续的无极调速和反电动势过零点检测都要使用这个函数

  1 /******************************************************************************
  2 * Function   :  ADC_HaveValuePro
  3 * Description:  获取AD值: 连续采集10次,去掉最大最小值后均值
  4 * Input      :  chn: 通道
  5 * Output     :  ad_value
  6 *******************************************************************************/
  7 sbit LED0 = P3^1;
  8 
  9 u16 ADC_OneChnValue16Pro(u8 chn)
 10 {
 11 //	u8 i;
 12 	u8 AD_H,AD_L;
 13 	u16	ad_value;
 14 	//u16 adsum=0;
 15 	//u16 admax=0x0000,admin=0xffff;
 16 
 17 	//6、选择相应信号的AD通道
 18 	ADCON0 &= ~(AINSL4 | 0x0F);
 19 	if (chn > 0x0F)
 20 	{
 21 		ADCON0 |= AINSL4 | (chn & 0x0F);
 22 	}
 23 	else
 24 	{
 25 		ADCON0 |= chn & 0x0F;
 26 	}
 27 
 28   LED0 = ~LED0;
 29 	//for(i=0;i<10;i++)
 30   //for(i=0;i<1;i++)
 31 	//{
 32 		ADC_START;
 33 		while(!(DRDY));   //等待AD转换完成
 34 		AD_L = ADDOL;     //读取AD数据
 35 		AD_H = ADDOH & 0x0F;
 36 		ADC_CLR_DRDY;
 37 		ad_value =(AD_H<<8)+ AD_L;
 38 		//
 39 //		if(admax<ad_value)
 40 //		{
 41 //			admax = ad_value;
 42 //		}
 43 //		else if(admin>ad_value)
 44 //		{
 45 //			admin = ad_value;
 46 //		}
 47 //		adsum+=ad_value;
 48 	//} 				
 49 	ADS=0;
 50 
 51 	//ad_value=(adsum-admax-admin)>>3;
 52   //ad_value=(adsum-admax-admin)>>1;
 53   LED0 = ~LED0;
 54 
 55 	return ad_value;
 56 }
 57 

这个ADC采样方式使用低通滤波,可以提高ADC采样精度。

  1 u16 ADC_HaveValue16Pro(u8 chn)
  2 {
  3 	u8 i;
  4 	u8 AD_H,AD_L;
  5 	u16	ad_value;
  6 	u16 adsum=0;
  7 	u16 admax=0x0000,admin=0xffff;
  8 
  9 	//6、选择相应信号的AD通道
 10 	ADCON0 &= ~(AINSL4 | 0x0F);
 11 	if (chn > 0x0F)
 12 	{
 13 		ADCON0 |= AINSL4 | (chn & 0x0F);
 14 	}
 15 	else
 16 	{
 17 		ADCON0 |= chn & 0x0F;
 18 	}
 19 
 20   LED0 = ~LED0;
 21 	for(i=0;i<10;i++)
 22   //for(i=0;i<1;i++)
 23 	{
 24 		ADC_START;
 25 		while(!(DRDY));   //等待AD转换完成
 26 		AD_L = ADDOL;     //读取AD数据
 27 		AD_H = ADDOH & 0x0F;
 28 		ADC_CLR_DRDY;
 29 		ad_value =(AD_H<<8)+ AD_L;
 30 		//
 31 		if(admax<ad_value)
 32 		{
 33 			admax = ad_value;
 34 		}
 35 		else if(admin>ad_value)
 36 		{
 37 			admin = ad_value;
 38 		}
 39 		adsum+=ad_value;
 40 	}
 41 	ADS=0;
 42 
 43 	ad_value=(adsum-admax-admin)>>3;
 44   //ad_value=(adsum-admax-admin)>>1;
 45   LED0 = ~LED0;
 46 
 47 	return ad_value;
 48 }

UART 串口world类型打印程序主要用来做程序调试

  1 void Uart_WriteWord(u16 dat)
  2 {
  3   if(UartCnt == 0)
  4   {
  5     fUartTxInt = 0;
  6     S0BUF = (u8)(dat>>8);
  7     UartCnt++;
  8   }
  9   else if(UartCnt == 1)
 10   {
 11     if(fUartTxInt)
 12     {
 13       fUartTxInt = 0;
 14       S0BUF = (u8)(dat);
 15       //UartCnt++;
 16       UartCnt= 0;
 17     }
 18   }
 19 //  else if(UartCnt == 2)
 20 //  {
 21 //    if(fUartTxInt)
 22 //    {
 23 //      fUartTxInt = 0;
 24 //      S0BUF = (u8)(10);
 25 //      UartCnt= 0;
 26 //    }
 27 //  }
 28 }

PWM 这用于给PWM通道赋值,输出对应目标占空比。

  1 void PwmDuty(u16 u,u16 v,u16 w)
  2 {
  3   T2D1H = U16_HI_BYTE(u);
  4   T2D1L = U16_LOW_BYTE(u);
  5   T2D2H = U16_HI_BYTE(v);
  6   T2D2L = U16_LOW_BYTE(v);
  7   T2D3H = U16_HI_BYTE(w);
  8   T2D3L = U16_LOW_BYTE(w);
  9 }

这个函数用于给PWM驱动电机时换相使用,上桥输出占空比,下桥输出100%.

  1 void SixStep(u8 StepValue)
  2 {
  3   switch(StepValue)
  4   {
  5     case 1: T2EN = 0;T2PWMCON1 = 0x04;T2PWMCON2 = 0x00;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x40; P1OE |= 0x40; TIMER2_ENABLE;break;   //UV  pwm1    P16
  6     case 2: T2EN = 0;T2PWMCON1 = 0x04;T2PWMCON2 = 0x00;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x20; P1OE |= 0x20; TIMER2_ENABLE;break;   //UW  PWM1    P15
  7     case 3: T2EN = 0;T2PWMCON1 = 0x00;T2PWMCON2 = 0x01;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x20; P1OE |= 0x20; TIMER2_ENABLE;break;   //VW  PWM2    P15
  8     case 4: T2EN = 0;T2PWMCON1 = 0x00;T2PWMCON2 = 0x01;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x80; P1OE |= 0x80; TIMER2_ENABLE;break;   //VU  PWM2    P17
  9     case 5: T2EN = 0;T2PWMCON1 = 0x00;T2PWMCON2 = 0x04;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x80; P1OE |= 0x80; TIMER2_ENABLE;break;   //WU  PWM3    P17
 10     case 6: T2EN = 0;T2PWMCON1 = 0x00;T2PWMCON2 = 0x04;SET_SFR_PAGE0;P1 &= 0x1f;P1OE&=0x1f;P1 |= 0x40; P1OE |= 0x40; TIMER2_ENABLE;break;   //WV  PWM3    P16
 11     default : break;
 12   }
 13 }
 14 
posted @ 2026-09-08 20:44  steven_lg  阅读(5)  评论(0)    收藏  举报